############################## import rhinoscriptsyntax as rs import sys, math, random, os sys.path.append("P:\WWW\halil2003\DM2") import DM_lib as dm #reload (osm) import OSM_lib as osm #reload (osm) rs.UnitSystem(4) # meters = 4 rs.ShowGrid(None, 0) rs.ShowGridAxes(None, 1) rs.EnableRedraw(0) currentMode = rs.ViewDisplayMode(rs.CurrentView()) rs.ViewDisplayMode(rs.CurrentView(), "wireframe") rs.Redraw() dm.newEmptyLayer("XYZ", [100,100,250]) rs.ShowObjects(rs.AllObjects()) sphere_color = [255, 183, 3] ring_color = [2, 48, 71] ring_edge_color = [255, 183, 3] cylindar_color = [33, 158, 188] bldg_names = ["_bldg3D_higBy_flo_136691386", "_bldg3D_higBy_flo_60739635", "_bldg3D_higBy_flo_904652296", "_bldg3D_higBy_flo_116806281"] centers_above_bldgs = [] intersection_pts_with_bldgs = [] secondary_spheres = [] larger_radius = 5 small_radius = 4 z_offset_bottom = -40 z_offset_top = 40 def create_spehere(center, radius): scale_vec = [radius, 0, 0] for i in range(1001): scale_vec = rs.VectorRotate(scale_vec, random.uniform(-90,90), [random.uniform(-1,1) for i in range(3)]) x = rs.VectorAdd(center, scale_vec) y = rs.VectorAdd(center, [0, 1, 0]) plane = rs.PlaneFromPoints(center, x, y) circle_id = rs.AddCircle(plane, radius) rs.ObjectColor(circle_id, sphere_color) def connect_2_spheres(first_center, first_radius, second_center, second_radius): vec_between_2_centers = rs.VectorCreate(first_center, second_center) unit_vec = rs.VectorUnitize(vec_between_2_centers) def get_circle_pts(unit_vec, sphere_center, radius, num_pts): radius_vec = rs.VectorScale(unit_vec, radius) spehere_intersection_pt = rs.VectorAdd(sphere_center, radius_vec) pt_back = rs.VectorSubtract(spehere_intersection_pt, rs.VectorScale(unit_vec, 0.4)) plane = rs.PlaneFromNormal(pt_back, unit_vec) sphere_id = rs.AddSphere(sphere_center, radius) sphere = rs.SurfaceSphere(sphere_id) intersection = rs.PlaneSphereIntersection(plane, sphere[0], radius) rs.DeleteObject(sphere_id) circle_pts = [] if intersection: circle_center = intersection[1] circle_radius = intersection[2] circle_id = rs.AddCircle(circle_center, circle_radius) circle_pts = rs.DivideCurve(circle_id, num_pts, 0) rs.DeleteObject(circle_id) return circle_pts number_of_pts = 50 # find circle on the first sphere first_circle_pts = get_circle_pts(rs.VectorReverse(unit_vec), first_center, first_radius, number_of_pts) # find circle on the second sphere second_circle_pts = get_circle_pts(unit_vec, second_center, second_radius, number_of_pts) # and now connect them for i in range(number_of_pts): min_distance = 9999999999999999999 idx = -1 for j in range(number_of_pts): temp_distance = rs.Distance(first_circle_pts[i], second_circle_pts[j]) if temp_distance < min_distance: min_distance = temp_distance idx = j line_id = rs.AddLine(first_circle_pts[i], second_circle_pts[idx]) rs.ObjectColor(line_id, cylindar_color) for bldg_name in bldg_names: blgd_id = rs.ObjectsByName(bldg_name)[0] coords = dm.getSurfacePoints(blgd_id) center_in = dm.pntCentroid(coords) if bldg_name == "_bldg3D_higBy_flo_904652296": # this building really has a specific shape # so let's just slightly move the center # of this building so it's easier to display # cylinder for connecting with the sphere above it center_in = rs.VectorAdd(center_in, [0, 25, 0]) center_above = rs.VectorAdd(center_in, [0,0,40]) centers_above_bldgs.append(center_above) max_z = -1 top_pts = [] for c in coords: if max_z < c[2]: top_pts = [] max_z = c[2] top_pts.append(c) elif max_z == c[2]: top_pts.append(c) assert len(top_pts) > 2 top_plane = rs.PlaneFromPoints(top_pts[0], top_pts[1], top_pts[2]) res = rs.LinePlaneIntersection([center_in, center_above], top_plane) intersection_pts_with_bldgs.append(res) main_center = dm.pntCentroid(centers_above_bldgs) create_spehere(main_center, small_radius) def filter_pts_outside_secondary_spheres(circle, number_of_pts=1000): circle_pts = rs.DivideCurve(circle, number_of_pts, 0) pts_groups = [] new_pts_groups_required = True for pt in circle_pts: pt_inside_sphere = False for secondary_sphere in secondary_spheres: if rs.Distance(pt, secondary_sphere) < small_radius: pt_inside_sphere = True new_pts_groups_required = True break if not pt_inside_sphere: if new_pts_groups_required: pts_groups.append([]) new_pts_groups_required = False pts_groups[-1].append(pt) # visualize ring for pts_group in pts_groups: curve_id = rs.AddCurve(pts_group) rs.ObjectColor(curve_id, ring_edge_color) return pts_groups def connect_2_ring_pts(first, second, color): middle = dm.pntInbetween(first, second) min_distance = rs.Distance(middle, secondary_spheres[0]) closest_sphere = secondary_spheres[0] for sphere in secondary_spheres: temp_distance = rs.Distance(middle, sphere) if temp_distance < min_distance: min_distance = temp_distance closest_sphere = sphere res = rs.LineSphereIntersection([first, second], closest_sphere, small_radius) if len(res) == 2: first_id = rs.AddLine(first, res[0]) second_id = rs.AddLine(second, res[1]) rs.ObjectColor(first_id, ring_color) rs.ObjectColor(second_id, ring_color) else: line_id = rs.AddLine(first, second) rs.ObjectColor(line_id, ring_color) def create_ring(ring_center, ring_height, distance_to_sphere_center, sphere_radius): radiuses = [distance_to_sphere_center - sphere_radius / 2, distance_to_sphere_center + sphere_radius / 2] inner_groups_saved = False inner_pts_groups = [] outer_pts_groups = [] for radius in radiuses: temp_center = rs.VectorAdd(ring_center, [0, 0, ring_height]) circle_up = rs.AddCircle(temp_center, radius) pts_groups_up = filter_pts_outside_secondary_spheres(circle_up) rs.DeleteObject(circle_up) if not inner_groups_saved: inner_pts_groups.append(pts_groups_up) else: outer_pts_groups.append(pts_groups_up) temp_center = rs.VectorAdd(ring_center, [0, 0, -ring_height]) circle_down = rs.AddCircle(temp_center, radius) pts_groups_down = filter_pts_outside_secondary_spheres(circle_down) rs.DeleteObject(circle_down) assert len(pts_groups_up) == len(pts_groups_down) for idx in range(len(pts_groups_down)): pts_group_up = pts_groups_up[idx] pts_group_down = pts_groups_down[idx] min_pts_len = min(len(pts_group_up), len(pts_group_down)) for pt_idx in range(min_pts_len): connect_2_ring_pts(pts_group_up[pt_idx], pts_group_down[pt_idx], [0, 0, 0]) if not inner_groups_saved: inner_pts_groups.append(pts_groups_down) else: outer_pts_groups.append(pts_groups_down) inner_groups_saved = True assert len(inner_pts_groups) == len(outer_pts_groups) for idx in range(len(inner_pts_groups)): curr_inner_pts_groups = inner_pts_groups[idx] curr_outer_pts_groups = outer_pts_groups[idx] assert len(curr_inner_pts_groups) == len(curr_outer_pts_groups) for pts_group_idx in range(len(curr_inner_pts_groups)): pts_inner = curr_inner_pts_groups[pts_group_idx] pts_outer = curr_outer_pts_groups[pts_group_idx] num_pts = min(len(pts_inner), len(pts_outer)) for pt_idx in range(num_pts): connect_2_ring_pts(pts_inner[pt_idx], pts_outer[pt_idx], [255, 165, 0]) def create_secondary_spheres(): lower_z = 9999999999999 upper_z = -1 distance_to_the_sphere_center = -1 d = 20 z_bottom = z_offset_bottom + 10 z_top = z_offset_top - 10 x_offsets = [-d, -d, d, d, -d, -d, d, d] # left - right y_offsets = [-d, d, -d, d, -d, d, -d, d] # further - closer z_offsets = [z_bottom, z_bottom, z_bottom, z_bottom, z_top, z_top, z_top, z_top] # up - down for idx in range(8): temp_vector = [x_offsets[idx], y_offsets[idx], z_offsets[idx]] new_center = rs.VectorAdd(main_center, temp_vector) secondary_spheres.append(new_center) upper_z = max(upper_z, new_center[2]) lower_z = min(lower_z, new_center[2]) temp_center = [main_center[0], main_center[1], main_center[2] + z_offsets[idx]] temp_vector = rs.VectorCreate(temp_center, new_center) distance_to_the_sphere_center = rs.VectorLength(temp_vector) create_spehere(new_center, small_radius) connect_2_spheres(main_center, small_radius, new_center, small_radius) distance = upper_z - lower_z + 1 number_of_rings = 5 step = distance / (number_of_rings - 1) spheres = [] for i in range(4): spheres.append([]) for z in range(int(lower_z), int(upper_z + 1), int(step)): ring_center = [main_center[0], main_center[1], z] x_offsets_for_ring_spheres = [-d, -d, d, d] # left - right y_offsets_for_ring_spheres = [-d, d, -d, d] # further - closer for idx in range(4): offset = [x_offsets_for_ring_spheres[idx], y_offsets_for_ring_spheres[idx], 0] sphere_center = rs.VectorAdd(ring_center, offset) create_spehere(sphere_center, small_radius) spheres[idx].append(sphere_center) secondary_spheres.append(sphere_center) create_ring(ring_center, step / 6, distance_to_the_sphere_center, small_radius) for position_idx in range(4): for idx in range(1, number_of_rings): connect_2_spheres(spheres[position_idx][idx - 1], small_radius, spheres[position_idx][idx], small_radius) create_secondary_spheres() def create_highest_and_lowest_spheres(): upper_z = -1 lower_z = 999999999999999 for secondary_sphere in secondary_spheres: upper_z = max(upper_z, secondary_sphere[2]) for secondary_sphere in secondary_spheres: lower_z = min(lower_z, secondary_sphere[2]) top_secondary_spheres = [] bottom_secondary_spheres = [] for secondary_sphere in secondary_spheres: if secondary_sphere[2] == upper_z: top_secondary_spheres.append(secondary_sphere) elif secondary_sphere[2] == lower_z: bottom_secondary_spheres.append(secondary_sphere) # 2 spheres - the heighest and lowest one z_offsets = [z_offset_bottom, z_offset_top] # up - down spheres = [bottom_secondary_spheres, top_secondary_spheres] for idx in range(2): temp_vector = [0, 0, z_offsets[idx]] new_center = rs.VectorAdd(main_center, temp_vector) create_spehere(new_center, small_radius) for secondary_sphere in spheres[idx]: connect_2_spheres(secondary_sphere, small_radius, new_center, small_radius) create_highest_and_lowest_spheres() def create_spheres_on_the_top_of_the_buildings(): upper_z = -1 for secondary_sphere in secondary_spheres: upper_z = max(upper_z, secondary_sphere[2]) for idx in range(len(centers_above_bldgs)): sphere_center = centers_above_bldgs[idx] create_spehere(sphere_center, larger_radius) circle_center = intersection_pts_with_bldgs[idx] connect_2_spheres(sphere_center, larger_radius, rs.VectorSubtract(circle_center, [0, 0, larger_radius]), larger_radius) closest_sphere = [0, 0, 0] min_distance = 99999999999999999 for secondary_sphere in secondary_spheres: if secondary_sphere[2] != upper_z: # if it's not one of the top sphere then do not connect to it! continue distance = rs.Distance(secondary_sphere, sphere_center) if distance < min_distance: min_distance = distance closest_sphere = secondary_sphere connect_2_spheres(closest_sphere, small_radius, sphere_center, larger_radius) create_spheres_on_the_top_of_the_buildings() #################################### rs.CurrentLayer("XYZ") rs.ViewDisplayMode(None, "rendered") capture_animation_imgs = False if capture_animation_imgs: circle_id = rs.AddCircle(main_center, 400) circle_pts = rs.DivideCurve(circle_id, 300, 0) def to_frame_name(frame_idx): s = str(frame_idx) while len(s) < 4: s = "0" + s return "frame_" + s path = "C:/Users/hanci/Desktop/test/" if not os.path.exists(path): os.makedirs(path) frame_number = 0 for circle_pt in circle_pts: dm.setCameraTarget(circle_pt, main_center) rs.Redraw() rs.Command("-viewCaptureToFile Width=1280 Height=720 Scale=2 DrawCPlaneAxes=No TransparentBackground=No " + path + to_frame_name(frame_number) + " ", 0) frame_number += 1