def _cell_update_halfface(volmesh, hfkey, xyz, normal=None): """Return new coordinates for the halfface. """ new_cell_xyz = {} ckey = volmesh.halfface_cell(hfkey) cell_vkeys = volmesh.cell_vertices(ckey) hf_vkeys = volmesh.halfface_vertices(hfkey) if not normal: normal = volmesh.halfface_normal(hfkey) plane = (xyz, normal) edges = {key: [] for key in hf_vkeys} for u in hf_vkeys: nbrs = volmesh.vertex_neighbors(u) for v in nbrs: if v not in hf_vkeys and v in cell_vkeys: edges[u].append(v) for u in hf_vkeys: v = edges[u][0] u_xyz = volmesh.vertex_coordinates(u) v_xyz = volmesh.vertex_coordinates(v) line = (u_xyz, v_xyz) it = intersection_line_plane(line, plane) new_cell_xyz[u] = it return new_cell_xyz
def intersect_residual(boundary, frame): intersections = [] for key in boundary: a = cablenet.vertex_coordinates(key) r = cablenet.residual(key) b = add_vectors(a, r) pt = intersection_line_plane((a, b), (frame.point, frame.zaxis)) intersections.append(pt) return intersections
def dropped_perpendicular_points(line_point_1_1, line_point_1_2, line_point_2_1, line_point_2_2): """compute the projected tangent point on axis defined by [L1_pt1, L1_pt2] and [L2_pt1, L2_pt2] See Fig. 3.7 in SP's dissertaion (below). We are computing the point pair (P1, P_{C1}) here, given the axis endpoints of bar b_{e1} and b_{n1} .. image:: ../images/perpendicular_bar_tangent_to_two_existing_bars.png :scale: 80 % :alt: perpendicular_bar_tangent_to_two_existing_bars :align: center Parameters ---------- line_point_1_1 : [type] [description] line_point_1_2 : [type] [description] line_point_2_1 : [type] [description] line_point_2_2 : [type] [description] Returns ------- list of two points representing the contact line segment between the two axes """ line_unity_vector_1 = normalize_vector(vector_from_points(line_point_1_1, line_point_1_2)) line_unity_vector_2 = normalize_vector(vector_from_points(line_point_2_1, line_point_2_2)) d_vector = cross_vectors(line_unity_vector_1, line_unity_vector_2) normal_1 = cross_vectors(line_unity_vector_1, d_vector) normal_2 = cross_vectors(line_unity_vector_2, d_vector) plane_1 = (line_point_1_1, normal_1) plane_2 = (line_point_2_1, normal_2) line_1_dp_point = intersection_line_plane((line_point_1_1, line_point_1_2), plane_2) line_2_dp_point = intersection_line_plane((line_point_2_1, line_point_2_2), plane_1) return [line_1_dp_point, line_2_dp_point]
def reflect_line_plane(line, plane, tol=1e-6): """Bounce a line of a reflection plane. Parameters ---------- line : tuple Two points defining the line. plane : tuple Base point and normal vector of the plane. tol : float, optional A tolerance for membership verification. Default is ``1e-6``. Returns ------- tuple The reflected line defined by the intersection point of the line and plane and the mirrored start point of the line with respect to a line perpendicular to the plane through the intersection. Notes ----- The direction of the line and plane are important. The line is only reflected if it points towards the front of the plane. This is true if the dot product of the direction vector of the line and the normal vector of the plane is smaller than zero. Examples -------- >>> plane = [0, 0, 0], [0, 1, 0] >>> line = [-1, 1, 0], [-0.5, 0.5, 0] >>> reflect_line_plane(line, plane) ([0.0, 0.0, 0.0], [1.0, 1.0, 0.0]) """ x = intersection_line_plane(line, plane, tol=tol) if not x: return a, b = line o, n = plane ab = subtract_vectors(b, a) if dot_vectors(ab, n) > 0: # the line does not point towards the front of the plane return mirror = x, add_vectors(x, n) return x, mirror_point_line(a, mirror)
def cell_relocate_face(cell, fkey, xyz, normal): """Relocate the face of a mesh. Parameters ---------- cell : Mesh Cell as a mesh object. fkey : hashable Identifier of the face. xyz : tuple xyz coordinates of the new target plane. normal : tuple Target normal vector. Returns ------- cell : Mesh Updated cell. """ cell_split_indet_face_vertices(cell, fkey) vkeys = cell.face_vertices(fkey) # new target plane for the face plane = (xyz, normal) # neighboring edges edges = {} for u in vkeys: for v in cell.vertex_neighbors(u): if v not in vkeys: edges[u] = v for u in edges: line = cell.edge_coordinates(u, edges[u]) it = intersection_line_plane(line, plane) cell.vertex_update_xyz(u, it, constrained=False) return cell
def OnDynamicDraw(sender, e): cp = e.CurrentPoint plane = (cp, normal) line = (center, add_vectors(center, normal)) it = intersection_line_plane(line, plane) translation = subtract_vectors(it, center) dot = dot_vectors(normal, translation) dot = dot / abs(dot) dist = distance_point_point(center, it) * dot for hfkey in hfkeys: hf_center = volmesh.halfface_center(hfkey) hf_normal = volmesh.halfface_oriented_normal(hfkey) ep = add_vectors(hf_center, scale_vector(hf_normal, dist)) e.Display.DrawDottedLine(Point3d(*hf_center), Point3d(*ep), feedback_color) e.Display.DrawPoint(Point3d(*ep), 0, 4, black) for vkey in volmesh.halfface_vertices(hfkey): sp = volmesh.vertex_coordinates(vkey) e.Display.DrawLine(Point3d(*sp), Point3d(*ep), black, 2)
hits = igl.intersection_ray_mesh(ray, mesh) if hits: i1, r1 = ray_mesh_intersect_reflect(ray, mesh, hits[0], index_face) intersections.append(i1) vector = r1 - i1 vector.unitize() ray = i1, vector hits = igl.intersection_ray_mesh(ray, mesh) if hits: if len(hits) > 1: hit = hits[1] else: hit = hits[0] i2, _ = ray_mesh_intersect_reflect(ray, mesh, hit, index_face) if (i2 - i1).length < 0.01: x = intersection_line_plane((i1, r1), ground) r1 = Point(*x) reflections.append((i1, r1)) else: reflections.append((i1, i2)) else: x = intersection_line_plane((i1, r1), ground) r1 = Point(*x) reflections.append((i1, r1)) # ============================================================================== # Visualisation # ============================================================================== viewer = ObjectViewer()
def RunCommand(is_interactive): #load Derivation and model derivation = Derivation.from_json( rhino_UI_utilities.get_json_file_location()) model = derivation.get_next_step() #select beams selection_reference = [] selection_reference.append( rs.GetObject(message="select start Beam", filter=32, preselect=True)) selection_reference.extend( rs.GetObjects(message="select Beams to connect", filter=32, preselect=True)) #load helpers helper = UI_helpers() #name search selected_beams = helper.extract_BeambyName(model, selection_reference) #check for parallel planes, uses the function above start_beam = selected_beams[0] beams_to_connect = selected_beams[1:] parallel_check = check_for_parallel_vectors(start_beam, beams_to_connect) if parallel_check != True: raise IndexError('beams are not parallel') else: print("beams are parallel") #check for coplanarity, uses the function above coplanar_planes = {} face_ids_coplanar_planes = {} for i in range(1, 5): start_beam_plane = start_beam.face_plane(i).copy() start_beam_origin = start_beam_plane.point a = get_coplanar_planes(start_beam_plane, start_beam_origin, beams_to_connect) if a != False: coplanar_planes['' + str(i)] = a[0] face_ids_coplanar_planes['' + str(i)] = a[1] else: pass print("face_dictionary here", face_ids_coplanar_planes) if len(coplanar_planes.keys()) == 2: print("'success", coplanar_planes) else: raise IndexError('beams are not coplanar') #user inputs face_id = rs.GetInteger(("possible face connections " + "face_id " + coplanar_planes.keys()[0] + " or face_id " + coplanar_planes.keys()[1]), None, None, None) start_point = (helper.Get_SelectPointOnMeshEdge("Select mesh edge", "Pick point on edge")) ext_start = rs.GetReal("extension length start", 200, None, None) ext_end = rs.GetReal("extension length end", 200, None, None) #list of coplanar planes extracted from coplanar_planes dict using face_id as key coplanar_planes_along_selected_face = [] coplanar_planes_along_selected_face.append( start_beam.face_plane(face_id).copy()) for key, value in coplanar_planes.items(): if key == "" + str(face_id): coplanar_planes_along_selected_face.extend(value) #list of face_ids of coplanar planes coplanar_face_ids = [] coplanar_face_ids.append(face_id) for key, value in face_ids_coplanar_planes.items(): if key == "" + str(face_id): coplanar_face_ids.extend(value) #intersection points by passing a line from the origin of start beam to the adjacent planes of the coplanar planes of all beams points_to_compare = [] for i in range(len(selected_beams)): beam = selected_beams[i] start_beam_selected_face_frame = selected_beams[0].face_frame(face_id) line_pt_a = start_beam_selected_face_frame.point normal = start_beam_selected_face_frame.normal line_pt_b = add_vectors(line_pt_a, scale_vector(normal, 0.3)) line_to_intersect = Line(line_pt_a, line_pt_b) face_index = coplanar_face_ids[i] adjacent_planes = beam.neighbour_face_plane(face_index) for p in adjacent_planes: intersection_point = intersection_line_plane(line_to_intersect, p) points_to_compare.append(intersection_point) viz_pts = [] #project distance from points_to_compare to the plane of the start Beam distances = [] start_beam_face_frame = start_beam.face_frame(face_id).copy() start_beam_Plane_perpendicular_to_face_id_Plane = Plane( start_beam_face_frame.point, start_beam_face_frame.normal) viz_pts.append(start_beam_Plane_perpendicular_to_face_id_Plane.point) for point in points_to_compare: viz_pts.append(point) vector = subtract_vectors( point, start_beam_Plane_perpendicular_to_face_id_Plane.point) distances.append( dot_vectors( vector, start_beam_Plane_perpendicular_to_face_id_Plane.normal)) #search to find max point maximum_distance = max(distances) minimum_distance = min(distances) beam_length = (maximum_distance - minimum_distance) + ext_start + ext_end ext_len = maximum_distance + ext_start #project selected point to perpendicular planes of the beams to connect if coplanar_planes.keys()[0] == "1" or coplanar_planes.keys()[0] == "3": start_beam_perpendicular_plane = start_beam.face_plane(5).copy() elif coplanar_planes.keys()[0] == "2" or coplanar_planes.keys()[0] == "4": start_beam_perpendicular_plane = start_beam.face_plane(6).copy() tol = 1.0e-5 # tol = 5.0 perpendicular_plane = [] for beam in beams_to_connect: for i in range(5, 7): beam_plane = beam.face_plane(i).copy() print("beam_plane", beam_plane) angle_check = start_beam_perpendicular_plane.normal.angle( beam_plane.normal) print("angle", angle_check) if (abs(angle_check) - 0) < tol or (abs(angle_check) - 180) < tol: perpendicular_plane.append(beam_plane) print(perpendicular_plane) print(len(perpendicular_plane)) #project points projected_point_list = [] new_start_point = project_points_plane([start_point], start_beam_perpendicular_plane) projected_point_list.extend(new_start_point) for plane in perpendicular_plane: new_point = project_points_plane(new_start_point, plane) projected_point_list.extend(new_point) #list of distance to move joints on match beam model.rule_Connect_90lap(selected_beams, projected_point_list, coplanar_face_ids, beam_length, ext_len, create_id()) print(len(projected_point_list)) print(projected_point_list) #Save Derivation (Model is also saved) derivation.to_json(rhino_UI_utilities.get_json_file_location(), pretty=True) # Visualization viz_point = [] for pt in projected_point_list: a = (pt[0], pt[1], pt[2]) viz_point.append({'pos': a, 'color': (0, 255, 0)}) artist = MeshArtist(None, layer='BEAM::Beams_out') artist.clear_layer() artist.draw_points(viz_point) for beam in model.beams: artist = MeshArtist( beam.mesh, layer='BEAM::Beams_out' ) #.mesh is not ideal fix in beam and assemble class artist.draw_faces(join_faces=True)
bottom = ... # the vertices of the top face are the intersection points of the face normal # placed at each (offset) bottom vertex and a plane perpendicular to the # face normal placed at a distance THICKNESS along the face normal from the # face centroid. # define the plane origin = ... normal = ... plane = add_vectors(origin, ...), normal top = [] for a in bottom: b = ... ... = intersection_line_plane(...) top.append(...) top[:] = ... vertices = ... + ... faces = [[0, 3, 2, 1], ..., [3, 0, 4, 7], [2, 3, 7, 6], [1, 2, 6, 5], [0, 1, 5, 4]] block = Mesh.from_...(...) blocks.append(block) # ============================================================================== # Visualize the block with a mesh artist in the specified layer. Use # `draw_faces` (with `join_faces=True`) instead of `draw_mesh` to get a flat # shaded result. Also draw the vertex labels tovisualize the cycle directions.
def point_on_plane(point, frame, direction=None): if direction is None: direction = frame.normal line = line_sdl(point, direction, 1.0) return intersection_line_plane((line.start, line.end), (frame.point, frame.normal))
right_vertices = right_vertices[i:] + right_vertices[:i] right_points = block.vertices_attributes('xyz', keys=right_vertices) # ============================================================================== # Movement paths # ============================================================================== left_plane = Plane([0, 0, 0], [-1, 0, 0]) right_plane = Plane([WIRE, 0, 0], [+1, 0, 0]) left_intersections = [left_plane.point] right_intersections = [right_plane.point] for line in zip(left_points, right_points): left_x = intersection_line_plane(line, left_plane) right_x = intersection_line_plane(line, right_plane) left_intersections.append(left_x) right_intersections.append(right_x) left_intersections.append(left_intersections[1]) right_intersections.append(right_intersections[1]) left_intersections.append(left_intersections[0]) right_intersections.append(right_intersections[0]) # polylines left_poly = Polyline(left_intersections) right_poly = Polyline(right_intersections)
def rhino_volmesh_halfface_pinch(volmesh): hfkeys = _select_boundary_halffaces(volmesh) key = hfkeys[0] center = volmesh.halfface_center(key) normal = volmesh.halfface_oriented_normal(key) line = (center, add_vectors(center, normal)) # -------------------------------------------------------------------------- # dynamic draw # -------------------------------------------------------------------------- rs.EnableRedraw(True) def OnDynamicDraw(sender, e): cp = e.CurrentPoint plane = (cp, normal) line = (center, add_vectors(center, normal)) it = intersection_line_plane(line, plane) translation = subtract_vectors(it, center) dot = dot_vectors(normal, translation) dot = dot / abs(dot) dist = distance_point_point(center, it) * dot for hfkey in hfkeys: hf_center = volmesh.halfface_center(hfkey) hf_normal = volmesh.halfface_oriented_normal(hfkey) ep = add_vectors(hf_center, scale_vector(hf_normal, dist)) e.Display.DrawDottedLine(Point3d(*hf_center), Point3d(*ep), feedback_color) e.Display.DrawPoint(Point3d(*ep), 0, 4, black) for vkey in volmesh.halfface_vertices(hfkey): sp = volmesh.vertex_coordinates(vkey) e.Display.DrawLine(Point3d(*sp), Point3d(*ep), black, 2) # -------------------------------------------------------------------------- # input point # -------------------------------------------------------------------------- ip = Point3d(*center) axis = Rhino.Geometry.Line(ip, ip + Vector3d(*normal)) gp = get_target_point(axis, OnDynamicDraw) plane = (gp, normal) it = intersection_line_plane(line, plane) translation = subtract_vectors(it, center) dot = dot_vectors(normal, translation) dot = dot / abs(dot) rise = distance_point_point(center, it) * dot for hfkey in hfkeys: hf_center = volmesh.halfface_center(hfkey) hf_normal = volmesh.halfface_oriented_normal(hfkey) ep = add_vectors(hf_center, scale_vector(hf_normal, rise)) volmesh_halfface_pinch(volmesh, hfkey, ep) volmesh.draw() return volmesh
shell = Shell.from_json(FILE_I) keys = [268, 258, 115, 106, 114, 269, 281, 145] origin = [0, 2.5, 0] normal = [0, 1.0, 0] plane = (origin, normal) points = [] rhinopoints = [] for key in keys: a = shell.vertex_coordinates(key) r = shell.get_vertex_attributes(key, ['rx', 'ry', 'rz']) b = add_vectors(a, r) line = a, b x = intersection_line_plane(line, plane) points.append(x) rhinopoints.append({ 'pos' : x, 'color' : (0, 0, 255), 'name' : "{}.{}.anchor".format(shell.name, key) }) box = bounding_box(points) lines = [] for i, j in [(0, 1), (1, 5), (5, 4), (4, 0)]: a = box[i] b = box[j] d = distance_point_point(a, b)
def OnDynamicDraw(sender, e): cp = e.CurrentPoint plane = (cp, f_normal) new_pt_list = [] for u in f_vkeys: v = edges[u] u_xyz = cell.vertex_coordinates(u) v_xyz = cell.vertex_coordinates(v) line = (u_xyz, v_xyz) it = intersection_line_plane(line, plane) xyz_dict[u] = it new_pt_list.append(it) e.Display.DrawDottedLine(Point3d(*u_xyz), Point3d(*it), black) for vkey in cell.vertex: xyz = cell.vertex_coordinates(vkey) e.Display.DrawPoint(Point3d(*xyz), 0, 5, black) # old normal and area -------------------------------------------------- e.Display.DrawDot(Point3d(*f_center), str(round(f_area, 3)), gray, white) # draw original face --------------------------------------------------- for i in range(-1, len(f_vkeys) - 1): vkey1 = f_vkeys[i] vkey2 = f_vkeys[i + 1] sp = Point3d(*cell.vertex_coordinates(vkey1)) np = Point3d(*cell.vertex_coordinates(vkey2)) e.Display.DrawDottedLine(sp, np, black) # get current face info ------------------------------------------------ areas = {} normals = {} for fkey in cell.faces(): face_coordinates = [ xyz_dict[vkey] for vkey in cell.face_vertices(fkey) ] areas[fkey] = polygon_area_oriented(face_coordinates) normals[fkey] = polygon_normal_oriented(face_coordinates) # draw new face areas / vectors ---------------------------------------- for fkey in cell.faces(): area = areas[fkey] normal = normals[fkey] value = area / max(areas.values()) color = i_to_rgb(value) color = FromArgb(*color) # draw vectors ----------------------------------------------------- scale = 0.25 center = datastructure_centroid(cell) sp = Point3d(*center) vector = scale_vector(normal, area * scale) ep = Point3d(*add_vectors(center, vector)) e.Display.DrawArrow(Line(sp, ep), color, 20, 0) # draw face -------------------------------------------------------- face_coordinates = [ xyz_dict[vkey] for vkey in cell.face_vertices(fkey) ] face_coordinates.append(face_coordinates[0]) polygon_xyz = [Point3d(*xyz) for xyz in face_coordinates] e.Display.DrawPolyline(polygon_xyz, black, 2) if fkey == face: e.Display.DrawPolyline(polygon_xyz, black, 4) e.Display.DrawPolygon(polygon_xyz, color, filled=True) # display force magnitudes ----------------------------------------- vector = add_vectors(vector, scale_vector(normalize_vector(normal), 0.75)) xyz = add_vectors(center, vector) if fkey == face: color = black e.Display.DrawDot(Point3d(*xyz), str(round(area, 2)), color, white)
def GetPlanks(name): # ============================================================================== # BGet Vertices on the boundary based on the name # ============================================================================== SOUTH = list(cablenet.vertices_where({'constraint': name})) boundary = list(cablenet.vertices_on_boundary(ordered=True)) SOUTH[:] = [key for key in boundary if key in SOUTH] # ============================================================================== # Boundary plane # ============================================================================== a = cablenet.vertex_coordinates(SOUTH[0]) b = cablenet.vertex_coordinates(SOUTH[-1]) xaxis = subtract_vectors(b, a) yaxis = [0, 0, 1.0] zaxis = cross_vectors(xaxis, yaxis) xaxis = cross_vectors(yaxis, zaxis) frame = Frame(a, xaxis, yaxis) point = add_vectors(frame.point, scale_vector(frame.zaxis, OFFSET)) normal = frame.zaxis plane = point, normal # ============================================================================== # Intersections # ============================================================================== intersections = [] for key in SOUTH: a = cablenet.vertex_coordinates(key) r = cablenet.residual(key) b = add_vectors(a, r) x, y, z = intersection_line_plane((a, b), plane) intersections.append(Point(x, y, z)) # ============================================================================== # Bounding boxes # ============================================================================== limitLength = 2 limitSmall = 0.12 frame_box_len_All = [] start = 0 end = start + 2 #len(intersections) #print("start " + str(start)) while end <= len(intersections): frame_box_len = [] flag = True while (flag and end <= len(intersections)): #print((str)(start) + " " + (str)(end)) #print("number of points " + str(start) + "-" + str(end) ) frame_box_lenTemp = GetBoundingBox(pca_numpy, intersections, PADDING, start, end, frame) numOfPts = end - start """ if(numOfPts==2): end+=1 continue """ #if(numOfPts==2): """ print(frame_box_lenTemp) frame_box_len = frame_box_lenTemp end+=1 break """ """ if(frame_box_lenTemp[2]>limitLength): flag = False print("end" + str(end)) break """ #Check the widht of the plank #print(frame_box_lenTemp[2]) if (frame_box_lenTemp[3] > limitSmall or frame_box_lenTemp[2] > limitLength): flag = False #print("end" + str(end)) break """ if(frame_box_lenTemp[3]>limitSmall and frame_box_lenTemp[2]>limitLength): flag = False print("end" + str(end)) break """ frame_box_len = frame_box_lenTemp end += 1 start = end - 2 end = start + 2 frame_box_len_All.append(frame_box_len) #print("start " + str(start)) return [frame_box_len_All, intersections]
point = add_vectors(frame.point, scale_vector(frame.zaxis, OFFSET)) normal = frame.zaxis plane = point, normal # ============================================================================== # Compute the intersections of the residual force vectors at the boundary # vertices with the previously defined intersection plane. # ============================================================================== intersections = [] for key in SOUTH: a = cablenet.vertex_coordinates(key) r = cablenet.residual(key) b = add_vectors(a, r) x = intersection_line_plane((a, b), plane) intersections.append(x) # ============================================================================== # Select the first 6 vertices of the boundary for the first segment of the # supporting structure. Compute a local frame for the selected vertices using a # PCA of the vertex locations. # ============================================================================== points = intersections[:6] origin, axes, values = pca_numpy(points) frame1 = Frame(origin, axes[0], axes[1]) # ==============================================================================
# artist.draw() # # # ============================================================================== # # # Compute the intersections of the residual force vectors at the boundary # # # vertices with the previously defined intersection plane. # # # ============================================================================== intersections_front = [] intersections_back = [] pca_points = [] for key in l: a = cablenet.vertex_coordinates(key) r = cablenet.residual(key) b = add_vectors(a, r) x_front = intersection_line_plane((a, b), plane_front) x_back = intersection_line_plane((a, b), plane_back) move_point_to_front = add_vectors( x_back, scale_vector(frame_0.zaxis, -THICKNESS)) intersections_front.append(x_front) intersections_back.append(x_back) pca_points.append(x_front) pca_points.append(move_point_to_front) PointArtist.draw_collection(intersections_back, layer=name + "::Intersections_back", clear=True) PointArtist.draw_collection(pca_points, layer=name + "::Intersections_front", clear=True)