149 lines
4.4 KiB
Python
149 lines
4.4 KiB
Python
|
import matplotlib.patches as patches
|
||
|
import matplotlib.pyplot as plt
|
||
|
import numpy as np
|
||
|
from pathlib import Path
|
||
|
|
||
|
|
||
|
def get_quadrant(x, y):
|
||
|
"""Return the quadrant of a given point."""
|
||
|
if x >= 0 and y >= 0:
|
||
|
return 1
|
||
|
elif x < 0 and y >= 0:
|
||
|
return 2
|
||
|
elif x < 0 and y < 0:
|
||
|
return 3
|
||
|
else:
|
||
|
return 4
|
||
|
|
||
|
|
||
|
def is_overlapping(x, y, existing_points, radius):
|
||
|
"""Check if a point overlaps with existing points, crosses a quadrant or goes beyond the quadrant lines."""
|
||
|
current_quadrant = get_quadrant(x, y)
|
||
|
buffer = 0.25
|
||
|
# Check if circle touches/crosses the x=0 or y=0 lines.
|
||
|
if (
|
||
|
abs(x) + radius > buffer
|
||
|
and abs(x) - radius < buffer
|
||
|
or abs(y) + radius > buffer
|
||
|
and abs(y) - radius < buffer
|
||
|
):
|
||
|
return True
|
||
|
|
||
|
for ex, ey in existing_points:
|
||
|
# Check overlap with existing points
|
||
|
if np.sqrt((x - ex) ** 2 + (y - ey) ** 2) <= 2 * radius + 0.5:
|
||
|
return True
|
||
|
# Check if the circle touches another quadrant
|
||
|
if (
|
||
|
get_quadrant(ex, ey) != current_quadrant
|
||
|
and np.sqrt((x - ex) ** 2 + (y - ey) ** 2) <= radius
|
||
|
):
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
|
||
|
DIR = "/teamspace/studios/this_studio/out_sortcolors"
|
||
|
|
||
|
N = 100
|
||
|
DPI = 300
|
||
|
SIZE = 72 # canvas size?
|
||
|
radius = 3
|
||
|
variance = 72 # Adjust variance as needed
|
||
|
|
||
|
Path(DIR).mkdir(exist_ok=True, parents=True)
|
||
|
|
||
|
|
||
|
with open(f"{DIR}/arrangement_grid.txt", "w") as f:
|
||
|
radius = 3
|
||
|
half = SIZE / 2 - 4
|
||
|
# make points an equispaced grid of 10 x 10 ranging from [-35, 35]
|
||
|
interval = (half - (-half)) / 9 # 10 points, so 9 intervals
|
||
|
|
||
|
# Generate the grid points
|
||
|
points = [
|
||
|
(x, y)
|
||
|
for x in np.arange(-half, half + 0.1, interval)
|
||
|
for y in np.arange(-half, half + 0.1, interval)
|
||
|
]
|
||
|
|
||
|
for x, y in points:
|
||
|
f.write(f"{x-radius}, {y+radius}\n")
|
||
|
# f.write(f"{x}, {y}\n")
|
||
|
|
||
|
print("wrote grid")
|
||
|
|
||
|
|
||
|
for seed in range(11, 22):
|
||
|
try:
|
||
|
np.random.seed(seed)
|
||
|
|
||
|
# To store plotted points
|
||
|
points = []
|
||
|
max_iterations = int(1e7)
|
||
|
iterations = 0
|
||
|
# Generate points
|
||
|
for k in range(N):
|
||
|
while True:
|
||
|
# x, y = np.random.normal(0, variance), np.random.normal(0, variance)
|
||
|
random_angle = np.random.uniform(0, 2 * np.pi)
|
||
|
# random_radius = np.random.uniform(0.25+radius, SIZE/2 - radius - 0.25)
|
||
|
random_radius = abs(np.random.normal(0, variance))
|
||
|
x = random_radius * np.cos(random_angle)
|
||
|
y = random_radius * np.sin(random_angle)
|
||
|
iterations += 1
|
||
|
if not is_overlapping(x, y, points, radius):
|
||
|
if max(abs(x), abs(y)) + radius < SIZE / 2 - 0.25:
|
||
|
points.append((x, y))
|
||
|
break
|
||
|
if iterations > max_iterations:
|
||
|
raise ValueError(f"Too many iterations: {k} points")
|
||
|
print(f"{k}: ({x}, {y}) @ {iterations:09d}")
|
||
|
|
||
|
# Create plot with circles
|
||
|
fig, ax = plt.subplots(1, 1, figsize=(SIZE, SIZE))
|
||
|
for x, y in points:
|
||
|
circle = patches.Circle((x, y), radius, color="black")
|
||
|
ax.add_patch(circle)
|
||
|
|
||
|
# Draw the standard quadrants
|
||
|
ax.axhline(0, color="black", linewidth=0.5)
|
||
|
ax.axvline(0, color="black", linewidth=0.5)
|
||
|
|
||
|
# Use square axis and set limits
|
||
|
|
||
|
lim_x = (
|
||
|
max(
|
||
|
abs(max(points, key=lambda t: t[0])[0]),
|
||
|
abs(min(points, key=lambda t: t[0])[0]),
|
||
|
)
|
||
|
+ radius
|
||
|
)
|
||
|
lim_y = (
|
||
|
max(
|
||
|
abs(max(points, key=lambda t: t[1])[1]),
|
||
|
abs(min(points, key=lambda t: t[1])[1]),
|
||
|
)
|
||
|
+ radius
|
||
|
)
|
||
|
lim_x = lim_y = SIZE / 2
|
||
|
ax.axis("off")
|
||
|
ax.set_aspect("equal")
|
||
|
ax.set_xlim(-lim_x, lim_x)
|
||
|
ax.set_ylim(-lim_y, lim_y)
|
||
|
|
||
|
# Save and show
|
||
|
fig.tight_layout(pad=0)
|
||
|
plt.savefig(
|
||
|
f"{DIR}/arrangement_{seed}.png", dpi=DPI, bbox_inches="tight", pad_inches=0
|
||
|
)
|
||
|
# plt.show()
|
||
|
# also save x/y coords as text file
|
||
|
with open(f"{DIR}/arrangement_{seed}.txt", "w") as f:
|
||
|
for x, y in points:
|
||
|
f.write(f"{x-radius}, {y+radius}\n")
|
||
|
# f.write(f"{x}, {y}\n")
|
||
|
except ValueError as e:
|
||
|
print(f"{seed}: {e}")
|
||
|
except AssertionError as e:
|
||
|
print(f"{seed}: {e}")
|