-
Notifications
You must be signed in to change notification settings - Fork 0
/
functions.py
203 lines (159 loc) · 5.87 KB
/
functions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
import math
from scipy import misc
import glob
import zlib, struct
def png_pack(png_tag, data):
chunk_head = png_tag + data
return (struct.pack("!I", len(data)) +
chunk_head +
struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head)))
def write_png(buf, width, height):
""" buf: must be bytes or a bytearray in Python3.x,
a regular string in Python2.x.
"""
# reverse the vertical line order and add null bytes at the start
width_byte_4 = width * 4
raw_data = b''.join(b'\x00' + buf[span:span + width_byte_4]
for span in range((height - 1) * width_byte_4, -1, - width_byte_4))
return b''.join([
b'\x89PNG\r\n\x1a\n',
png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)),
png_pack(b'IDAT', zlib.compress(raw_data, 9)),
png_pack(b'IEND', b'')])
def saveAsPNG(array, filename):
if any([len(row) != len(array[0]) for row in array]):
raise ValueError, "Array should have elements of equal size"
#First row becomes top row of image.
flat = []; map(flat.extend, reversed(array))
#Big-endian, unsigned 32-byte integer.
buf = b''.join([struct.pack('>I', ((0xffFFff & i32)<<8)|(i32>>24) )
for i32 in flat]) #Rotate from ARGB to RGBA.
data = write_png(buf, len(array[0]), len(array))
f = open(filename, 'wb')
f.write(data)
f.close()
def arctan(y, x):
if y >= 0:
return 2*math.pi-math.atan2(y,x)
else:
return 0-math.atan2(y,x)
# radius = 400
# for r in range(radius):
# x = [[0xffFFFFFF for i in range(1000)] for j in range(1000)]
# for i in range(1000):
# for j in range(1000):
# dist = (i-500)**2+(j-500)**2
# if abs((r**2) - dist) <= 400:
# x[j][i] = 0xff000000
# saveAsPNG(x, "frame"+str(r)+".png")
def fracColor(x):
r,g,b = 0,0,0
if x <= 1.0/6:
r = 255
g = x*255*6
b = 0
elif x <= 2.0/6:
r = (1-6*(x-1.0/6))*255
g = 255
b = 0
elif x <= 3.0/6:
r = 0
g = 255
b = (x-2.0/6)*255*6
elif x <= 4.0/6:
r = 0
g = (1-6*(x-3.0/6))*255
b = 255
elif x <= 5.0/6:
r = (x-4.0/6)*255*6
g = 0
b = 255
else:
r = 255
g = 0
b = (1-6*(x-5.0/6))*255
r,g,b = int(r), int(g), int(b)
return 0xff000000+r*256*256+256*g+b
def parameterCurve(f, steps, thickness, startTime, endTime, numFrames): #f: [0,1]x[startTime, endTime] -> ([-500, 500]x[-500, 500])x[startTime, endTime]
canvas = [[0xffFFFFFF for i in range(1000)] for j in range(1000)]
t = startTime
frame = 0
while t < endTime:
s = 0
changes =[]
while s < 1:
center = f(s,t)
offset = f(s+.0005, t)
dx = offset[0] - center[0]
dy = offset[1]-center[1]
if dx**2 + dy**2 != 0:
dx, dy = dx/((dx**2+dy**2)**.5), dy/((dx**2+dy**2)**.5)
for q in range(-thickness, thickness):
changes.append((int(round(dx*q+center[1]))+500, int(round(-dy*q+center[0]))+500))
canvas[changes[-1][0]][changes[-1][1]] = fracColor(s)
s += 1/float(steps)
saveAsPNG(canvas, "frame"+str(frame)+".png")
print "Created frame", frame
for i in changes:
canvas[i[0]][i[1]] = 0xffFFFFFF
frame += 1
t += (endTime - startTime)/float(numFrames)
def traceCurve(f, numSteps, thickness, numFrames): #f: [0,1] -> ([-500, 500]x[-500, 500])x[startTime, endTime]
canvas = [[0xffFFFFFF for i in range(1000)] for j in range(1000)]
numFrames -= 1
t = 0
frame = 0
saveAsPNG(canvas, "frame"+str(frame)+".png")
print "Created frame", frame
step = 0
interval = numSteps/numFrames
while step <= numSteps:
center = f(t)
offset = f(t+.005)
dx = offset[0] - center[0]
dy = offset[1]-center[1]
if dx**2 + dy**2 != 0:
dx, dy = dx/((dx**2+dy**2)**.5), dy/((dx**2+dy**2)**.5)
for q in range(-thickness, thickness):
canvas[int(round(dx*q+center[1]))+500][int(round(-dy*q+center[0]))+500] = fracColor(t)
if frame*interval == step:
frame += 1
saveAsPNG(canvas, "frame"+str(frame)+".png")
print "Created frame", frame
step += 1
t += 1/float(numSteps)
frame += 1
saveAsPNG(canvas, "frame"+str(frame)+".png")
print "Created frame", frame
def circ(t,r):
return (r*math.cos(2*math.pi*t), r*math.sin(2*math.pi*t))
def sin(t,h):
return (t*800-400, 100*math.sin(2*math.pi*h/100)*math.sin(8*math.pi*t))
def flower(theta, k):
return (400*math.cos(2*math.pi*theta)*math.sin(2*math.pi*k*theta), 400*math.sin(2*math.pi*theta)*math.sin(2*math.pi*k*theta))
def straightLineHomotopy(c1, c2): #c1 and c2 are curves parameterized by x
def homotopy(s, t):
dx = c2(s)[0]-c1(s)[0]
dy = c2(s)[1] - c1(s)[1]
return (t*dx+c1(s)[0], t*dy+c1(s)[1])
return homotopy
def square(t, length):
t = (2-t+.375) % 1
if t <=.25:
return (-1*length/2+4*t*length, length/2)
elif t <= .5:
return (length/2, length/2 - 4*(t-.25)*length)
elif t <= .75:
return (length/2 - 4*(t-.5)*length, -1*length/2)
else:
return (-1*length/2, 4*(t-.75)*length-length/2)
def spiral(b, length):
def curve(t):
t *= length
return ((b*t)*math.cos(t), (b*t)*math.sin(t))
return curve
# parameterCurve(flower, 1000, 5, 0, 2, 100)
parameterCurve(flower, 20000, 5, 0, 16, 100)
# traceCurve(lambda t: circ(t,400), 10000, 10, 1000)
# parameterCurve(straightLineHomotopy(lambda t: square(t, 200), lambda t: circ(t, 400)), 20000, 5, 0, 1, 1000)
# traceCurve(spiral(20, 6*math.pi), 20000, 5, 100)