mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-15 15:20:37 -08:00
Added Face.is_planar property Issue #756
This commit is contained in:
parent
d8d841e5a3
commit
c7a8529c24
2 changed files with 30 additions and 9 deletions
|
|
@ -181,6 +181,7 @@ from OCP.GeomFill import (
|
|||
GeomFill_Frenet,
|
||||
GeomFill_TrihedronLaw,
|
||||
)
|
||||
from OCP.GeomLib import GeomLib_IsPlanarSurface
|
||||
from OCP.gp import (
|
||||
gp_Ax1,
|
||||
gp_Ax2,
|
||||
|
|
@ -3447,7 +3448,7 @@ class ShapeList(list[T]):
|
|||
# could be moved out maybe?
|
||||
def axis_parallel_predicate(axis: Axis, tolerance: float):
|
||||
def pred(shape: Shape):
|
||||
if isinstance(shape, Face) and shape.geom_type == GeomType.PLANE:
|
||||
if isinstance(shape, Face) and shape.is_planar:
|
||||
shape_axis = Axis(shape.center(), shape.normal_at(None))
|
||||
elif isinstance(shape, Edge) and shape.geom_type == GeomType.LINE:
|
||||
shape_axis = Axis(shape.position_at(0), shape.tangent_at(0))
|
||||
|
|
@ -3462,7 +3463,7 @@ class ShapeList(list[T]):
|
|||
plane_xyz = plane.z_dir.wrapped.XYZ()
|
||||
|
||||
def pred(shape: Shape):
|
||||
if isinstance(shape, Face) and shape.geom_type == GeomType.PLANE:
|
||||
if isinstance(shape, Face) and shape.is_planar:
|
||||
shape_axis = Axis(shape.center(), shape.normal_at(None))
|
||||
return plane_axis.is_parallel(shape_axis, tolerance)
|
||||
if isinstance(shape, Wire):
|
||||
|
|
@ -5601,7 +5602,7 @@ class Face(Shape):
|
|||
def length(self) -> float:
|
||||
"""length of planar face"""
|
||||
result = None
|
||||
if self.geom_type == GeomType.PLANE:
|
||||
if self.is_planar:
|
||||
# Reposition on Plane.XY
|
||||
flat_face = Plane(self).to_local_coords(self)
|
||||
face_vertices = flat_face.vertices().sort_by(Axis.X)
|
||||
|
|
@ -5617,7 +5618,7 @@ class Face(Shape):
|
|||
def width(self) -> float:
|
||||
"""width of planar face"""
|
||||
result = None
|
||||
if self.geom_type == GeomType.PLANE:
|
||||
if self.is_planar:
|
||||
# Reposition on Plane.XY
|
||||
flat_face = Plane(self).to_local_coords(self)
|
||||
face_vertices = flat_face.vertices().sort_by(Axis.Y)
|
||||
|
|
@ -5628,7 +5629,7 @@ class Face(Shape):
|
|||
def geometry(self) -> str:
|
||||
"""geometry of planar face"""
|
||||
result = None
|
||||
if self.geom_type == GeomType.PLANE:
|
||||
if self.is_planar:
|
||||
flat_face = Plane(self).to_local_coords(self)
|
||||
flat_face_edges = flat_face.edges()
|
||||
if all([e.geom_type == GeomType.LINE for e in flat_face_edges]):
|
||||
|
|
@ -5661,6 +5662,13 @@ class Face(Shape):
|
|||
origin = self.position_at(0.5, 0.5)
|
||||
return Plane(origin, z_dir=self.normal_at(origin)).location
|
||||
|
||||
@property
|
||||
def is_planar(face: Face) -> bool:
|
||||
"""Is the face planar even though its geom_type may not be PLANE"""
|
||||
surface = BRep_Tool.Surface_s(face.wrapped)
|
||||
is_face_planar = GeomLib_IsPlanarSurface(surface, TOLERANCE)
|
||||
return is_face_planar.IsPlanar()
|
||||
|
||||
def _geom_adaptor(self) -> Geom_Surface:
|
||||
""" """
|
||||
return BRep_Tool.Surface_s(self.wrapped)
|
||||
|
|
@ -5810,7 +5818,7 @@ class Face(Shape):
|
|||
Vector: center
|
||||
"""
|
||||
if (center_of == CenterOf.MASS) or (
|
||||
center_of == CenterOf.GEOMETRY and self.geom_type == GeomType.PLANE
|
||||
center_of == CenterOf.GEOMETRY and self.is_planar
|
||||
):
|
||||
properties = GProp_GProps()
|
||||
BRepGProp.SurfaceProperties_s(self.wrapped, properties)
|
||||
|
|
@ -7447,9 +7455,7 @@ class Solid(Mixin3D, Shape):
|
|||
clip_faces = [
|
||||
f
|
||||
for f in faces
|
||||
if not (
|
||||
f.geom_type == GeomType.PLANE and f.normal_at().dot(direction) == 0.0
|
||||
)
|
||||
if not (f.is_planar and f.normal_at().dot(direction) == 0.0)
|
||||
]
|
||||
if not clip_faces:
|
||||
raise ValueError("provided face does not intersect target_object")
|
||||
|
|
|
|||
|
|
@ -1220,6 +1220,21 @@ class TestFace(DirectApiTestCase):
|
|||
extrude(amount=1)
|
||||
self.assertEqual(test.faces().sort_by(Axis.Z).last.geometry, "POLYGON")
|
||||
|
||||
def test_is_planar(self):
|
||||
self.assertTrue(Face.make_rect(1, 1).is_planar)
|
||||
self.assertFalse(
|
||||
Solid.make_cylinder(1, 1).faces().filter_by(GeomType.CYLINDER)[0].is_planar
|
||||
)
|
||||
# Some of these faces have geom_type BSPLINE but are planar
|
||||
mount = Solid.make_loft(
|
||||
[
|
||||
Rectangle((1 + 16 + 4), 20, align=(Align.MIN, Align.CENTER)).wire(),
|
||||
Pos(1, 0, 4)
|
||||
* Rectangle(16, 20, align=(Align.MIN, Align.CENTER)).wire(),
|
||||
],
|
||||
)
|
||||
self.assertTrue(all(f.is_planar for f in mount.faces()))
|
||||
|
||||
def test_negate(self):
|
||||
square = Face.make_rect(1, 1)
|
||||
self.assertVectorAlmostEquals(square.normal_at(), (0, 0, 1), 5)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue