import rhinoscriptsyntax as rs import math # Clear everything and start from scratch rs.DeleteObjects(rs.AllObjects()) # Parameters tower_height = 300 # Total height of the tower num_segments = 100 # Number of segments for the loft base_radius = 10 # Base radius sine_amplitude = 5 # Amplitude of the sine wave sine_frequency = 2 # Frequency of the sine wave window_width = 2 # Width of the window window_height = 4 # Height of the window rows = 50 # Number of rows for windows columns = 20 # Number of columns for windows # Function to generate sine-wave-modulated radii def sine_wave_radius(z, amplitude, frequency, base_radius): """ Calculates the radius at a given height (z) based on a sine wave. """ return base_radius + amplitude * math.sin(2 * math.pi * frequency * z / tower_height) # Create base curves for loft curves = [] for i in range(num_segments + 1): # Top segment # Calculate height step z = i * (tower_height / num_segments) # Calculate radius radius = sine_wave_radius(z, sine_amplitude, sine_frequency, base_radius) # Create a circle circle = rs.AddCircle((0, 0, z), radius) curves.append(circle) # Loft the curves to create the tower surface loft = rs.AddLoftSrf(curves, loft_type=0) # 0 = Normal loft if loft: rs.CapPlanarHoles(loft) # Cap the top and bottom of the tower rs.DeleteObjects(curves) # Clean up intermediate circles # Ensure we are working with a single surface tower_surface = None if loft: if isinstance(loft, list): # Extract the first surface if it's a list tower_surface = loft[0] else: # If not a list, use it directly tower_surface = loft # Add windows to the surface if tower_surface and rs.IsSurface(tower_surface): # Get the surface domain in U and V u_domain = rs.SurfaceDomain(tower_surface, 0) v_domain = rs.SurfaceDomain(tower_surface, 1) # Divide the surface into a grid u_step = (u_domain[1] - u_domain[0]) / columns v_step = (v_domain[1] - v_domain[0]) / rows # Generate windows openings = [] for i in range(columns): for j in range(rows): # Calculate UV coordinates u = u_domain[0] + i * u_step v = v_domain[0] + j * v_step # Evaluate the point on the surface point = rs.EvaluateSurface(tower_surface, u, v) # Create a plane at the point normal = rs.SurfaceNormal(tower_surface, (u, v)) if normal: plane = rs.PlaneFromNormal(point, normal) # Create a rectangle for the window window = rs.AddRectangle(plane, window_width, window_height) if window: # Extrude the rectangle to create a window volume extrusion = rs.ExtrudeCurveStraight(window, (0, 0, -1), (0, 0, -10)) if extrusion: openings.append(extrusion) rs.DeleteObject(window) # Clean up the rectangle # Subtract the windows from the tower surface if openings: final_surface = rs.BooleanDifference(tower_surface, openings) if final_surface: rs.DeleteObjects(openings) # Cleanup window geometry # Enable redraw in Rhino rs.EnableRedraw(True)