diff --git a/src/build123d/operations_generic.py b/src/build123d/operations_generic.py index 19d3e0ac..16734949 100644 --- a/src/build123d/operations_generic.py +++ b/src/build123d/operations_generic.py @@ -616,7 +616,14 @@ def offset( inner_wires.append(offset_wire) except: pass - new_face = Face(outer_wire, inner_wires) + # inner wires may go beyond the outer wire so subtract faces + new_face = Face(outer_wire) + if inner_wires: + inner_faces = [Face(w) for w in inner_wires] + new_face = new_face.cut(*inner_faces) + if isinstance(new_face, Compound): + new_face = new_face.unwrap(fully=True) + if (new_face.normal_at() - face.normal_at()).length > 0.001: new_face = -new_face new_faces.append(new_face) diff --git a/tests/test_build_generic.py b/tests/test_build_generic.py index 68f013f5..46a6c345 100644 --- a/tests/test_build_generic.py +++ b/tests/test_build_generic.py @@ -521,6 +521,13 @@ def test_face_offset(self): offset(amount=1, kind=Kind.INTERSECTION) self.assertAlmostEqual(test.sketch.area, 9, 5) + def test_face_offset_with_holes(self): + sk = Rectangle(100, 100) - GridLocations(80, 80, 2, 2) * Circle(5) + sk2 = offset(sk, -5) + self.assertTrue(sk2.face().is_valid()) + self.assertLess(sk2.area, sk.area) + self.assertEqual(len(sk2), 1) + def test_box_offset(self): with BuildPart() as test: Box(10, 10, 10)