Fixed 3d offset - Issue #74

This commit is contained in:
Roger Maitland 2023-01-28 14:18:41 -05:00
parent 9a15088ba2
commit 755994f8c5
4 changed files with 65 additions and 10 deletions

View file

@ -153,7 +153,7 @@ Cheat Sheet
+----------+---------------------+-----------------------------------------+---------------------------------------------+
| Operator | Operand | Method | Description |
+==========+=====================+=========================================+=============================================+
| == | Any | :meth:`~direct_api.Shape.is_equal` | Compare CAD objects not including meta data |
| == | Any | :meth:`~direct_api.Shape.is_same` | Compare CAD objects not including meta data |
+----------+---------------------+-----------------------------------------+---------------------------------------------+

View file

@ -437,7 +437,7 @@ class Offset(Compound):
else:
openings_in_this_solid = []
new_solids.append(
solid.shell(openings_in_this_solid, amount, kind=kind).fix()
solid.offset_3d(openings_in_this_solid, amount, kind=kind).fix()
)
new_objects = new_wires + new_faces + new_solids

View file

@ -2066,6 +2066,64 @@ class Mixin3D:
return return_value
def offset_3d(
self,
openings: Optional[Iterable[Face]],
thickness: float,
tolerance: float = 0.0001,
kind: Kind = Kind.ARC,
) -> Solid:
"""Shell
Make an offset solid of self.
Args:
openings (Optional[Iterable[Face]]): List of faces to be removed,
which must be part of the solid. Can be an empty list.
thickness (float): offset amount - positive offset outwards, negative inwards
tolerance (float, optional): modelling tolerance of the method. Defaults to 0.0001.
kind (Kind, optional): intersection type. Defaults to Kind.ARC.
Raises:
ValueError: Kind.TANGENT not supported
Returns:
Solid: A shelled solid.
"""
if kind == Kind.TANGENT:
raise ValueError("Kind.TANGENT not supported")
kind_dict = {
Kind.ARC: GeomAbs_JoinType.GeomAbs_Arc,
Kind.INTERSECTION: GeomAbs_JoinType.GeomAbs_Intersection,
Kind.TANGENT: GeomAbs_JoinType.GeomAbs_Tangent,
}
occ_faces_list = TopTools_ListOfShape()
for face in openings:
occ_faces_list.Append(face.wrapped)
offset_builder = BRepOffsetAPI_MakeThickSolid()
offset_builder.MakeThickSolidByJoin(
self.wrapped,
occ_faces_list,
thickness,
tolerance,
Intersection=True,
RemoveIntEdges=True,
Join=kind_dict[kind],
)
offset_builder.Build()
offset_occt_solid = offset_builder.Shape()
offset_solid = self.__class__(offset_occt_solid)
# The Solid can be inverted, if so reverse
if offset_solid.volume < 0:
offset_solid.wrapped.Reverse()
return offset_solid
def is_inside(self, point: VectorLike, tolerance: float = 1.0e-6) -> bool:
"""Returns whether or not the point is inside a solid or compound
object within the specified tolerance.
@ -2635,8 +2693,8 @@ class Shape(NodeMixin):
return self.wrapped.IsEqual(other.wrapped)
def __eq__(self, other) -> bool:
"""Are shapes equal?"""
return self.is_equal(other) if isinstance(other, Shape) else False
"""Are shapes same?"""
return self.is_same(other) if isinstance(other, Shape) else False
def is_valid(self) -> bool:
"""Returns True if no defect is detected on the shape S or any of its

View file

@ -163,12 +163,9 @@ class TestOffset(unittest.TestCase):
def test_box_offset(self):
with BuildPart() as test:
Box(1, 1, 1)
Offset(
amount=1,
kind=Kind.INTERSECTION,
)
self.assertAlmostEqual(test.part.volume, 3**3 - 1**3, 5)
Box(10, 10, 10)
Offset(amount=-1, kind=Kind.INTERSECTION, mode=Mode.SUBTRACT)
self.assertAlmostEqual(test.part.volume, 10**3 - 8**3, 5)
def test_box_offset_with_opening(self):
with BuildPart() as test: