-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathJumpFloodVoronoi.py
315 lines (246 loc) · 9.1 KB
/
JumpFloodVoronoi.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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 16 13:37:01 2021
Implementation of the Jump-Flood Algorithm (JFA) adapted to create Voronoi Diagrams
@author: bentdoug
"""
import matplotlib.pyplot as plt
import numpy as np
import math
import random
def JFA_Voronoi(row, col, seedlist):
"""
Create Voronoi Diagram Utalizing an implementation
of the Jump Flood Algorithm that does not use GPU
row:
x-axis resolution (how many points desired in x-axis)
col:
y-axis resolution (how many points desired in y-axis)
seedlist:
list of seed points [[x-coord, ycoord]]
"""
#Dictionary = Key: Value of a point in arr1 (Corresponding to Color) ->
#Value: Origin point of that color value (Original Voronoi Site)
seeds = {}
#graph to be filled in with Voronoi Diagram
arr1 = np.zeros((row, col))
#list of already filled points (Current Voronoi Sites)
arrlisted = []
#setting initial step length to half the dimensions of the grid
step = col//2
#divides the color limit of the graph by the number of intial seeds (Voronoi Sites)
#this is the distance between each color value
numseeds = len(seedlist)
numasigncalc = 40/numseeds
numpoint = 1
#Filling arrlisted, calculates and assigns color value, inputs this data to
#seeds and arr1
for point in seedlist:
arrlisted.append(point)
value = (numasigncalc*numpoint)
seeds.update({value: point})
numpoint+=1
arr1[point[0], point[1]] = value
#counter used when naming each image to be saved (figure number)
fignum = 0
#array used to efficiently look at a points neighbors
moves = [1, -1, 0]
#Creates and saves initial image
plt.imshow(arr1)
plt.clim(0,40)
plt.savefig("JFAVoronoi" + str(fignum)+ ".png", dpi = 300)
fignum+=1
plt.show()
#JFA adapted to create Voronoi Diagrams
while step > 0:
#loop through each filled site (Voronoi Sites)
for seed in arrlisted:
x = seed[0]
y = seed[1]
val = arr1[x, y]
#loop through each of this points 8 neighbors at a certain distance away
for i in moves:
for j in moves:
a = x+(step*i)
b = y+(step*j)
#if this neighbor point is within the bounds of the graph
if 0 <= a < row and 0 <= b < col:
#if this neighbor point is not equal to the Voronoi Site it is
#the neighbor of
if arr1[a,b] != val:
#if this neighbor point is empty -> fill and add to arrlisted
if arr1[a, b] == 0:
arr1[a, b] = val
arrlisted.append([a, b])
#else -> compute the distances from this neighbor point and
#its current origin point as well as from this neighbor point
#to the current Voronoi Site's origin point (in dictionary; seeds)
else:
##location of seed associated with this points value
loc1 = seeds[arr1[a,b]]
##location of the seed trying to replace this points value
loc2 = seeds[val]
##Calculating Distances
##distance from seed already connected to this point to the point
dist1 = math.sqrt( ((loc1[0]-a)**2)+((loc1[1]-b)**2) )
##distance from seed trying to replace previous to this point
dist2 = math.sqrt( ((loc2[0]-a)**2)+((loc2[1]-b)**2) )
##if dist2 is less than dist1, change the points value to that new seeds value
##else do nothing at this point
if dist2 < dist1:
arr1[a,b] = val
#Saving each image
plt.imshow(arr1)
plt.clim(0,40)
fignum+=1
plt.savefig("JFAVoronoi" + str(fignum)+ ".png", dpi = 300)
plt.show()
step //= 2
def face(x, y):
"""
Calculates points to fill in order to plot a smiley-face on a graph of
x and y dimensions
Parameters
----------
x:
x-axis resolution (how many points desired in x-axis)
y:
y-axis resolution (how many points desired in y-axis)
Returns
-------
seedlist : the neccessary points in a shuffled order as to ensure most points
do not get assigned the same color value as their neighbor
"""
#list of seed locations to be filled and returned
seedlist = []
#calculates a the value of a third and a sixth of the dimensions of the grid
#to be used in calculating location of points
third = x//3
sixth = x//6
#calculates points that will create two lines to represent eyes and adds those
#points to seedlist
for x in range(third):
seedlist.append([third+x, third])
seedlist.append([third+x, 2*third])
#calculates points that will create the vertical sides of the face's mouth
# and adds those points to seedlist
for x in range(sixth):
seedlist.append([x + 5*sixth, sixth])
seedlist.append([x + 5*sixth, sixth*5])
#calculates points that will create the horizontal portion of the face's mouth
#and adds those points to seedlist
for x in range(2*third):
seedlist.append([47, sixth+x])
#shuffles the order of these seeds in seedlist
random.shuffle(seedlist)
return seedlist
def square(x, y):
"""
Calculates points to fill in order to plot a square on a graph of
x and y dimensions
Parameters
----------
x:
x-axis resolution (how many points desired in x-axis)
y:
y-axis resolution (how many points desired in y-axis)
Returns
-------
seedlist : the neccessary points for the square
"""
seedlist = []
third = x//3
sixth = x//6
for x in range(third):
seedlist.append([third+x, third])
seedlist.append([third+x, 2*third])
for x in range(third):
seedlist.append([third, third+x])
seedlist.append([2*third, third+x])
return seedlist
def thankyou(x, y):
"""
Calculates points to fill in order to plot "thank you" on a graph of
x and y dimensions
Parameters
----------
x:
x-axis resolution (how many points desired in x-axis)
y:
y-axis resolution (how many points desired in y-axis)
Returns
-------
seedlist : the neccessary points to write "thank you"
"""
seedlist = []
##T
for x in range(400):
seedlist.append([50+x, 100])
for x in range(100):
seedlist.append([50, x+50])
##H
for x in range(400):
seedlist.append([50+x, 200])
seedlist.append([50+x, 300])
for x in range(100):
seedlist.append([250, 200+x])
##A
x = 450
x2 = 450
y = 50
ctr = 0
while y <=450:
seedlist.append([y, x])
seedlist.append([y, x2])
y += 1
ctr+=1
if ctr%4 == 0:
x+=1
x2-=1
for x in range(100):
seedlist.append([250, 400+x])
##N
for x in range(400):
seedlist.append([50+x, 600])
seedlist.append([50+x, 700])
y = 600
x = 50
ctr = 0
while x <=450:
seedlist.append([x, y])
x+=1
ctr+=1
if ctr%4 == 0:
y += 1
##K
for x in range(400):
seedlist.append([50+x, 750])
x = 200
y = 750
ctr = 0
while x >= 50:
seedlist.append([x,y])
x-=1
ctr+=1
if ctr%2 == 0:
y+=1
x = 200
y = 750
ctr = 0
while x <= 450:
seedlist.append([x,y])
x+=1
ctr+=1
if ctr%3 == 0:
y+=1
##S
for x in range(100):
seedlist.append([50, 880+x])
seedlist.append([250, 880+x])
seedlist.append([450, 880+x])
for x in range(200):
seedlist.append([50+x, 880])
seedlist.append([250+x, 980])
return seedlist
seedlist = [[2,2], [4,1], [0,4]]
JFA_Voronoi(5, 5, seedlist)