From 88e7432bd4239b88d955bbe3a36a8ee265f0c909 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 20 Nov 2023 17:37:10 -0500 Subject: [PATCH] fix(shademesh): Trinagulate and remove degenerate from ShadeMesh --- honeybee/model.py | 2 ++ honeybee/shademesh.py | 27 ++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/honeybee/model.py b/honeybee/model.py index d474cd74..1c0255c0 100644 --- a/honeybee/model.py +++ b/honeybee/model.py @@ -1779,6 +1779,8 @@ def remove_degenerate_geometry(self, tolerance=None): self._remove_degenerate_faces(self._orphaned_apertures, tolerance) self._remove_degenerate_faces(self._orphaned_doors, tolerance) self._remove_degenerate_faces(self._orphaned_shades, tolerance) + for sm in self._shade_meshes: + sm.triangulate_and_remove_degenerate_faces(tolerance) def triangulate_non_planar_quads(self, tolerance=None): """Triangulate any non-planar orphaned geometry in the model. diff --git a/honeybee/shademesh.py b/honeybee/shademesh.py index cd21681e..3a9b98ae 100644 --- a/honeybee/shademesh.py +++ b/honeybee/shademesh.py @@ -3,7 +3,7 @@ from __future__ import division import math -from ladybug_geometry.geometry3d.mesh import Mesh3D +from ladybug_geometry.geometry3d import Mesh3D, Face3D from ladybug.color import Color from ._base import _Base @@ -218,6 +218,31 @@ def scale(self, factor, origin=None): self._geometry = self.geometry.scale(factor, origin) self.properties.scale(factor, origin) + def triangulate_and_remove_degenerate_faces(self, tolerance=0.01): + """Triangulate all faces in the mesh and remove all degenerate faces from the result. + + This is helpful for certain geometry interfaces that require perfectly + planar geometry without duplicate or colinear vertices. + + Args: + tolerance: The minimum distance between a vertex and the boundary segments + at which point the vertex is considered colinear. Default: 0.01, + suitable for objects in meters. + """ + new_faces, verts = [], self.geometry.vertices + for shd in self.faces: + shades = (shd,) if len(shd) == 3 else \ + ((shd[0], shd[1], shd[2]), (shd[2], shd[3], shd[0])) + for shade in enumerate(shades): + shd_verts = [verts[v] for v in shade] + shade_face = Face3D(shd_verts) + try: + shade_face.remove_colinear_vertices(tolerance) + except AssertionError: + continue # degenerate face to remove + new_faces.append(shade) + self._geometry = Mesh3D(verts, new_faces) + def is_geo_equivalent(self, shade_mesh, tolerance=0.01): """Get a boolean for whether this object is geometrically equivalent to another.