Advertisement
Guest User

LissRK4.py

a guest
Mar 31st, 2015
373
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.34 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. import sys, getopt
  4. from math import sin, cos, pi
  5.  
  6. ''' Plot a Lissajous figure, saving as PBM
  7.  
  8.    Written by PM 2Ring March 2009
  9.    2015.03.31 Updated to use approximately constant distance
  10.    between succesive points, using Runge-Kutta integration.
  11.  
  12.  
  13.    Parametric equations of a Lissajous figure:
  14.    x = cos(a*th), y = sin(b*th)
  15.  
  16.    Derivatives:
  17.    dx/dth = -a*sin(a*th), dy/dth = b*cos(b*th)
  18.  
  19.    Derivative squared of arc length wrt to th
  20.    (ds/dth)^2 = a^2*sin^2(a*th) + b^2*cos^2(b*th)
  21.  
  22.    v = ds/dt = ds/dth * dth/dt
  23.    dth/dt = v / (ds/dth)
  24.    th = integral(v / (ds/dth)) dt
  25.     = integral(v / sqrt(a^2*sin^2(a*th) + b^2*cos^2(b*th))) dt
  26. '''
  27.  
  28. class bitmap:
  29.     ''' Basic pixel array, with PBM output '''
  30.     def __init__(self, width, height):
  31.         self.width, self.height = width, height
  32.  
  33.         #Pixel buffer. 0=white, 1=black.
  34.         row = ['0']*width + ['\n']
  35.         self.pix = [row[:] for i in xrange(height)]
  36.  
  37.     #Put pixel in buffer.
  38.     def put(self, x, y, c=1):
  39.         self.pix[y][x] = '01'[c]
  40.  
  41.     def savepbm(self, fname):
  42.         with open(fname, 'w') as f:
  43.             f.write('P1\n%d %d\n' % (self.width, self.height))
  44.             #Technically, each row should be no more than 70 chars
  45.             for row in self.pix:
  46.                 #Space is permitted, but not required
  47.                 f.write(''.join(row))
  48.  
  49. def liss(a, b, speed, width, height, fname):
  50.     ''' Generate a Lissajous figure with approximately
  51.        constant distance between successive points
  52.        using Runge-Kutta integration
  53.    '''
  54.     #Pixel buffer
  55.     pix = bitmap(width, height)
  56.  
  57.     #Origin
  58.     ox, oy = width // 2, height // 2
  59.     rad = min(ox, oy) - 3
  60.  
  61.     def speedfunc(theta):
  62.         s = (a * sin(a * theta))**2 + (b * cos(b * theta))**2
  63.         return speed / (rad * s ** 0.5)
  64.  
  65.     maxtheta = 2. * pi
  66.     theta = 0.0
  67.     while theta < maxtheta:
  68.         x = rad * cos(a * theta)
  69.         y = rad * sin(b * theta)
  70.         pix.put(int(.5 + ox + x), int(.5 + oy + y))
  71.  
  72.         #Calculate Runge-Kutta 4 increments
  73.         k1 = speedfunc(theta)
  74.         k2 = speedfunc(theta + 0.5 * k1)
  75.         k3 = speedfunc(theta + 0.5 * k2)
  76.         k4 = speedfunc(theta + k3)
  77.  
  78.         dtheta = (k1 + 2.0 * k2 + 2.0 * k3 + k4) / 6.0
  79.         theta += dtheta
  80.  
  81.     pix.savepbm(fname)
  82.  
  83. def main():
  84.     #Default args
  85.     fname = 'liss.pbm'  #Bitmap filename.
  86.     width = 512
  87.     height = 512
  88.     xfreq = 3.0
  89.     yfreq = 2.0
  90.     speed = 1.0
  91.  
  92.     def usage():
  93.         s = """Plot a Lissajous figure, saving as PBM.
  94. Usage: %s [-h] [-x x_frequency=%3f] [-y y_frequency=%3f] [-s speed=%f]
  95. [-w width=%d] [-v vertical_height=%d] [-f filename='%s']"""
  96.         print s % (sys.argv[0], xfreq, yfreq, speed, width, height, fname)
  97.         raise SystemExit, 1
  98.  
  99.     try:
  100.         opts, args = getopt.getopt(sys.argv[1:], "hx:y:s:w:v:f:")
  101.     except getopt.GetoptError, e:
  102.         print e.msg
  103.         usage()
  104.  
  105.     for o, a in opts:
  106.         if o == "-h": usage()
  107.         elif o == "-x": xfreq = float(a)
  108.         elif o == "-y": yfreq = float(a)
  109.         elif o == "-s": speed = float(a)
  110.         elif o == "-w": width = int(a)
  111.         elif o == "-v": height = int(a)
  112.         elif o == "-f": fname = a
  113.  
  114.     liss(xfreq, yfreq, speed, width, height, fname)
  115.  
  116. if __name__ == "__main__":
  117.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement