Test run, settings as posted Placed 66 of 68
from mathutils import Vector, Matrix
from mathutils.noise import random, seed_set
import bpy
# Specify parameters
seed = 0
xmin = -10
xmax = 10
ymin = -10
ymax = 10
radius = 1
num_circles = 68
max_tries = 10000
max_height = 4
# Init
seed_set(seed)
sx = xmax - xmin - 2 * radius
sy = ymax - ymin - 2 * radius
xminm = xmin + radius
yminm = ymin + radius
existing_locations = []
sce = bpy.context.scene
bpy.ops.mesh.primitive_cylinder_add(
location=(0, 0, 0),
depth=1,
radius=radius)
ref_circle = bpy.context.object
ref_circle.data.transform(Matrix.Translation((0, 0, 0.5)))
# Loop
for i in range(num_circles):
j = 0
searchOn = True
while searchOn:
if j > max_tries:
print("Placed", i, "of", num_circles)
bpy.ops.object.select_all(action='DESELECT')
ref_circle.select_set(True)
bpy.ops.object.delete()
raise ValueError('Found no more room for another circle')
break
j += 1
new_location = (xminm + random() * sx,
yminm + random() * sy,
0)
for existing_location in existing_locations:
if (Vector(existing_location) - Vector(new_location)).length < 2 * radius:
break
else:
new_circle = ref_circle.copy()
new_circle.dimensions.z = max_height * random()
new_circle.location = new_location
sce.collection.objects.link(new_circle)
existing_locations.append(new_location)
searchOn = False
ref_circle.select_set(True)
bpy.ops.object.delete()
sce.update()