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_to_compas_mesh(mesh): """Convert a mola mesh to a compas mesh. Parameters ---------- mesh : :class:`mola.Mesh` Mesh to convert. Returns ------- :class:`compas.datastructures.Mesh` """ mesh.update_topology() cmesh = CMesh() for face in mesh.faces: idx = [] dict_ = face.__dict__ vertices = dict_.pop("vertices") for vertex in vertices: dict_ = vertex.__dict__ x, y, z = dict_.pop("x"), dict_.pop("y"), dict_.pop("z") # store v attributes in attr dict i = cmesh.add_vertex(x=x, y=y, z=z, attr_dict=dict_) idx.append(i) # store f attributes in attr dict cmesh.add_face(idx, attr_dict=dict_) return cmesh
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 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 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 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
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
vec_leaf = Vector.from_start_end(mesh.vertex_coordinates(key), pt) vec_leaf.unitize() vec_leaf.scale(leaf_width) pt = add_vectors(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) # mesh.to_json('mesh1.json', pretty=True) artist = MeshArtist(mesh) artist.draw_vertices() artist.draw_faces() # artist = MeshArtist(convex_hull_mesh) # artist.draw_faces(color=(255, 0, 0)) # artist.draw_edges(color=(255, 0, 0))
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()]
from compas.datastructures import Mesh mesh = Mesh() a = mesh.add_vertex() # x,y,z coordinates are optional and default to 0,0,0 b = mesh.add_vertex(x=1) c = mesh.add_vertex(x=1, y=1) d = mesh.add_vertex(y=1) mesh.add_face([a, b, c, d]) print(mesh.summary())
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()} face = mesh.face_vertices(fkey) new_mesh.add_face(key=idx, vertices=face, attr_dict=attr_dict) all_vertices.update(face) for vkey, attr in mesh.vertices(True): if vkey not in all_vertices: continue attr_dict = {k: v for k, v in attr.items()} new_mesh.add_vertex(vkey, attr_dict=attr_dict) mesh = new_mesh # ========================================================================== # 45 degrees field # ========================================================================== # for fkey, attr in mesh.faces(True):
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) # top and bottom surface face = [geometric_key(pt) for pt in pts_a] mesh_v.add_face(face) face = [geometric_key(pt) for pt in pts_b[::-1]] mesh_v.add_face(face) artist = MeshArtist(mesh_v, layer='voussoir_hex') artist.draw_faces(join_faces=True) artist.redraw()
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()]
# 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 face_a = [key_index_a[key] for key in mesh.face_vertices(fkey)] face_b = [key_index_b[key] for key in mesh.face_vertices(fkey)] face_b.reverse() voussoir_mesh.add_face(face_a) voussoir_mesh.add_face(face_b) voussoirs_meshes[fkey] = voussoir_mesh # draw all voussoir meshes for fkey, voussoir_mesh in voussoirs_meshes.items(): # assign voussoir mesh to tessellation mesh mesh.set_face_attribute(fkey, 'voussoir', voussoir_mesh.to_data())
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) # create fins #dis = 0.5 #for u, v in trans_mesh.edges(): # normal_u = trans_mesh.vertex_normal(u) # normal_v = trans_mesh.vertex_normal(v) # pt1 = trans_mesh.vertex_coordinates(u) # pt2 = trans_mesh.vertex_coordinates(v) # pt3 = add_vectors(pt2, scale_vector(normal_v, dis)) # pt4 = add_vectors(pt1, scale_vector(normal_u, dis)) # rs.AddSrfPt([pt1, pt2, pt3, pt4])