def mesh_from_shell_elements(structure): """ Returns a Mesh datastructure object from a Structure's ShellElement objects. Parameters ---------- structure: obj The structure to extract a Mesh from. Returns ------- obj Mesh datastructure object. """ ekeys = [ ekey for ekey in structure.elements if structure.elements[ekey].__name__ == 'ShellElement' ] nkeys = {nkey for ekey in ekeys for nkey in structure.elements[ekey].nodes} mesh = Mesh() for nkey in nkeys: x, y, z = structure.node_xyz(nkey) mesh.add_vertex(key=nkey, x=x, y=y, z=z) for ekey in ekeys: mesh.add_face(structure.elements[ekey].nodes, key=ekey) return mesh
def triangulate_strips(zone): meshes = [] for faces in zone: mesh = Mesh() mesh.update_default_vertex_attributes(FABRIC.default_vertex_attributes) mesh.update_default_edge_attributes(FABRIC.default_edge_attributes) mesh.update_default_face_attributes(FABRIC.default_face_attributes) for fkey in faces: keys = FABRIC.face_vertices(fkey) for key in keys: if key not in mesh.vertex: attr = FABRIC.vertex[key].copy() mesh.add_vertex(key=key, attr_dict=attr) attr = FABRIC.facedata[fkey].copy() mesh.add_face(keys, fkey=fkey, attr_dict=attr) for u, v, attr in mesh.edges(True): for name in attr: value = FABRIC.get_edge_attribute((u, v), name) attr[name] = value trimesh = mesh.copy() mesh_quads_to_triangles(trimesh, check_angles=True) meshes.append([mesh, trimesh]) return meshes
def mesh_fast_copy(other): subd = Mesh() subd.vertex = deepcopy(other.vertex) subd.face = deepcopy(other.face) subd.facedata = deepcopy(other.facedata) subd.halfedge = deepcopy(other.halfedge) subd._max_face = other._max_face subd._max_vertex = other._max_vertex return subd
def join_meshes(meshes): joined = Mesh() for mesh in meshes: for f in mesh.faces(): vertices = mesh.face_vertices(f) points = mesh.get_vertices_attributes('xyz', keys=vertices) for p in points: joined.add_vertex(x=p[0], y=p[1], z=p[2]) joined.add_face(vertices) return joined
def quadmesh_no_attr(): """ Mesh with 4 vertices and 1 face. """ mesh = Mesh() a = mesh.add_vertex(x=0, y=0, z=0) b = mesh.add_vertex(x=1, y=0, z=0) c = mesh.add_vertex(x=1, y=1, z=0) d = mesh.add_vertex(x=0, y=1, z=0) mesh.add_face([a, b, c, d]) return mesh
def trimesh_attr(vector_tag): """ Mesh with 3 vertices, 1 face, and one attribute. """ mesh = Mesh() a = mesh.add_vertex(x=0.0, y=0.0, z=0.0) b = mesh.add_vertex(x=1.0, y=0.0, z=0.0) c = mesh.add_vertex(x=1.0, y=1.0, z=0.0) fkey = mesh.add_face([a, b, c]) mesh.face_attribute(key=fkey, name=vector_tag, value=[0.0, 1.0, 0.0]) return mesh
def test_constructor(): mesh = Mesh() a = mesh.add_vertex() b = mesh.add_vertex(x=1.0) c = mesh.add_vertex(x=1.0, y=1.0) d = mesh.add_vertex(y=1.0) mesh.add_face([a, b, c, d]) assert mesh.vertex_coordinates(a) == [0.0, 0.0, 0.0] assert mesh.vertex_coordinates(b) == [1.0, 0.0, 0.0] assert mesh.vertex_coordinates(c) == [1.0, 1.0, 0.0] assert mesh.vertex_coordinates(d) == [0.0, 1.0, 0.0] assert mesh.vertex_coordinates(a) == mesh.vertex_attributes(a, 'xyz') assert mesh.vertex_coordinates(b) == mesh.vertex_attributes(b, 'xyz') assert mesh.vertex_coordinates(c) == mesh.vertex_attributes(c, 'xyz') assert mesh.vertex_coordinates(d) == mesh.vertex_attributes(d, 'xyz')
def volmesh_merge_adjacent_halffaces(volmesh, hfkeys): # check halffaces ---------------------------------------------------------- for hfkey in hfkeys: if not volmesh.is_halfface_on_boundary(hfkey): raise ValueError('Halfface {} is interior.'.format(hfkey)) if not _are_halffaces_chained(volmesh, hfkeys): raise ValueError('These halffaces are not chained.') # -------------------------------------------------------------------------- halffaces = [volmesh.halfface[hfkey] for hfkey in hfkeys] # -------------------------------------------------------------------------- vkeys = set() for hfkey in hfkeys: for key in volmesh.halfface_vertices(hfkey): vkeys.add(key) vkeys = list(vkeys) points = [volmesh.vertex_coordinates(vkey) for vkey in vkeys] faces_by_index = convex_hull(points) faces_by_vkeys = [] for face in faces_by_index: faces_by_vkeys.append([vkeys[index] for index in face]) # make temp cell mesh ------------------------------------------------------ cell = Mesh() for i in range(len(vkeys)): key = vkeys[i] x, y, z = points[i] cell.add_vertex(key=key, x=x, y=y, z=z) for face in faces_by_vkeys: cell.add_face(face) # merge coplanar faces ----------------------------------------------------- cell_merge_coplanar_adjacent_faces(cell) # get correct direction of faces ------------------------------------------- faces = [cell.face[fkey] for fkey in cell.face] if halffaces[0] in faces: new_faces = [face[::-1] for face in faces] else: new_faces = faces volmesh.add_cell(new_faces) return volmesh
def mesh(): """ A COMPAS mesh with two vectors stored as face attributes. """ _mesh = Mesh() # add vertices for i in range(4): _mesh.add_vertex(key=i) # right-hand side winding -- normals pointing up _mesh.add_face(fkey=0, vertices=[0, 1, 2]) _mesh.add_face(fkey=1, vertices=[0, 2, 3]) name = "my_vector_field" _mesh.face_attribute(key=0, name=name, value=[0.0, 0.0, 1.0]) _mesh.face_attribute(key=1, name=name, value=[0.0, 0.0, 2.0]) return _mesh
def mesh(vectors): """ A COMPAS mesh with three vectors stored as face attributes. """ _mesh = Mesh() # add vertices for i in range(5): _mesh.add_vertex(key=i, x=i, y=i, z=i) # right-hand side winding -- normals pointing up _mesh.add_face(fkey=0, vertices=[0, 1, 2]) _mesh.add_face(fkey=1, vertices=[0, 2, 3]) _mesh.add_face(fkey=2, vertices=[0, 3, 4]) name = "my_vector_field" _mesh.face_attribute(key=0, name=name, value=vectors[0]) _mesh.face_attribute(key=1, name=name, value=vectors[1]) _mesh.face_attribute(key=2, name=name, value=vectors[2]) return _mesh
def join_meshes(meshes, cull_duplicates=False, precision='3f'): """Join multiple meshes. Parameters ---------- meshes : Meshes A list of mesh objects. cull_duplicates: Boolean True if resulting duplicate vertices should be deleted False otherwise """ count = 0 mesh_all = Mesh() map = {} for mesh in meshes: faces = list(mesh.faces()) vertices = list(mesh.faces()) for key, attr in mesh.vertices(True): mesh_all.add_vertex(count, x=attr['x'], y=attr['y'], z=attr['z'], attr_dict=attr) map[key] = count count += 1 for fkey, attr in mesh.faces(True): vertices = mesh.face_vertices(fkey) new_vertices = [map[key] for key in vertices] mesh_all.add_face(new_vertices) if cull_duplicates: mesh_cull_duplicate_vertices(mesh_all, precision) return mesh_all
joints = [] for key in network.node: if network.is_leaf(key): leafs.append(key) else: joints.append(key) pt_center = network.node_coordinates(joints[0]) pts = [network.node_coordinates(key) for key in leafs] joint_width = 15 leaf_width = 7 convex_hull_mesh = get_convex_hull_mesh(pts) mesh = Mesh() for key in convex_hull_mesh.vertices(): mesh.add_vertex(key) mesh.vertex[key].update(convex_hull_mesh.vertex[key]) descdent_tree = copy.deepcopy(convex_hull_mesh.halfedge) for u, v in convex_hull_mesh.edges(): descdent_tree[u][v] = {'jp': None, 'lp': None} descdent_tree[v][u] = {'jp': None, 'lp': None} current_key = convex_hull_mesh.number_of_vertices() for fkey in convex_hull_mesh.faces(): f_centroid = convex_hull_mesh.face_centroid(fkey) vec = Vector.from_start_end(pt_center, f_centroid)
def delaunay_from_points(points, boundary=None, holes=None, tiny=1e-12): """Computes the delaunay triangulation for a list of points. Parameters ---------- points : sequence of tuple XYZ coordinates of the original points. boundary : sequence of tuples list of ordered points describing the outer boundary (optional) holes : list of sequences of tuples list of polygons (ordered points describing internal holes (optional) Returns ------- list The faces of the triangulation. Each face is a triplet of indices referring to the list of point coordinates. Notes ----- For more info, see [1]_. References ---------- .. [1] Sloan, S. W., 1987 *A fast algorithm for constructing Delaunay triangulations in the plane* Advances in Engineering Software 9(1): 34-55, 1978. Example ------- .. plot:: :include-source: from compas.datastructures import Mesh from compas.geometry import pointcloud_xy from compas.geometry import delaunay_from_points from compas_plotters import MeshPlotter points = pointcloud_xy(20, (0, 50)) faces = delaunay_from_points(points) delaunay = Mesh.from_vertices_and_faces(points, faces) plotter = MeshPlotter(delaunay) plotter.draw_vertices(radius=0.1) plotter.draw_faces() plotter.show() """ from compas.datastructures import Mesh from compas.datastructures import trimesh_swap_edge def super_triangle(coords): centpt = centroid_points(coords) bbpts = bounding_box(coords) dis = distance_point_point(bbpts[0], bbpts[2]) dis = dis * 300 v1 = (0 * dis, 2 * dis, 0) v2 = (1.73205 * dis, -1.0000000000001 * dis, 0) # due to numerical issues v3 = (-1.73205 * dis, -1 * dis, 0) pt1 = add_vectors(centpt, v1) pt2 = add_vectors(centpt, v2) pt3 = add_vectors(centpt, v3) return pt1, pt2, pt3 mesh = Mesh() # to avoid numerical issues for perfectly structured point sets points = [(point[0] + random.uniform(-tiny, tiny), point[1] + random.uniform(-tiny, tiny), 0.0) for point in points] # create super triangle pt1, pt2, pt3 = super_triangle(points) # add super triangle vertices to mesh n = len(points) super_keys = n, n + 1, n + 2 mesh.add_vertex(super_keys[0], {'x': pt1[0], 'y': pt1[1], 'z': pt1[2]}) mesh.add_vertex(super_keys[1], {'x': pt2[0], 'y': pt2[1], 'z': pt2[2]}) mesh.add_vertex(super_keys[2], {'x': pt3[0], 'y': pt3[1], 'z': pt3[2]}) mesh.add_face(super_keys) # iterate over points for i, pt in enumerate(points): key = i # newtris should be intialised here # check in which triangle this point falls for fkey in list(mesh.faces()): # abc = mesh.face_coordinates(fkey) #This is slower # This is faster: keya, keyb, keyc = mesh.face_vertices(fkey) dicta = mesh.vertex[keya] dictb = mesh.vertex[keyb] dictc = mesh.vertex[keyc] a = [dicta['x'], dicta['y']] b = [dictb['x'], dictb['y']] c = [dictc['x'], dictc['y']] if is_point_in_triangle_xy(pt, [a, b, c], True): # generate 3 new triangles (faces) and delete surrounding triangle key, newtris = mesh.insert_vertex(fkey, key=key, xyz=pt, return_fkeys=True) break while newtris: fkey = newtris.pop() # get opposite_face keys = mesh.face_vertices(fkey) s = list(set(keys) - set([key])) u, v = s[0], s[1] fkey1 = mesh.halfedge[u][v] if fkey1 != fkey: fkey_op, u, v = fkey1, u, v else: fkey_op, u, v = mesh.halfedge[v][u], u, v if fkey_op: keya, keyb, keyc = mesh.face_vertices(fkey_op) dicta = mesh.vertex[keya] a = [dicta['x'], dicta['y']] dictb = mesh.vertex[keyb] b = [dictb['x'], dictb['y']] dictc = mesh.vertex[keyc] c = [dictc['x'], dictc['y']] circle = circle_from_points_xy(a, b, c) if is_point_in_circle_xy(pt, circle): fkey, fkey_op = trimesh_swap_edge(mesh, u, v) newtris.append(fkey) newtris.append(fkey_op) # Delete faces adjacent to supertriangle for key in super_keys: mesh.delete_vertex(key) # Delete faces outside of boundary if boundary: for fkey in list(mesh.faces()): centroid = mesh.face_centroid(fkey) if not is_point_in_polygon_xy(centroid, boundary): mesh.delete_face(fkey) # Delete faces inside of inside boundaries if holes: for polygon in holes: for fkey in list(mesh.faces()): centroid = mesh.face_centroid(fkey) if is_point_in_polygon_xy(centroid, polygon): mesh.delete_face(fkey) return [mesh.face_vertices(fkey) for fkey in mesh.faces()]
def test_is_empty(): mesh = Mesh() assert mesh.is_empty() mesh.add_vertex() assert not mesh.is_empty()
# compute offset points for key in mesh.vertices(): pt = mesh.vertex_coordinates(key) normal = mesh.vertex_normal(key) pt_a = add_vectors(pt, scale_vector(normal, thickness * .5)) pt_b = add_vectors(pt, scale_vector(normal, thickness * -.5)) mesh.set_vertex_attribute(key, 'point_a', pt_a) mesh.set_vertex_attribute(key, 'point_b', pt_b) for fkey in mesh.faces(): vertices = mesh.face_vertices(fkey) pts_a = [mesh.get_vertex_attribute(key, 'point_a') for key in vertices] pts_b = [mesh.get_vertex_attribute(key, 'point_b') for key in vertices] # initialize mesh for voussoir mesh_v = Mesh() # vertices for voussoir for pt in pts_a + pts_b: x, y, z = pt mesh_v.add_vertex(key=geometric_key(pt), x=x, y=y, z=z) # side surfaces for i, _ in enumerate(pts_a): face = [ geometric_key(pts_a[i - 1]), geometric_key(pts_b[i - 1]), geometric_key(pts_b[i]), geometric_key(pts_a[i]) ] mesh_v.add_face(face)
def delaunay_from_points(points, boundary=None, holes=None, tiny=1e-12): """Computes the delaunay triangulation for a list of points. Parameters ---------- points : sequence[[float, float, float] | :class:`compas.geometry.Point`] XYZ coordinates of the original points. boundary : sequence[[float, float, float] | :class:`compas.geometry.Point`] | :class:`compas.geometry.Polygon`, optional List of ordered points describing the outer boundary. holes : sequence[sequence[[float, float, float] | :class:`compas.geometry.Point`] | :class:`compas.geometry.Polygon`], optional List of polygons (ordered points describing internal holes. Returns ------- list[[int, int, int]] The faces of the triangulation. Each face is a triplet of indices referring to the list of point coordinates. Notes ----- For more info, see [1]_. References ---------- .. [1] Sloan, S. W., 1987 *A fast algorithm for constructing Delaunay triangulations in the plane* Advances in Engineering Software 9(1): 34-55, 1978. Examples -------- >>> """ from compas.datastructures import Mesh from compas.datastructures import trimesh_swap_edge def super_triangle(coords, ccw=True): centpt = centroid_points(coords) bbpts = bounding_box(coords) dis = distance_point_point(bbpts[0], bbpts[2]) dis = dis * 300 v1 = (0 * dis, 2 * dis, 0) v2 = (1.73205 * dis, -1.0000000000001 * dis, 0 ) # due to numerical issues v3 = (-1.73205 * dis, -1 * dis, 0) pt1 = add_vectors(centpt, v1) pt2 = add_vectors(centpt, v2) pt3 = add_vectors(centpt, v3) if ccw: return pt1, pt3, pt2 return pt1, pt2, pt3 mesh = Mesh() # to avoid numerical issues for perfectly structured point sets points = [(point[0] + random.uniform(-tiny, tiny), point[1] + random.uniform(-tiny, tiny), 0.0) for point in points] # create super triangle pt1, pt2, pt3 = super_triangle(points) # add super triangle vertices to mesh n = len(points) super_keys = n, n + 1, n + 2 mesh.add_vertex(super_keys[0], {'x': pt1[0], 'y': pt1[1], 'z': pt1[2]}) mesh.add_vertex(super_keys[1], {'x': pt2[0], 'y': pt2[1], 'z': pt2[2]}) mesh.add_vertex(super_keys[2], {'x': pt3[0], 'y': pt3[1], 'z': pt3[2]}) mesh.add_face(super_keys) # iterate over points for key, point in enumerate(points): # newtris should be intialised here # check in which triangle this point falls for fkey in list(mesh.faces()): abc = mesh.face_coordinates(fkey) if is_point_in_triangle_xy(point, abc, True): # generate 3 new triangles (faces) and delete surrounding triangle key, newtris = mesh.insert_vertex(fkey, key=key, xyz=point, return_fkeys=True) break while newtris: fkey = newtris.pop() face = mesh.face_vertices(fkey) i = face.index(key) u = face[i - 2] v = face[i - 1] nbr = mesh.halfedge[v][u] if nbr is not None: a, b, c = mesh.face_coordinates(nbr) circle = circle_from_points_xy(a, b, c) if is_point_in_circle_xy(point, circle): fkey, nbr = trimesh_swap_edge(mesh, u, v) newtris.append(fkey) newtris.append(nbr) # Delete faces adjacent to supertriangle for key in super_keys: mesh.delete_vertex(key) # Delete faces outside of boundary if boundary: for fkey in list(mesh.faces()): centroid = mesh.face_centroid(fkey) if not is_point_in_polygon_xy(centroid, boundary): mesh.delete_face(fkey) # Delete faces inside of inside boundaries if holes: for polygon in holes: for fkey in list(mesh.faces()): centroid = mesh.face_centroid(fkey) if is_point_in_polygon_xy(centroid, polygon): mesh.delete_face(fkey) return [mesh.face_vertices(fkey) for fkey in mesh.faces()]
faces_list.append([key_index_a[u], key_index_a[v], key_index_b[v], key_index_b[u]]) # planarize interfaces if 0: planarize_faces(vertices_list, faces_list, kmax=150, callback=callback) layer = 'voussoirs_planar' else: layer = 'voussoirs_ruled' # create mesh per voussoir/block voussoirs_meshes = {} for fkey in mesh.faces(): # initiate mesh object voussoir_mesh = Mesh() # loop over edges of face (fkey) for u,v in mesh.face_halfedges(fkey): # add top vertices of face x, y, z = vertices_list[key_index_a[u]] voussoir_mesh.add_vertex(key_index_a[u],x=x,y=y,z=z) # add bottom vertices of face x, y, z = vertices_list[key_index_b[u]] voussoir_mesh.add_vertex(key_index_b[u],x=x,y=y,z=z) # add interfaces face = [key_index_a[v], key_index_a[u], key_index_b[u], key_index_b[v]] voussoir_mesh.add_face(face) # add top and bottom faces
def find_devisions(mesh, edge_groups, trg_len): for edges in edge_groups: lengths = 0 for u, v in edges: lengths += mesh.get_edge_attribute((u, v), 'length') ave_len = lengths / len(edges) div = max((round(ave_len / trg_len, 0), 1)) for u, v in edges: crv = mesh.get_edge_attribute((u, v), 'guid') pts = rs.DivideCurve(crv, div) mesh.set_edge_attribute((u, v), 'points', pts) edges = set(mesh.edges()) coons_meshes = [] for fkey in mesh.faces(): h_edges = mesh.face_halfedges(fkey) # arrange point lists in circular order along edge faces pts_coon = [] for h_edge in h_edges: pts = mesh.get_edge_attribute(h_edge, 'points')[:] if not h_edge in edges: pts.reverse() if not mesh.get_edge_attribute(h_edge, 'dir'): pts.reverse() pts_coon.append(pts) # handle triangles correctly based on user input (flag 0 - 2) lengths = [len(pts_coon[0]), len(pts_coon[1])] if len(h_edges) == 4: ab, bc, dc, ad = pts_coon else: flag = mesh.get_face_attribute(fkey, 'corner') if flag == 0: ab, bc, dc, ad = pts_coon[0], pts_coon[1], [], pts_coon[2] elif flag == 1: ab, bc, dc, ad = pts_coon[0], [], pts_coon[1], pts_coon[2] lengths = [len(pts_coon[0]), len(pts_coon[2])] elif flag == 2: ab, bc, dc, ad = pts_coon[0], pts_coon[1], pts_coon[2], [] # reverse for coons patch (see parameters) dc.reverse() ad.reverse() vertices, faces = discrete_coons_patch(ab, bc, dc, ad) coons_meshes.append((vertices, faces, lengths)) # join al sub "meshes" of the coons patches in one mesh (with duplicate vertices) inc = 0 mesh = Mesh() for coons_mesh in coons_meshes: vertices, faces, lengths = coons_mesh a, b = lengths indices = [] for i, pt in enumerate(vertices): indices.append(i) pass indices = indices[::b] + indices[b - 1::b] + indices[:b] + indices[ (a - 1) * b:] indices = set(indices) for i, pt in enumerate(vertices): if i in indices: attr = {'coon_bound': True} else: attr = {'coon_bound': False} mesh.add_vertex(i + inc, x=pt[0], y=pt[1], z=pt[2], attr_dict=attr) for face in faces: face = [key + inc for key in face] mesh.add_face(face) inc += len(vertices) return mesh
]) # Displacements mdl.add([ RollerDisplacementXY(name='disp_edges', nodes='nset_edges'), PinnedDisplacement(name='disp_pinned', nodes='nset_corner1'), GeneralDisplacement(name='disp_xdof', nodes='nset_corner2', x=0), ]) # Loads mdl.add([ GravityLoad(name='load_gravity', elements=['elset_ribs', 'elset_vault']), PrestressLoad(name='load_prestress', elements='elset_ties', sxx=10*10**6), TributaryLoad(mdl, name='load_area', mesh=mesh_from_guid(Mesh(), rs.ObjectsByLayer('load_mesh')[0]), z=-2000), ]) # Steps mdl.add([ GeneralStep(name='step_bc', displacements=['disp_edges', 'disp_pinned', 'disp_xdof']), GeneralStep(name='step_loads', loads=['load_gravity', 'load_area'], factor={'load_gravity': 1.35, 'load_area': 1.50}), ]) mdl.steps_order = ['step_bc', 'step_loads'] # Summary mdl.summary() # Run
# create planes along the rail curve planes = [] for i in range(div_r): vec = subtract_vectors(pts_a[i + 1], pts_a[i]) planes.append([pts_a[i], vec]) # subsequentely project profile curve to all planes pts_uv = [] pts = pts_p for i in range(div_r - 1): pts = project_points_plane(pts, planes[i]) pts_uv.append(pts) # create mesh object trans_mesh = Mesh() # add vertices for u in xrange(len(pts_uv)): for v in xrange(len(pts_uv[u])): x, y, z = pts_uv[u][v] trans_mesh.add_vertex((u, v), x=x, y=y, z=z) # add faces for u in xrange(len(pts_uv) - 1): for v in xrange(len(pts_uv[u]) - 1): trans_mesh.add_face([(u, v), (u + 1, v), (u + 1, v + 1), (u, v + 1)]) artist = MeshArtist(trans_mesh, layer='voussoir_hex') artist.draw_faces(join_faces=True)
] vector_tag_1 = 'ps_1_top' vector_tag_2 = 'ps_2_top' vector_tag = 'ps_1_2_top' # bisector vector_tag = vector_tag_1 smooth_iters = 100 n_clusters = 4 sigma = 2.0 # ========================================================================== # Import mesh # ========================================================================== mesh = Mesh() new_mesh = Mesh() mesh.load(HERE) # ========================================================================== # rebuild mesh # ========================================================================== all_vertices = set() for idx, tup in enumerate(mesh.faces(True)): fkey, attr = tup if mesh.face_centroid(fkey)[0] < 0.0: # mesh deleter by symmetry continue attr_dict = {k: v for k, v in attr.items()}
section='sec_ends', elset='elset_ends'), ]) # Displacements mdl.add([ RollerDisplacementY(name='disp_top', nodes='nset_top'), RollerDisplacementY(name='disp_bot', nodes='nset_bot'), ]) # Loads mdl.add(GravityLoad(name='load_gravity', elements='elset_mesh')) mesh = mesh_from_guid(Mesh(), rs.ObjectsByLayer('elset_mesh')[0]) point_loads = {} for key in mesh.vertices(): xyz = mesh.vertex_coordinates(key) pt = rs.ProjectPointToSurface([xyz], rs.ObjectsByLayer('surface')[0], [0, 0, 1])[0] pz = mesh.vertex_area(key) * distance_point_point(xyz, pt) * 2400 * 9.81 point_loads[mdl.check_node_exists(xyz)] = {'z': -pz} mdl.add(PointLoads(name='load_points', components=point_loads)) # Steps displacements = ['disp_top', 'disp_bot'] loads = ['load_gravity', 'load_points']
class SkeletonVol(Mesh): """ SkeletonVol is typologically constructed low poly mesh. It construct a branch like volumetric mesh from input lines. """ def __init__(self): super(SkeletonVol, self).__init__() @classmethod def from_skeleton_lines(cls, lines=[]): skeleton_vol = cls() network = Network.from_lines(lines) convex_hull_mesh = get_convex_hull_mesh(points) def get_convex_hull_mesh(points): faces = convex_hull(points) vertices = list(set(flatten(faces))) i_index = {i: index for index, i in enumerate(vertices)} vertices = [points[index] for index in vertices] faces = [[i_index[i] for i in face] for face in faces] faces = unify_cycles(vertices, faces) mesh = Mesh.from_vertices_and_faces(vertices, faces) return mesh guids = compas_rhino.select_lines() lines = compas_rhino.get_line_coordinates(guids) network = Network.from_lines(lines) leafs = [] joints = [] for key in network.node: if network.is_leaf(key): leafs.append(key) else: joints.append(key) pt_center = network.node_coordinates(joints[0]) pts = [network.node_coordinates(key) for key in leafs] convex_hull_mesh = get_convex_hull_mesh(pts) mesh = Mesh() # for key in convex_hull_mesh.vertices(): # mesh.add_vertex(key) # mesh.vertex[key].update(convex_hull_mesh.vertex[key]) descdent_tree = copy.deepcopy(convex_hull_mesh.halfedge) for u, v in convex_hull_mesh.edges(): descdent_tree[u][v] = {'jp': None, 'lp': None} descdent_tree[v][u] = {'jp': None, 'lp': None} # current_key = convex_hull_mesh.number_of_vertices() current_key = 0 for fkey in convex_hull_mesh.faces(): f_centroid = convex_hull_mesh.face_centroid(fkey) vec = Vector.from_start_end(pt_center, f_centroid) # if the branches has a 'convex' corner, # flip the vec to the corresponding face. f_normal = convex_hull_mesh.face_normal(fkey) angle = angle_vectors(f_normal, vec, False) if angle > math.pi * 0.5: pln = Plane(pt_center, f_normal) pt_mirror = mirror_point_plane(f_centroid, pln) vec = Vector.from_start_end(pt_center, pt_mirror) vec.unitize() vec.scale(joint_width) pt = add_vectors(pt_center, vec) face = convex_hull_mesh.face[fkey] v_keys = face + [face[0]] for u, v in pairwise(v_keys): descdent_tree[u][v].update({'jp': current_key}) mesh.add_vertex(current_key) mesh.vertex[current_key].update({'x': pt[0], 'y': pt[1], 'z': pt[2]}) current_key += 1 for key in convex_hull_mesh.vertices(): nbrs = convex_hull_mesh.vertex_neighbors(key) for nbr in nbrs: halfedge = (key, nbr) pt_joint_descendent = mesh.vertex_coordinates( descdent_tree[key][nbr]['jp']) vec_edge = Vector.from_start_end( pt_center, convex_hull_mesh.vertex_coordinates(key)) pln_end = Plane(convex_hull_mesh.vertex_coordinates(key), vec_edge) pt = project_point_plane(pt_joint_descendent, pln_end) vec_leaf = Vector.from_start_end( convex_hull_mesh.vertex_coordinates(key), pt) vec_leaf.unitize() vec_leaf.scale(leaf_width) pt = add_vectors(convex_hull_mesh.vertex_coordinates(key), vec_leaf) descdent_tree[key][nbr].update({'lp': current_key}) mesh.add_vertex(current_key) mesh.vertex[current_key].update({ 'x': pt[0], 'y': pt[1], 'z': pt[2] }) current_key += 1 for key in convex_hull_mesh.vertices(): nbrs = convex_hull_mesh.vertex_neighbors(key, ordered=True) v_keys = nbrs + [nbrs[0]] for a, b in pairwise(v_keys): face = [ descdent_tree[key][a]['lp'], descdent_tree[key][a]['jp'], descdent_tree[key][b]['jp'], descdent_tree[key][b]['lp'] ] mesh.add_face(face) fixed = list(mesh.vertices_where({'vertex_degree': 3})) fixed = list(mesh.vertices()) mesh = mesh_subdivide_catmullclark(mesh, k=1, fixed=fixed) # mesh = mesh_subdivide_quad(mesh, k=1) mesh_smooth_centroid(mesh, fixed=fixed) artist = MeshArtist(mesh) artist.draw_mesh()