Advertisement
Guest User

Untitled

a guest
Apr 23rd, 2019
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.96 KB | None | 0 0
  1. import numpy as np
  2. import math
  3. from PIL import Image, ImageDraw
  4. import animation
  5.  
  6. NUM_GENERATIONS = 13
  7. NUM_FRAMES = 64
  8.  
  9. def apply_l_system(tokens, rules):
  10. return [result_token for token in tokens for result_token in rules[token]]
  11.  
  12. def get_rotation_matrix(axis_name, theta):
  13. c = math.cos(theta)
  14. s = math.sin(theta)
  15. mats = {
  16. "x": [[1,0,0],[0,c,-s],[0,s,c]],
  17. "y": [[c,0,s],[0,1,0],[-s,0,c]],
  18. "z": [[c,-s,0],[s,c,0],[0,0,1]]
  19. }
  20. return np.array(mats[axis_name])
  21.  
  22. def chunk(seq, size):
  23. for i in range(0, len(seq), size):
  24. yield seq[i: i+size]
  25.  
  26. rules = {
  27. 'Fu': ('Fl', 'Lu'), 'Fd': ('Fr', 'Rd'), 'Fl': ('Fd', 'Dl'), 'Fr': ('Fu', 'Ur'),
  28. 'Bu': ('Br', 'Ru'), 'Bd': ('Bl', 'Ld'), 'Bl': ('Bu', 'Ul'), 'Br': ('Bd', 'Dr'),
  29. 'Uf': ('Ur', 'Rf'), 'Ub': ('Ul', 'Lb'), 'Ul': ('Uf', 'Fl'), 'Ur': ('Ub', 'Br'),
  30. 'Df': ('Dl', 'Lf'), 'Db': ('Dr', 'Rb'), 'Dl': ('Db', 'Bl'), 'Dr': ('Df', 'Fr'),
  31. 'Lf': ('Lu', 'Uf'), 'Lb': ('Ld', 'Db'), 'Lu': ('Lb', 'Bu'), 'Ld': ('Lf', 'Fd'),
  32. 'Rf': ('Rd', 'Df'), 'Rb': ('Ru', 'Ub'), 'Ru': ('Rf', 'Fu'), 'Rd': ('Rb', 'Bd')
  33. }
  34.  
  35. unit_vectors = {'F': (0, 0, 1), 'B': (0, 0, -1), 'U': (0, 1, 0), 'D': (0, -1, 0), 'L': (-1, 0, 0), 'R': (1, 0, 0), 'O': (0, 0, 0)}
  36.  
  37. #generate system
  38. s = ["Fu"]
  39. for _ in range(NUM_GENERATIONS):
  40. s = apply_l_system(s, rules)
  41.  
  42. #calculate direction and magnitude of each step in walk
  43. walk_steps = [(0,0,0)]
  44. for token in s:
  45. walk_steps.append(unit_vectors[token[0]])
  46.  
  47. #calculate coordinates of walk
  48. coords = np.cumsum(walk_steps, 0)
  49.  
  50. #rotate coordinates so it makes a complete revolution per cycle
  51. frame_coords = []
  52. print("Applying rotations to canonical coordinates.")
  53. for i in range(NUM_FRAMES):
  54. print(f"{i+1} / {NUM_FRAMES}")
  55. f = float(i) / NUM_FRAMES
  56. m = get_rotation_matrix("x", math.radians(-10))
  57. m = m @ get_rotation_matrix("y", f * 2 * math.pi)
  58. frame_coords.append(coords @ m.T)
  59.  
  60. #concatenate all frames and convert to pixel coordinates.
  61. all_coords = np.concatenate(frame_coords)
  62.  
  63. margin = 10
  64. total_size = 250
  65. operable_size = total_size - margin*2
  66.  
  67. #determine ratio between logical space and pixel space.
  68. left = min(all_coords[:,0])
  69. right = max(all_coords[:,0])
  70. top = min(all_coords[:,1])
  71. bottom = max(all_coords[:,1])
  72. ratio = max(right-left, bottom-top)/operable_size
  73. print(left, right, top, bottom)
  74.  
  75. all_coords = ((all_coords - [left, top, 0]) / ratio) + margin
  76.  
  77. #chunk into individual frames and render
  78. images = []
  79. print("Rendering frames.")
  80. for frame_idx, frame_coord in enumerate(chunk(all_coords, len(coords))):
  81. print(f"{frame_idx+1} / {NUM_FRAMES}")
  82. img = Image.new("RGB", (total_size, total_size), "white")
  83. draw = ImageDraw.Draw(img)
  84. for i in range(len(frame_coord)-1):
  85. x1,y1,_ = frame_coord[i]
  86. x2,y2,_ = frame_coord[i+1]
  87. draw.line((x1,y1,x2,y2), fill="black")
  88. images.append(img)
  89.  
  90. print("Creating gif.")
  91. animation.make_gif(images, delay=4)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement