mirror of
https://github.com/gumyr/build123d.git
synced 2026-01-06 09:14:03 -08:00
Adding Face.remove_holes and Face.total_area property
This commit is contained in:
parent
0e3dbbe15b
commit
c728124b3b
2 changed files with 75 additions and 1 deletions
|
|
@ -73,7 +73,7 @@ from OCP.BRepFilletAPI import BRepFilletAPI_MakeFillet2d
|
|||
from OCP.BRepGProp import BRepGProp, BRepGProp_Face
|
||||
from OCP.BRepIntCurveSurface import BRepIntCurveSurface_Inter
|
||||
from OCP.BRepOffsetAPI import BRepOffsetAPI_MakeFilling, BRepOffsetAPI_MakePipeShell
|
||||
from OCP.BRepTools import BRepTools
|
||||
from OCP.BRepTools import BRepTools, BRepTools_ReShape
|
||||
from OCP.GProp import GProp_GProps
|
||||
from OCP.Geom import Geom_BezierSurface, Geom_Surface
|
||||
from OCP.GeomAPI import GeomAPI_PointsToBSplineSurface, GeomAPI_ProjectPointOnSurf
|
||||
|
|
@ -405,6 +405,23 @@ class Face(Mixin2D, Shape[TopoDS_Face]):
|
|||
result = face_vertices[-1].X - face_vertices[0].X
|
||||
return result
|
||||
|
||||
@property
|
||||
def total_area(self) -> float:
|
||||
"""
|
||||
Calculate the total surface area of the face, including the areas of any holes.
|
||||
|
||||
This property returns the overall area of the face as if the inner boundaries (holes)
|
||||
were filled in.
|
||||
|
||||
Returns:
|
||||
float: The total surface area, including the area of holes. Returns 0.0 if
|
||||
the face is empty.
|
||||
"""
|
||||
if self.wrapped is None:
|
||||
return 0.0
|
||||
|
||||
return self.remove_holes().area
|
||||
|
||||
@property
|
||||
def volume(self) -> float:
|
||||
"""volume - the volume of this Face, which is always zero"""
|
||||
|
|
@ -1201,6 +1218,28 @@ class Face(Mixin2D, Shape[TopoDS_Face]):
|
|||
projected_shapes.append(shape)
|
||||
return projected_shapes
|
||||
|
||||
def remove_holes(self) -> Face:
|
||||
"""remove_holes
|
||||
|
||||
Remove all of the holes from this face.
|
||||
|
||||
Returns:
|
||||
Face: A new Face instance identical to the original but without any holes.
|
||||
"""
|
||||
if self.wrapped is None:
|
||||
raise ValueError("Cannot remove holes from an empty face")
|
||||
|
||||
if not (inner_wires := self.inner_wires()):
|
||||
return self
|
||||
|
||||
holeless = copy.deepcopy(self)
|
||||
reshaper = BRepTools_ReShape()
|
||||
for hole_wire in inner_wires:
|
||||
reshaper.Remove(hole_wire.wrapped)
|
||||
modified_shape = downcast(reshaper.Apply(self.wrapped))
|
||||
holeless.wrapped = modified_shape
|
||||
return holeless
|
||||
|
||||
def to_arcs(self, tolerance: float = 1e-3) -> Face:
|
||||
"""to_arcs
|
||||
|
||||
|
|
|
|||
|
|
@ -447,6 +447,41 @@ class TestFace(unittest.TestCase):
|
|||
face = Cylinder(1, 1).faces().filter_by(GeomType.CYLINDER)[0]
|
||||
self.assertAlmostEqual(face.normal_at(0, 1), (1, 0, 0), 5)
|
||||
|
||||
def test_remove_holes(self):
|
||||
# Planar test
|
||||
frame = (Rectangle(1, 1) - Rectangle(0.5, 0.5)).face()
|
||||
filled = frame.remove_holes()
|
||||
self.assertEqual(len(frame.inner_wires()), 1)
|
||||
self.assertEqual(len(filled.inner_wires()), 0)
|
||||
self.assertAlmostEqual(frame.area, 0.75, 5)
|
||||
self.assertAlmostEqual(filled.area, 1.0, 5)
|
||||
|
||||
# Errors
|
||||
frame.wrapped = None
|
||||
with self.assertRaises(ValueError):
|
||||
frame.remove_holes()
|
||||
|
||||
# No holes
|
||||
rect = Face.make_rect(1, 1)
|
||||
self.assertEqual(rect, rect.remove_holes())
|
||||
|
||||
# Non-planar test
|
||||
cyl_face = (
|
||||
(Cylinder(1, 3) - Cylinder(0.5, 3, rotation=(90, 0, 0)))
|
||||
.faces()
|
||||
.sort_by(Face.area)[-1]
|
||||
)
|
||||
filled = cyl_face.remove_holes()
|
||||
self.assertEqual(len(cyl_face.inner_wires()), 2)
|
||||
self.assertEqual(len(filled.inner_wires()), 0)
|
||||
self.assertTrue(cyl_face.area < filled.area)
|
||||
self.assertAlmostEqual(cyl_face.total_area, filled.area, 5)
|
||||
|
||||
def test_total_area(self):
|
||||
frame = (Rectangle(1, 1) - Rectangle(0.5, 0.5)).face()
|
||||
frame.wrapped = None
|
||||
self.assertAlmostEqual(frame.total_area, 0.0, 5)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue