How do I generate random cylinders, with random height on a predefined area? I am using the following python script to generate an amount of random cylinders that do not overlap with each other: 

     import bpy
 from random import random
 from mathutils import Vector

 cylinderRadius    = 1
 maxIterations = 500 # Max iterations to prevent while loop from running 
 forever

# min and max values for each axis for the random numbers
ranges = {
   'x' : { 'min' : 7, 'max' : 10 },
   'y' : { 'min' : 7, 'max' : 10 },
   'z' : { 'min' : 0, 'max' : 0}
  }

# Generates a random number within the axis minmax range
randLocInRange = lambda axis: ranges[axis]['min'] + random() * ( 
ranges[axis]['max'] - ranges[axis]['min'] )

size  = 50 # Number of cylinders
cylinders = []  # Cylinders coordinates list

loopIterations = 0
while len( cylinders ) &lt; size and loopIterations &lt; maxIterations:
   loopIterations += 1

# Generate a random 3D coordinate
loc = Vector([ randLocInRange( axis ) for axis in ranges.keys() ])

if len( cylinders ) &gt; 0:
    # Search for overlapping points (within the cylinder radius radius)
    overlappingPoints = [ p for p in cylinders if ( p - loc ).length &lt; cylinderRadius * 2 ]

    # if any found, skip this location
    if overlappingPoints: continue

# Add coordinate to cylinder list
cylinders.append( loc )

# Add the first cylinder (others will be duplicated from it)
bpy.ops.mesh.primitive_cylinder_add( radius = cylinderRadius, location = 
cylinders[0] )
cylinder = bpy.context.scene.objects['Cylinder']

# Add all other cylinders
for c in cylinders[1:]:
    dupliCylinder = cylinder.copy()
    dupliCylinder.location = c
    bpy.context.scene.objects.link( dupliCylinder )


However, I do not get the 50 cylinders I am asking for when compiling. Does anyone have an idea on how to actually avoid setting a number of cylinders to be generated, but to fill in a pre-defined area (e.g. a square) with randomly placed cylinders, that do not overlap with each other, on it ? 

Thanks!
Test run, settings as posted Placed 66 of 68

Algorithm for random distribution of circles in a square


  This simple script to place a number of num_circles circles with
  radius radius in a refined rectangle (aligned to global axes) speficied
  by xmin, xmax, ymin and ymax by trying random locations until it not
  colliding with an existing circle. This is certainly not the most
  efficient way of doing it, but it should be fine for smaller problems
  and if the relative area covered is not too high.


Test code after making a couple of edits to https://blender.stackexchange.com/a/89658/15543 to make it add cylinders of random height to a rectangle.

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 &gt; 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 &lt; 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()
context.view_layer.update()