diff --git a/cadquery/occ_impl/shapes.py b/cadquery/occ_impl/shapes.py index 7eb28caca..97a6bd65d 100644 --- a/cadquery/occ_impl/shapes.py +++ b/cadquery/occ_impl/shapes.py @@ -4027,15 +4027,15 @@ def makeShell(cls, listOfFaces: Iterable[Face]) -> Shell: class Mixin3D(object): - def fillet(self: Any, radius: float, edgeList: Iterable[Edge]) -> Any: + def fillet(self: Any, radius: float, edgeList: Shape | Iterable[Edge]) -> Any: """ Fillets the specified edges of this solid. :param radius: float > 0, the radius of the fillet - :param edgeList: a list of Edge objects, which must belong to this solid + :param edgeList: a list of Edge objects or a Shape containing edges, which must belong to this solid :return: Filleted solid """ - nativeEdges = [e.wrapped for e in edgeList] + nativeEdges = [e.wrapped for e in _get_edge_list(edgeList)] fillet_builder = BRepFilletAPI_MakeFillet(self.wrapped) @@ -4045,17 +4045,20 @@ def fillet(self: Any, radius: float, edgeList: Iterable[Edge]) -> Any: return self.__class__(fillet_builder.Shape()) def chamfer( - self: Any, length: float, length2: float | None, edgeList: Iterable[Edge] + self: Any, + length: float, + length2: float | None, + edgeList: Shape | Iterable[Edge], ) -> Any: """ Chamfers the specified edges of this solid. :param length: length > 0, the length (length) of the chamfer :param length2: length2 > 0, optional parameter for asymmetrical chamfer. Should be `None` if not required. - :param edgeList: a list of Edge objects, which must belong to this solid + :param edgeList: a list of Edge objects or a Shape containing edges, which must belong to this solid :return: Chamfered solid """ - nativeEdges = [e.wrapped for e in edgeList] + nativeEdges = [e.wrapped for e in _get_edge_list(edgeList)] # make a edge --> faces mapping edge_face_map = TopTools_IndexedDataMapOfShapeListOfShape() @@ -5304,6 +5307,17 @@ def _get_edges(*shapes: Shape) -> Iterable[Edge]: raise ValueError(f"Required type(s): Edge, Wire; encountered {t}") +def _get_edge_list(edges: Shape | Iterable[Edge]) -> Iterable[Edge]: + """ + Normalize a Shape or an iterable of edges to an iterable of edges. + """ + + if isinstance(edges, Shape): + return _get_edges(edges.edges()) + + return edges + + def _get_faces(*shapes: Shape) -> Iterable[Face]: """ Get faces or faces from wires or edges. diff --git a/tests/test_free_functions.py b/tests/test_free_functions.py index 24f7d8722..3802aefd8 100644 --- a/tests/test_free_functions.py +++ b/tests/test_free_functions.py @@ -1023,6 +1023,20 @@ def test_chamfer(): assert r.faces(">Z").Area() < 1 +@pytest.mark.parametrize("sel, n", [("|Z", 4), (">X and >Y", 1)]) +def test_fillet_chamfer_methods_shape_arg(sel, n): + + b = box(1, 1, 1) + edges = b.edges(sel) + + r1 = b.fillet(0.1, edges) + r2 = b.chamfer(0.1, None, edges) + + assert r1.isValid() + assert r2.isValid() + assert len(r1.Edges()) == len(r2.Edges()) == 12 + 3 * n + + def test_extrude(): v = vertex(0, 0, 0)