Skip to content

Commit

Permalink
feat(face3d): Adding method for is_centered_adjacent
Browse files Browse the repository at this point in the history
  • Loading branch information
chriswmackey authored and Chris Mackey committed Jun 7, 2019
1 parent 04834ae commit 87b282e
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 2 deletions.
30 changes: 29 additions & 1 deletion ladybug_geometry/geometry3d/face.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,8 @@ def is_geometrically_equivalent(self, face, tolerance):
direction of the face. However, all other properties must be matching to
within the input tolerance.
This is useful for identifying matching surfaces when solving for adjacency.
This is useful for identifying matching surfaces when solving for adjacency
and you need to ensure that two faces match perfectly in their area and vertices.
Note that you may also want to use the remove_colinear_vertices() method
on input faces before using this method in order to count faces with the
same non-colinear vertices as geometrically equivalent.
Expand Down Expand Up @@ -553,6 +554,33 @@ def is_geometrically_equivalent(self, face, tolerance):
return False
return True

def is_centered_adjacent(self, face, tolerance, angle_tolerance):
"""Check whether a given face is centered adjacent with this Face.
Centered adjacency is definied as being coplananar with this face and sharing
the same center point to within the tolerance.
This is useful for identifying matching surfaces when you want to quickly
solve for adjacency and you are not concerned about false positives in cases
where one face does not perfectly match the other in terms of area or vertices.
This means it is good enough for cases where users know how to set up their
model correctly.
Args:
face: Another face for which centered adjacency will be tested.
tolerance: The minimum difference between the coordinate values of two
centers at which they can be considered centered adjacent.
angle_tolerance: The max angle in radians that the plane normals can
differ from one another in order for them to be considered coplanar.
Returns:
True if centered adjacent. False if not centered adjacent.
"""
if not self.center.is_equivalent(face.center, tolerance):
return False
if not self.plane.is_coplanar_tolerance(face.plane, tolerance, angle_tolerance):
return False
return True

def is_sub_face(self, face, tolerance, angle_tolerance):
"""Check whether a given face is a sub-face of this face.
Expand Down
26 changes: 25 additions & 1 deletion tests/face3d_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def test_face3d_to_from_dict(self):
assert new_face.to_dict() == face_dict

def test_face3d_init_from_vertices(self):
"""Test the initalization of Face3D objects from_vertices."""
"""Test the initalization of Face3D objects without a plane."""
pts = (Point3D(0, 0, 2), Point3D(0, 2, 2), Point3D(2, 2, 2), Point3D(2, 0, 2))
face = Face3D(pts)

Expand Down Expand Up @@ -314,6 +314,30 @@ def test_is_equivalent(self):
assert face_1.is_geometrically_equivalent(face_7, 0.0001) is False
assert face_1.is_geometrically_equivalent(face_8, 0.0001) is True

def test_is_centered_adjacent(self):
"""Test the is_centered_adjacent method."""
plane_1 = Plane(Vector3D(0, 0, 1))
plane_2 = Plane(Vector3D(0, 0, -1))
pts_1 = (Point3D(0, 0), Point3D(2, 0), Point3D(2, 2), Point3D(0, 2))
pts_2 = (Point3D(0, 0), Point3D(0, 2), Point3D(2, 2), Point3D(2, 0))
pts_3 = (Point3D(0, 0), Point3D(2, 0), Point3D(2.1, 2.1), Point3D(0, 2))
pts_4 = (Point3D(1, 0), Point3D(0, 1), Point3D(1, 2), Point3D(2, 1))
pts_5 = (Point3D(2, 0), Point3D(2, 2), Point3D(0, 2), Point3D(0, 0))
face_1 = Face3D(pts_1, plane_1)
face_2 = Face3D(pts_2, plane_1)
face_3 = Face3D(pts_1, plane_2)
face_4 = Face3D(pts_2, plane_2)
face_5 = Face3D(pts_3, plane_1)
face_6 = Face3D(pts_4, plane_1)
face_7 = Face3D(pts_5, plane_1)

assert face_1.is_centered_adjacent(face_2, 0.0001, 0.0001) is True
assert face_1.is_centered_adjacent(face_3, 0.0001, 0.0001) is True
assert face_1.is_centered_adjacent(face_4, 0.0001, 0.0001) is True
assert face_1.is_centered_adjacent(face_5, 0.0001, 0.0001) is False
assert face_1.is_centered_adjacent(face_6, 0.0001, 0.0001) is True
assert face_1.is_centered_adjacent(face_7, 0.0001, 0.0001) is True

def test_is_sub_face(self):
"""Test the is_sub_face method."""
bound_pts = [Point3D(0, 0), Point3D(4, 0), Point3D(4, 4), Point3D(0, 4)]
Expand Down

0 comments on commit 87b282e

Please sign in to comment.