Skip to content

Commit

Permalink
fix(mesh): Add a face_edges property for faster edge computation
Browse files Browse the repository at this point in the history
  • Loading branch information
chriswmackey authored and Chris Mackey committed Apr 9, 2024
1 parent 25a0fad commit 87156cb
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 14 deletions.
2 changes: 1 addition & 1 deletion ladybug_geometry/_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def vertex_connected_faces(self):
"""Tuple with a tuple for each vertex that lists the indexes of connected faces.
"""
if self._vertex_connected_faces is None:
_vert_faces = [[] for i in xrange(len(self._vertices))]
_vert_faces = [[] for _ in xrange(len(self._vertices))]
for i, face in enumerate(self._faces):
for j in face:
_vert_faces[j].append(i)
Expand Down
15 changes: 15 additions & 0 deletions ladybug_geometry/geometry2d/mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from .pointvector import Point2D, Vector2D
from .line import LineSegment2D
from .polyline import Polyline2D
from .polygon import Polygon2D


Expand Down Expand Up @@ -272,6 +273,20 @@ def centroid(self):
self._centroid = Point2D(_weight_x / self.area, _weight_y / self.area)
return self._centroid

@property
def face_edges(self):
"""List of polylines with one Polyline2D for each face.
This is faster to compute compared to the edges and results in effectively
the same type of wireframe visualization.
"""
_all_verts = self._vertices
f_edges = []
for face in self._faces:
verts = tuple(_all_verts[v] for v in face) + (_all_verts[face[0]],)
f_edges.append(Polyline2D(verts))
return f_edges

@property
def edges(self):
""""Tuple of all edges in this Mesh3D as LineSegment3D objects."""
Expand Down
2 changes: 2 additions & 0 deletions ladybug_geometry/geometry2d/polygon.py
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,8 @@ def does_polygon_touch(self, polygon, tolerance):
Args:
polygon: A Polygon2D to test whether it touches this polygon.
tolerance: The minimum distance from an edge at which a point is
considered to touch the edge.
Returns:
A boolean denoting whether the polygon touches (True) or not (False).
Expand Down
22 changes: 21 additions & 1 deletion ladybug_geometry/geometry3d/mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from ..geometry2d.mesh import Mesh2D
from .pointvector import Point3D, Vector3D
from .line import LineSegment3D
from .polyline import Polyline3D
from .plane import Plane

try:
Expand Down Expand Up @@ -40,6 +41,7 @@ class Mesh3D(MeshBase):
* face_normals
* vertex_normals
* vertex_connected_faces
* face_edges
* edges
* naked_edges
* internal_edges
Expand Down Expand Up @@ -204,9 +206,27 @@ def vertex_normals(self):
self._vertex_normals = tuple(self._vertex_normals for face in self.vertices)
return self._vertex_normals

@property
def face_edges(self):
"""List of polylines with one Polyline3D for each face.
This is faster to compute compared to the edges and results in effectively
the same type of wireframe visualization.
"""
_all_verts = self._vertices
f_edges = []
for face in self._faces:
verts = tuple(_all_verts[v] for v in face) + (_all_verts[face[0]],)
f_edges.append(Polyline3D(verts))
return f_edges

@property
def edges(self):
""""Tuple of all edges in this Mesh3D as LineSegment3D objects."""
""""Tuple of all edges in this Mesh3D as LineSegment3D objects.
Note that this method will return only the unique edges in the mesh without
any duplicates. This is sometimes desirable but can take a lot of time
to compute for large meshes. For a faster property, use face_edges."""
if self._edges is None:
if self._edge_indices is None:
self._compute_edge_info()
Expand Down
10 changes: 5 additions & 5 deletions tests/mesh2d_test.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
# coding=utf-8
import pytest

from ladybug_geometry.geometry2d.pointvector import Point2D, Vector2D
from ladybug_geometry.geometry2d.mesh import Mesh2D
from ladybug_geometry.geometry2d.polygon import Polygon2D

import math

from ladybug_geometry.geometry2d import Point2D, Vector2D, Polyline2D, Mesh2D, Polygon2D


def test_mesh2d_init():
"""Test the initialization of Mesh2D objects and basic properties."""
Expand Down Expand Up @@ -38,6 +35,9 @@ def test_mesh2d_init():
assert len(mesh.vertex_connected_faces) == 4
for vf in mesh.vertex_connected_faces:
assert len(vf) == 1
assert len(mesh.face_edges) == 1
for pline in mesh.face_edges:
assert isinstance(pline, Polyline2D)

assert len(mesh.edges) == 4
assert len(mesh.naked_edges) == 4
Expand Down
13 changes: 6 additions & 7 deletions tests/mesh3d_test.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
# coding=utf-8
import pytest

from ladybug_geometry.geometry3d.pointvector import Point3D, Vector3D
from ladybug_geometry.geometry3d.mesh import Mesh3D
from ladybug_geometry.geometry3d.plane import Plane
from ladybug_geometry.geometry2d.mesh import Mesh2D
from ladybug_geometry.geometry2d.pointvector import Point2D

import math
import json
import os

from ladybug_geometry.geometry2d import Point2D, Mesh2D
from ladybug_geometry.geometry3d import Point3D, Vector3D, Polyline3D, Plane, Mesh3D


def test_mesh3d_init():
"""Test the initialization of Mesh3D objects and basic properties."""
Expand Down Expand Up @@ -39,6 +35,9 @@ def test_mesh3d_init():
assert len(mesh.vertex_connected_faces) == 4
for vf in mesh.vertex_connected_faces:
assert len(vf) == 1
assert len(mesh.face_edges) == 1
for pline in mesh.face_edges:
assert isinstance(pline, Polyline3D)

assert len(mesh.edges) == 4
assert len(mesh.naked_edges) == 4
Expand Down

0 comments on commit 87156cb

Please sign in to comment.