def compas_mesh_to_occ_shell(mesh: Mesh) -> TopoDS_Shell: """Convert a general COMPAS mesh to an OCC shell. Parameters ---------- mesh : :class:`~compas.datastructures.Mesh` A COMPAS mesh data structure. Returns ------- TopoDS_Shell """ # https://github.com/tpaviot/pythonocc-demos/blob/master/examples/core_geometry_geomplate.py shell = TopoDS_Shell() builder = BRep_Builder() builder.MakeShell(shell) for face in mesh.faces(): points = mesh.face_coordinates(face) if len(points) == 3: builder.Add(shell, triangle_to_face(points)) elif len(points) == 4: builder.Add(shell, quad_to_face(points)) else: builder.Add(shell, ngon_to_face(points)) return shell
def compas_quadmesh_to_occ_shell(mesh: Mesh) -> TopoDS_Shell: """Convert a COMPAS quad mesh to an OCC shell. Parameters ---------- mesh : :class:`~compas.datastructures.Mesh` A COMPAS mesh data structure with quad faces. Returns ------- TopoDS_Shell Raises ------ AssertionError If the input mesh is not a quad mesh. """ assert mesh.is_quadmesh(), "The input mesh is not a quad mesh." shell = TopoDS_Shell() builder = BRep_Builder() builder.MakeShell(shell) for face in mesh.faces(): points = mesh.face_coordinates(face) builder.Add(shell, quad_to_face(points)) return shell
def from_mesh(cls: 'MeshModel', mesh: Mesh, name: str = 'Mesh', targetlength: float = 1.0) -> None: model = cls(name) model.vertex_tag = {} for vertex in mesh.vertices(): point = mesh.vertex_coordinates(vertex) model.vertex_tag[vertex] = model.occ.add_point( *point, targetlength) for face in mesh.faces(): loop = [] for u, v in mesh.face_halfedges(face): tag = model.occ.add_line(model.vertex_tag[u], model.vertex_tag[v]) loop.append(tag) tag = model.occ.add_curve_loop(loop) model.occ.add_surface_filling(tag) return model
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()]
# ========================================================================== vector_tag = 'ps_1_top' lines = vector_lines_on_faces(mesh, vector_tag, True, factor=0.05) lines = [line for line in map(line_tuple_to_dict, lines)] for line in lines: line['width'] = 0.60 # ========================================================================== # Instantiate StructuralMesh() # ========================================================================== str_mesh = StructuralMesh(mesh) for tag in tags: vector_field = mesh.get_faces_attribute(keys=list(mesh.faces()), name=tag) str_mesh.set_face_vectors(vector_field, tag, normalize=True) str_mesh.set_vertex_vectors_angles(tag) # str_mesh.get_edge_labels(vector_tag, 0.01) str_mesh.get_face_labels(vector_tag, 0.0) umbilic_keys = list( str_mesh.c_mesh.faces_where_predicate( lambda f_key, attr: attr['label'] != 1)) not_umbilic_keys = list( str_mesh.c_mesh.faces_where_predicate( lambda f_key, attr: attr['label'] == 1)) umbilics = [str_mesh.c_mesh.face_centroid(fkey) for fkey in umbilic_keys] # ==========================================================================
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()]
else: mesh.face_attribute(fk, 'ftype', 'panel') 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) f = mesh.add_face([a, b, c, d]) mesh = sd.mesh_subdivide_tri(mesh) mesh = sd.mesh_subdivide_quad(mesh) fkeys = list(mesh.faces()) for fk in fkeys: new_keys = msd.segment_face(mesh, fk, num=2, start_index=0) for key in new_keys: mesh.face_attribute(key, "ftype", "plot") # artist = MeshArtist(mesh, layer="level1") # artist.clear_layer() # artist.draw_faces( join_faces=True) m1 = mesh.copy() subdivide_by_ftype(m1) # artist2 = MeshArtist(m1, layer="level2")
# Import mesh # ========================================================================== mesh = Mesh() mesh.load(HERE) mesh_unify_cycles(mesh) # ========================================================================== # Create PS vector lines # ========================================================================== vector_tag = 'ps_1_top' # ps_1_top angles = {} centroids = {} for fkey, attr in mesh.faces(data=True): vector = attr.get(vector_tag) angle = angle_vectors([1.0, 0.0, 0.0], vector, deg=True) angles[fkey] = angle centroids[fkey] = np.array(mesh.face_centroid(fkey)) print('max angle', min(angles.values())) print('min angle', max(angles.values())) for idx, angle in angles.items(): if angle <= 90.0: continue angles[idx] = 180.0 - angle print('max angle', min(angles.values())) print('min angle', max(angles.values()))
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()} 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.load(HERE) # ========================================================================== # 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()} 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)