diff --git a/cadquery/assembly.py b/cadquery/assembly.py index 60c2d42b6..d73b10a7d 100644 --- a/cadquery/assembly.py +++ b/cadquery/assembly.py @@ -4,7 +4,7 @@ from uuid import uuid1 as uuid from .cq import Workplane -from .occ_impl.shapes import Shape, Face, Edge, Wire +from .occ_impl.shapes import Shape, Compound, Face, Edge, Wire from .occ_impl.geom import Location, Vector, Plane from .occ_impl.assembly import Color from .occ_impl.solver import ( @@ -508,3 +508,14 @@ def _flatten(self, parents=[]): rv[PATH_DELIM.join(parents + [self.name])] = self return rv + + def toCompound(self) -> Compound: + """ + Returns a Compound made from this Assembly (including all children) with the + current Locations applied. Usually this method would only be used after solving. + """ + + shapes = self.shapes + shapes.extend((child.toCompound() for child in self.children)) + + return Compound.makeCompound(shapes).locate(self.loc) diff --git a/cadquery/occ_impl/shapes.py b/cadquery/occ_impl/shapes.py index 68fc07462..336cca3d1 100644 --- a/cadquery/occ_impl/shapes.py +++ b/cadquery/occ_impl/shapes.py @@ -899,7 +899,7 @@ def location(self) -> Location: return Location(self.wrapped.Location()) - def locate(self, loc: Location) -> "Shape": + def locate(self: T, loc: Location) -> T: """ Apply a location in absolute sense to self """ @@ -918,7 +918,7 @@ def located(self, loc: Location) -> "Shape": return r - def move(self, loc: Location) -> "Shape": + def move(self: T, loc: Location) -> T: """ Apply a location in relative sense (i.e. update current location) to self """ diff --git a/tests/test_assembly.py b/tests/test_assembly.py index fa06a403a..c3ef82724 100644 --- a/tests/test_assembly.py +++ b/tests/test_assembly.py @@ -391,3 +391,42 @@ def resulting_plane(shape0): # solid should fail fail_this(cq.Solid.makeBox(1, 1, 1)) + + +def test_toCompound(simple_assy, nested_assy): + + c0 = simple_assy.toCompound() + assert isinstance(c0, cq.Compound) + assert len(c0.Solids()) == 4 + + c1 = nested_assy.toCompound() + assert isinstance(c1, cq.Compound) + assert len(c1.Solids()) == 4 + + # check nested assy location appears in compound + # create four boxes, stack them on top of each other, check highest face is in final compound + box0 = cq.Workplane().box(1, 1, 3, centered=(True, True, False)) + box1 = cq.Workplane().box(1, 1, 4) + box2 = cq.Workplane().box(1, 1, 5) + box3 = cq.Workplane().box(1, 1, 6) + # top level assy + assy0 = cq.Assembly(box0, name="box0") + assy0.add(box1, name="box1") + assy0.constrain("box0@faces@>Z", "box1@faces@Z", "box3@faces@Z", "assy1/box2@faces@