This repository was archived by the owner on Feb 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path2DPoissonPoints.py
More file actions
146 lines (114 loc) · 3.8 KB
/
2DPoissonPoints.py
File metadata and controls
146 lines (114 loc) · 3.8 KB
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
import numpy as np
import matplotlib.pyplot as plt
import math
from PIL import Image, ImageDraw
# they must be some type of integer, no float allowed.
WIDTH = 2
HEIGHT = 2
# for display purpouse
POINTS_SIZE = 6
# adjust the radius automatically
r = 0.038*(max(HEIGHT, WIDTH))
k = 30
# used only for PIL display
IMAGE_SIZE = 1024
"""
Generate a random point around "point" in an anulus of r-2r.
"""
def random_point(point, r):
# generate the angle from the point
theta = np.random.uniform(0, 2*math.pi)
# generate the distance from the point, between r and 2r
distance = np.random.uniform(r, 2*r)
# add the point generated to the list of random points
point = ((point[0]+distance*np.sin(theta),
point[1]+distance*np.cos(theta)))
return point
"""
Add "point" in "grid" and in "active_list" given a cellsize.
"""
def add_point(grid, active_list, cellsize, point):
active_list.append(point)
i, j = int(point[0]/cellsize), int(point[1]/cellsize)
grid[i, j] = point
"""
Given a "point", check the absence in "grid" of another point in a r radius.
"""
def check_distances(grid, rows, cols, cellsize, r, point):
i, j = int(point[0]/cellsize), int(point[1]/cellsize)
# check if the cell is occupied
if grid[i, j][0] > -1:
return False
row, col = i, j
iMin = max(0, row-2)
jMin = max(0, col-2)
iMax = min(row+2, rows)
jMax = min(col+2, cols)
# check all the conflict zones
for i in range(iMin, iMax):
for j in range(jMin, jMax):
if i != row or j != col:
if grid[i, j][0] > -1:
# for every cell occupied, check the distance
if math.sqrt(math.pow(point[0]-grid[i, j][0], 2)+math.pow(point[1]-grid[i, j][1], 2)) < r:
return False
# no conflict found, the point is ok
return True
"""
Generate poisson points in a radius r, trying k times for every point.
"""
def generate_poisson_points(r=0.038, k=30):
cellsize = r/np.sqrt(2)
rows = int(np.ceil(WIDTH/cellsize))
cols = int(np.ceil(HEIGHT/cellsize))
grid = np.full((rows, cols, 2), -1.0)
active_list = []
# add a random point
add_point(grid, active_list, cellsize,
(np.random.uniform(WIDTH), np.random.uniform(HEIGHT)))
while len(active_list):
index = np.random.randint(len(active_list))
point = active_list.pop(index)
found = False
for _ in range(k):
newPoint = random_point(point, r)
if 0 <= newPoint[0] and newPoint[0] < WIDTH and 0 <= newPoint[1] and newPoint[1] < HEIGHT and check_distances(grid, rows, cols, cellsize, r, newPoint):
add_point(grid, active_list, cellsize, newPoint)
found = True
break
if found:
active_list.append(point)
poisson_points = []
for i in range(rows):
for j in range(cols):
point = grid[i, j]
if (point[0] != -1):
poisson_points.append(point)
return poisson_points
points = generate_poisson_points(r, k)
# Display the generated points on a plot
plt.figure()
plt.subplot(1, 1, 1, aspect=1)
X = []
Y = []
for (x, y) in points:
X.append(x)
Y.append(y)
plt.title("Fast Poisson Disk Sampling in 2 Dimensions\n r="+str(r)+" k="+str(k))
plt.scatter(X, Y, s=POINTS_SIZE)
plt.xlabel("X")
plt.xlim(0, WIDTH)
plt.ylabel("Y")
plt.ylim(0, HEIGHT)
plt.show()
"""
# Display the generated points on an image
img = Image.new('RGB', (1024, 1024), (255, 255, 255))
draw = ImageDraw.Draw(img)
points = generate_poisson_points(r,30)
for point in points:
x, y = point [0]/HEIGHT*IMAGE_SIZE, point[1]/WIDTH*IMAGE_SIZE
draw.ellipse((x-POINT_SIZE, y-POINT_SIZE, x+POINT_SIZE, y+POINT_SIZE), fill=(0, 0, 0))
#draw.point((x, y), fill=(0, 0, 0))
img.show()
"""