def face_skewness(self, fkey): """Face skewness as the maximum absolute angular deviation from the ideal polygon angle. Parameters ---------- fkey : Key The face key. Returns ------- float The skewness. References ---------- .. [1] Wikipedia. *Types of mesh*. Available at: https://en.wikipedia.org/wiki/Types_of_mesh. """ ideal_angle = 180 * (1 - 2 / float(len(self.face_vertices(fkey)))) angles = [] vertices = self.face_vertices(fkey) for u, v, w in window(vertices + vertices[:2], n=3): o = self.vertex_coordinates(v) a = self.vertex_coordinates(u) b = self.vertex_coordinates(w) angle = angle_points(o, a, b, deg=True) angles.append(angle) return max((max(angles) - ideal_angle) / (180 - ideal_angle), (ideal_angle - min(angles)) / ideal_angle)
def vertex_curvature(self, vkey): """Dimensionless vertex curvature. Parameters ---------- fkey : int The face key. Returns ------- float The dimensionless curvature. References ---------- Based on [1]_ .. [1] Botsch, Mario, et al. *Polygon mesh processing.* AK Peters/CRC Press, 2010. """ C = 0 for u, v in pairwise( self.vertex_neighbors(vkey, ordered=True) + self.vertex_neighbors(vkey, ordered=True)[:1]): C += angle_points(self.vertex_coordinates(vkey), self.vertex_coordinates(u), self.vertex_coordinates(v)) return 2 * pi - C
def is_boundary_vertex_kink(self, vkey, threshold_angle): """Return whether there is a kink at a boundary vertex according to a threshold angle. Parameters ---------- vkey : Key The boundary vertex key. threshold_angle : float Threshold angle in rad. Returns ------- bool True if vertex is on the boundary and has an angle larger than the threshold angle. False otherwise. """ # check if vertex is on boundary if not self.is_vertex_on_boundary(vkey): return False # get the two adjacent boundary vertices (exactly two for manifold meshes) ukey, wkey = [ nbr for nbr in self.vertex_neighbors(vkey) if self.is_edge_on_boundary(vkey, nbr) ] # compare boundary angle with threshold angle return angle_points(self.vertex_coordinates(ukey), self.vertex_coordinates(vkey), self.vertex_coordinates(wkey)) > threshold_angle
def brace_angle(self, value): if value is not None: self._brace_angle = value else: self._brace_angle = angle_points(self.column.end_pt, self.work_point, self.brace.end_pt, deg=True)
def trimesh_gaussian_curvature(mesh): r"""Compute the gaussian curvature at the vertices of a triangle mesh using the angular deficit. The angular deficit at a vertex is defined as the difference between a full circle angle (:math:`2\pi`) and the sum of the angles in the adjacent trianlges. .. math:: k_{G}(v_{i}) = 2\pi - \sum_{j \in N(i)} \teta_{ij} where :math:`N(i)` are the triangles incident on vertex :math:`i` and :math:`\teta_{ij}` is the angle at vertex :math:`i` in triangle :math:`j`. Parameters ---------- mesh : compas.oatastructures.Mesh The triangle mesh data structure. Returns ------- list of float Per vertex curvature values. Warning ------- This function will not check if the provided mesh is actually a triangle mesh. It will just treat as such... Examples -------- .. code-block:: python pass """ pi2 = 2 * pi key_xyz = { key: mesh.get_vertex_attributes(key, 'xyz') for key in mesh.vertices() } curvature = [] for key in mesh.vertices(): angles = [] o = key_xyz[key] for u in mesh.vertex_neighbors(key): fkey = mesh.halfedge[key][u] if fkey is not None: vertices = mesh.face_vertices(fkey) v = vertices[vertices.index(key) - 1] a = key_xyz[u] b = key_xyz[v] print(o, a, b) angles.append(angle_points(o, a, b)) curvature.append(pi2 - sum(angles)) return curvature
def vertex_curvatures(mesh): """Curvatures of the non-boundary mesh vertices as dict vertex: vertex curvature. Curvature of a vertex = 2 * pi - sum angles between adajcent edges. Parameters ---------- mesh : Mesh A mesh. Returns ------- vertex_curvature_dict: dict Dictionary of curvatures per vertex {vertex: vertex curvature}. None if vertex is on the boundary. Raises ------ - """ vertex_curvature_dict = {} for vkey in mesh.vertices(): if not mesh.is_vertex_on_boundary(vkey): sum_angles = 0 neighbours = mesh.vertex_neighbours(vkey) for i in range(len(neighbours)): nbr_1 = neighbours[i - 1] nbr_2 = neighbours[i] sum_angles += angle_points(mesh.vertex_coordinates(vkey), mesh.vertex_coordinates(nbr_1), mesh.vertex_coordinates(nbr_2)) vertex_curvature_dict[vkey] = 2 * pi - sum_angles else: vertex_curvature_dict[vkey] = None return vertex_curvature_dict
world = Frame.worldXY() for guid in guids: surface = RhinoSurface.from_guid(guid) block = surface.to_compas() block.name = str(guid) bottom = sorted( block.faces(), key=lambda face: dot_vectors(block.face_normal(face), [0, 0, -1]))[-1] u, v, w = sorted(block.face_corners(bottom), key=lambda corner: abs( angle_points(block.vertex_coordinates(corner[1]), block.vertex_coordinates(corner[2]), block.vertex_coordinates(corner[0])) - 0.5 * 3.14159))[0] if block.edge_length(u, v) > block.edge_length(v, w): edge = u, v else: edge = v, w xaxis = block.edge_direction(*edge) yaxis = cross_vectors([0, 0, 1], xaxis) xaxis = cross_vectors(yaxis, [0, 0, 1]) frame = Frame(block.face_centroid(bottom), xaxis, yaxis) T = Transformation.from_frame_to_frame(frame, world)