import rhinoscriptsyntax as rs import random as ran rs.DeleteObjects(rs.AllObjects()) number_of_towers = 10 #number of towers distance = 30 # distance between towers def towers_overlap(base_point, radius, distance): for obj in rs.ObjectsByType(16): # type 16 = surfaces bounding_box = rs.BoundingBox(obj) if bounding_box: x_min, y_min = bounding_box[0][0], bounding_box[0][1] x_max, y_max = bounding_box[2][0], bounding_box[2][1] x, y = base_point[0], base_point[1] if (x - radius - distance < x_max and x + radius + distance > x_min and y - radius - distance < y_max and y + radius + distance > y_min): return True return False def create_tower(base_point, radius1, radius2, height_step, segments): curves = [] for i in range(segments): if i > segments - 5: #smaller segments in the end scale_factor = 1 - (i - (segments - 5)) * 0.2 current_radius1 = radius1 * scale_factor current_radius2 = radius2 * scale_factor else: current_radius1 = radius1 current_radius2 = radius2 current_radius = current_radius1 if i % 2 else current_radius2 circle = rs.AddCircle(base_point, current_radius) rs.RotateObject(circle, base_point, ran.uniform(0, 20)) #small rotation #variation in height rs.MoveObject(circle, (0, 0, i * height_step)) curves.append(circle) #loft circles loft = rs.AddLoftSrf(curves, loft_type=0) rs.CapPlanarHoles(loft) rs.DeleteObjects(curves) #delete curves for j in range(number_of_towers): max_attempts = 100 # max. tries to find right position for attempt in range(max_attempts): #random position x = ran.uniform(-200, 200) y = ran.uniform(-200, 200) base_point = (x, y, 0) #random parameters radius1 = ran.uniform(5, 20) #first radius radius2 = ran.uniform(3, 15) #second radius height_step = ran.uniform(10, 40)#distance between segments segments = ran.randint(10, 35) #number of segments radius_check = max(radius1, radius2) #avoid overlapping if not towers_overlap(base_point, radius_check, distance): create_tower(base_point, radius1, radius2, height_step, segments) rs.EnableRedraw(True)