def solve_triangular_faces(self): """Modify the decomposition mesh from polylines to make it a quad mesh by converting the degenerated quad faces that appear as triangular faces. """ mesh = self.mesh for fkey in list(mesh.faces()): if len(mesh.face_vertices(fkey)) == 3: boundary_vertices = [vkey for vkey in mesh.face_vertices(fkey) if mesh.is_vertex_on_boundary(vkey)] case = sum(mesh.is_vertex_on_boundary(vkey) for vkey in mesh.face_vertices(fkey)) if case == 1: #convert triangular face to quad by duplicating the boundary vertex #due to compas_singular face vertices at the same location u = boundary_vertices[0] v = mesh.add_vertex(attr_dict = {attr: xyz for attr, xyz in zip(['x', 'y', 'z'], mesh.vertex_coordinates(u))}) # modify adjacent faces vertex_faces = mesh.vertex_faces(u, ordered = True) mesh_substitute_vertex_in_faces(mesh, u, v, vertex_faces[: vertex_faces.index(fkey)]) # modify triangular face mesh_insert_vertex_on_edge(mesh, u, mesh.face_vertex_ancestor(fkey, u), v) elif case == 2: # remove triangular face and merge the two boundary vertices # due to singularities at the same location polyline = Polyline(self.decomposition_polyline(*map(lambda x: geometric_key(mesh.vertex_coordinates(x)), boundary_vertices))) point = polyline.point(t = .5, snap = True) new_vkey = mesh.add_vertex(attr_dict = {'x': point.x, 'y': point.y , 'z': point.z}) # modify triangular face mesh.delete_face(fkey) # modify adjacent faces for old_vkey in boundary_vertices: mesh_substitute_vertex_in_faces(mesh, old_vkey, new_vkey, mesh.vertex_faces(old_vkey)) mesh.delete_vertex(old_vkey) to_move = {} # give some length to the new edge for edge in mesh.edges(): threshold = 1e-6 if mesh.edge_length(*edge) < threshold: for vkey in edge: xyz = centroid_points([mesh.vertex_coordinates(nbr) for nbr in mesh.vertex_neighbors(vkey)]) xyz0 = mesh.vertex_coordinates(vkey) to_move[vkey] = [0.1 * (a - a0) for a, a0 in zip(xyz, xyz0)] for vkey, xyz in to_move.items(): attr = mesh.vertex[vkey] attr['x'] += xyz[0] attr['y'] += xyz[1] attr['z'] += xyz[2]
def fix_boundaries(mesh, polyline_points, t=0): polyline = Polyline(polyline_points) n = len(mesh.vertices_on_boundary()) for i, vkey in enumerate(mesh.boundaries()[0]): xyz = polyline.point((t + i / n) % 1.0) mesh_move_vertex_to(mesh, xyz, vkey)
controlpoints = [ Point(0, 0, 0), Point(4, 2.5, 0), Point(6, -2.5, 0), Point(10, 0, 0) ] controlpoly = Polyline(controlpoints) curve = Bezier(controlpoints) poly = Polyline(curve.locus()) poly1 = Polyline(offset_polyline(poly, +0.15)) poly2 = Polyline(offset_polyline(poly, -0.15)) points = [poly.point(t) for t in linspace(0, 1, 20)] tangents = [(c - a).unitized() for a, b, c in window(points, 3) if a and c] normals = [Vector(0, 0, 1).cross(t) for t in tangents] lines = [[point, point + normal] for point, normal in zip(points[1:-1], normals)] points1 = [intersection_line_polyline(line, poly1) for line in lines] points2 = [intersection_line_polyline(line, poly2) for line in lines] frames = [] for a, b in pairwise(points[1:-1]): p = (a + b) * 0.5 t = (b - a).unitized() n = Vector(0, 0, 1).cross(t) frame = Frame(p, t, n) frames.append(frame)
def densification(self, edges_to_curves=None): """Generate a denser quad mesh from the coarse quad mesh and its strip densities. Returns ------- QuadMesh A denser quad mesh. """ edge_strip = {} for skey, edges in self.strips(data=True): for edge in edges: edge_strip[edge] = skey edge_strip[tuple(reversed(edge))] = skey pole_map = tuple([ geometric_key(self.vertex_coordinates(pole)) for pole in self.poles() ]) meshes = [] for fkey in self.faces(): #polylines = [[self.edge_point(u, v, float(i) / float(self.get_strip_density(edge_strip[(u, v)]))) for i in range(0, self.get_strip_density(edge_strip[(u, v)]) + 1)] for u, v in self.face_halfedges(fkey)] polylines = [] for u, v in self.face_halfedges(fkey): polyline = [] if edges_to_curves is None: curve = Polyline([ self.vertex_coordinates(u), self.vertex_coordinates(v) ]) else: if (u, v) in edges_to_curves: curve = Polyline(edges_to_curves[(u, v)]) elif (v, u) in edges_to_curves: curve = Polyline( list(reversed(edges_to_curves[(v, u)]))) else: curve = None d = self.get_strip_density(edge_strip[(u, v)]) for i in range(0, d + 1): point = curve.point(float(i) / float(d)) polyline.append(point) polylines.append(polyline) if self.is_face_pseudo_quad(fkey): pole = self.data['attributes']['face_pole'][fkey] idx = self.face_vertices(fkey).index(pole) polylines.insert(idx, None) ab, bc, cd, da = polylines if cd is not None: dc = list(reversed(cd)) else: dc = None if da is not None: ad = list(reversed(da)) else: ad = None vertices, faces = discrete_coons_patch(ab, bc, dc, ad) faces = [[u for u, v in pairwise(face + face[:1]) if u != v] for face in faces] mesh = PseudoQuadMesh.from_vertices_and_faces_with_face_poles( vertices, faces) meshes.append(mesh) face_pole_map = {} for mesh in meshes: for fkey in mesh.faces(): for u, v in pairwise( mesh.face_vertices(fkey) + mesh.face_vertices(fkey)[:1]): if geometric_key(mesh.vertex_coordinates( u)) in pole_map and geometric_key( mesh.vertex_coordinates(u)) == geometric_key( mesh.vertex_coordinates(v)): face_pole_map[geometric_key( mesh.face_center(fkey))] = geometric_key( mesh.vertex_coordinates(u)) break self.set_quad_mesh(meshes_join_and_weld(meshes)) face_pole = {} for fkey in self.get_quad_mesh().faces(): if geometric_key( self.get_quad_mesh().face_center(fkey)) in face_pole_map: for vkey in self.get_quad_mesh().face_vertices(fkey): if geometric_key(self.get_quad_mesh().vertex_coordinates( vkey)) == face_pole_map[geometric_key( self.get_quad_mesh().face_center(fkey))]: face_pole[fkey] = vkey break self.get_quad_mesh().data['attributes']['face_pole'] = face_pole return self.get_quad_mesh()
# ============================================================================== # Curves # ============================================================================== Z = Vector(0, 0, 1) controlpoints = [Point(0, 0, 0), Point(4, 2.5, 0), Point(6, -2.5, 0), Point(10, 0, 0)] controlpoly = Polyline(controlpoints) curve = Bezier(controlpoints) poly0 = Polyline(curve.locus()) poly1 = Polyline(offset_polyline(poly0, +0.15)) poly2 = Polyline(offset_polyline(poly0, -0.15)) points0 = [poly0.point(t) for t in linspace(0, 1, 20)] tangents0 = [(c - a).unitized() for a, b, c in window(points0, 3) if a and c] normals0 = [Z.cross(t) for t in tangents0] lines = [[point, point + normal] for point, normal in zip(points0[1:-1], normals0)] points1 = [intersection_line_polyline(line, poly1) for line in lines] points2 = [intersection_line_polyline(line, poly2) for line in lines] # ============================================================================== # Blocks # ============================================================================== frames = [] blocks = [] polygons = []