diff --git a/src/build123d/build_common.py b/src/build123d/build_common.py index 9e68c58..9bcbe9b 100644 --- a/src/build123d/build_common.py +++ b/src/build123d/build_common.py @@ -421,7 +421,7 @@ class Builder(ABC): raise RuntimeError("Nothing to intersect with") self._obj = self._obj.intersect(*typed[self._shape]) elif mode == Mode.REPLACE: - self._obj = Compound.make_compound(list(typed[self._shape])) + self._obj = Compound(list(typed[self._shape])) if self._obj is not None and clean: self._obj = self._obj.clean() @@ -452,9 +452,7 @@ class Builder(ABC): if isinstance(self._obj, Compound): self._obj = self._sub_class(self._obj.wrapped) else: - self._obj = self._sub_class( - Compound.make_compound(self._shapes()).wrapped - ) + self._obj = self._sub_class(Compound(self._shapes()).wrapped) # Add to pending if self._tag == "BuildPart": diff --git a/src/build123d/build_sketch.py b/src/build123d/build_sketch.py index aa017bd..ca66c7a 100644 --- a/src/build123d/build_sketch.py +++ b/src/build123d/build_sketch.py @@ -82,7 +82,7 @@ class BuildSketch(Builder): global_objs = [] for plane in workplanes: global_objs.append(plane.from_local_coords(self._obj)) - return Sketch(Compound.make_compound(global_objs).wrapped) + return Sketch(Compound(global_objs).wrapped) def __init__( self, diff --git a/src/build123d/exporters.py b/src/build123d/exporters.py index 6b24bd0..0ada589 100644 --- a/src/build123d/exporters.py +++ b/src/build123d/exporters.py @@ -139,8 +139,8 @@ class Drawing: BRepLib.BuildCurves3d_s(el, TOLERANCE) # Convert and store the results. - self.visible_lines = Compound.make_compound(map(Shape, visible)) - self.hidden_lines = Compound.make_compound(map(Shape, hidden)) + self.visible_lines = Compound(map(Shape, visible)) + self.hidden_lines = Compound(map(Shape, hidden)) # --------------------------------------------------------------------------- @@ -149,6 +149,7 @@ class Drawing: class AutoNameEnum(Enum): """An enum class that automatically sets members' value to their name.""" + @staticmethod def _generate_next_value_(name, start, count, last_values): return name @@ -865,6 +866,7 @@ class ExportSVG(Export2D): ValueError: Invalid unit. """ + # pylint: disable=too-many-instance-attributes _Converter = Callable[[Edge], ET.Element] @@ -1375,7 +1377,11 @@ class ExportSVG(Export2D): ltname = layer.line_type.value _, pattern = Export2D.LINETYPE_DEFS[ltname] - d = self.dot_length.value if isinstance(self.dot_length, DotLength) else self.dot_length + d = ( + self.dot_length.value + if isinstance(self.dot_length, DotLength) + else self.dot_length + ) pattern = copy(pattern) plen = len(pattern) for i in range(0, plen): diff --git a/src/build123d/importers.py b/src/build123d/importers.py index 7a5c7cd..218694f 100644 --- a/src/build123d/importers.py +++ b/src/build123d/importers.py @@ -45,6 +45,7 @@ from svgpathtools import svg2paths from build123d.geometry import Color from build123d.topology import Compound, Face, Shape, ShapeList, Wire + def import_brep(file_name: str) -> Shape: """Import shape from a BREP file @@ -86,7 +87,7 @@ def import_step(file_name: str) -> Compound: reader = STEPControl_Reader() read_status = reader.ReadFile(file_name) # pylint fails to understand OCP's module here, so suppress on the next line. - if read_status != OCP.IFSelect.IFSelect_RetDone: # pylint: disable=no-member + if read_status != OCP.IFSelect.IFSelect_RetDone: # pylint: disable=no-member raise ValueError(f"STEP File {file_name} could not be loaded") for i in range(reader.NbRootsForTransfer()): reader.TransferRoot(i + 1) @@ -100,7 +101,7 @@ def import_step(file_name: str) -> Compound: for shape in occ_shapes: solids.append(Shape.cast(shape)) - return Compound.make_compound(solids) + return Compound(solids) def import_stl(file_name: str) -> Face: diff --git a/src/build123d/joints.py b/src/build123d/joints.py index 6993721..a0baaf7 100644 --- a/src/build123d/joints.py +++ b/src/build123d/joints.py @@ -221,7 +221,7 @@ class RevoluteJoint(Joint): """A CAD symbol representing the axis of rotation as bound to part""" radius = self.parent.bounding_box().diagonal / 30 - return Compound.make_compound( + return Compound( [ Edge.make_line((0, 0, 0), (0, 0, radius * 10)), Edge.make_circle(radius), @@ -328,7 +328,7 @@ class LinearJoint(Joint): def symbol(self) -> Compound: """A CAD symbol of the linear axis positioned relative to_part""" radius = (self.linear_range[1] - self.linear_range[0]) / 15 - return Compound.make_compound( + return Compound( [ Edge.make_line( (0, 0, self.linear_range[0]), (0, 0, self.linear_range[1]) @@ -492,13 +492,14 @@ class CylindricalJoint(Joint): Raises: ValueError: angle_reference must be normal to axis """ + # pylint: disable=too-many-instance-attributes @property def symbol(self) -> Compound: """A CAD symbol representing the cylindrical axis as bound to part""" radius = (self.linear_range[1] - self.linear_range[0]) / 15 - return Compound.make_compound( + return Compound( [ Edge.make_line( (0, 0, self.linear_range[0]), (0, 0, self.linear_range[1]) @@ -640,7 +641,7 @@ class BallJoint(Joint): circle_y = Edge.make_circle(radius, self.angle_reference.rotated((90, 0, 0))) circle_z = Edge.make_circle(radius, self.angle_reference.rotated((0, 90, 0))) - return Compound.make_compound( + return Compound( [ circle_x, circle_y, diff --git a/src/build123d/objects_part.py b/src/build123d/objects_part.py index 483dc7b..015f471 100644 --- a/src/build123d/objects_part.py +++ b/src/build123d/objects_part.py @@ -92,15 +92,15 @@ class BasePartObject(Part): context._add_to_context(*new_solids, mode=mode) if len(new_solids) > 1: - new_part = Compound.make_compound(new_solids).wrapped + new_part = Compound(new_solids).wrapped elif isinstance(new_solids[0], Compound): # Don't add extra layers new_part = new_solids[0].wrapped else: - new_part = Compound.make_compound(new_solids).wrapped + new_part = Compound(new_solids).wrapped super().__init__( obj=new_part, - # obj=Compound.make_compound(new_solids).wrapped, + # obj=Compound(new_solids).wrapped, label=part.label, material=part.material, joints=part.joints, diff --git a/src/build123d/objects_sketch.py b/src/build123d/objects_sketch.py index 4dc1603..d65adb7 100644 --- a/src/build123d/objects_sketch.py +++ b/src/build123d/objects_sketch.py @@ -83,7 +83,7 @@ class BaseSketchObject(Sketch): if isinstance(context, BuildSketch): context._add_to_context(*new_faces, mode=mode) - super().__init__(Compound.make_compound(new_faces).wrapped) + super().__init__(Compound(new_faces).wrapped) class Circle(BaseSketchObject): diff --git a/src/build123d/operations_generic.py b/src/build123d/operations_generic.py index 655442b..f57d9a3 100644 --- a/src/build123d/operations_generic.py +++ b/src/build123d/operations_generic.py @@ -188,7 +188,7 @@ def add( else: raise RuntimeError(f"Builder {context.__class__.__name__} is unsupported") - return Compound.make_compound(new_objects) + return Compound(new_objects) def bounding_box( @@ -234,7 +234,7 @@ def bounding_box( ) if context is not None: context._add_to_context(*new_faces, mode=mode) - return Sketch(Compound.make_compound(new_faces).wrapped) + return Sketch(Compound(new_faces).wrapped) new_objects = [] for obj in object_list: @@ -251,7 +251,7 @@ def bounding_box( ) if context is not None: context._add_to_context(*new_objects, mode=mode) - return Part(Compound.make_compound(new_objects).wrapped) + return Part(Compound(new_objects).wrapped) #:TypeVar("ChamferFilletType"): Type of objects which can be chamfered or filleted @@ -326,7 +326,7 @@ def chamfer( if context is not None: context._add_to_context(new_part, mode=Mode.REPLACE) - return Part(Compound.make_compound([new_part]).wrapped) + return Part(Compound([new_part]).wrapped) if target._dim == 2: # Convert BaseSketchObject into Sketch so casting into Sketch during construction works @@ -344,7 +344,7 @@ def chamfer( ) else: new_faces.append(face) - new_sketch = Sketch(Compound.make_compound(new_faces).wrapped) + new_sketch = Sketch(Compound(new_faces).wrapped) if context is not None: context._add_to_context(new_sketch, mode=Mode.REPLACE) @@ -428,7 +428,7 @@ def fillet( if context is not None: context._add_to_context(new_part, mode=Mode.REPLACE) - return Part(Compound.make_compound([new_part]).wrapped) + return Part(Compound([new_part]).wrapped) if target._dim == 2: # Convert BaseSketchObject into Sketch so casting into Sketch during construction works @@ -445,7 +445,7 @@ def fillet( new_faces.append(face.fillet_2d(radius, vertices_in_face)) else: new_faces.append(face) - new_sketch = Sketch(Compound.make_compound(new_faces).wrapped) + new_sketch = Sketch(Compound(new_faces).wrapped) if context is not None: context._add_to_context(new_sketch, mode=Mode.REPLACE) @@ -522,7 +522,7 @@ def mirror( if context is not None: context._add_to_context(*mirrored, mode=mode) - mirrored_compound = Compound.make_compound(mirrored) + mirrored_compound = Compound(mirrored) if all([obj._dim == 3 for obj in object_list]): return Part(mirrored_compound.wrapped) if all([obj._dim == 2 for obj in object_list]): @@ -656,7 +656,7 @@ def offset( if context is not None: context._add_to_context(*new_objects, mode=mode) - offset_compound = Compound.make_compound(new_objects) + offset_compound = Compound(new_objects) if all([obj._dim == 3 for obj in object_list]): return Part(offset_compound.wrapped) if all([obj._dim == 2 for obj in object_list]): @@ -806,7 +806,7 @@ def project( if projected_points: result = ShapeList(projected_points) else: - result = Compound.make_compound(projected_shapes) + result = Compound(projected_shapes) if all([obj._dim == 2 for obj in object_list]): result = Sketch(result.wrapped) elif all([obj._dim == 1 for obj in object_list]): @@ -881,7 +881,7 @@ def scale( if context is not None: context._add_to_context(*new_objects, mode=mode) - scale_compound = Compound.make_compound(new_objects) + scale_compound = Compound(new_objects) if all([obj._dim == 3 for obj in object_list]): return Part(scale_compound.wrapped) if all([obj._dim == 2 for obj in object_list]): @@ -934,7 +934,7 @@ def split( if context is not None: context._add_to_context(*new_objects, mode=mode) - split_compound = Compound.make_compound(new_objects) + split_compound = Compound(new_objects) if all([obj._dim == 3 for obj in object_list]): return Part(split_compound.wrapped) if all([obj._dim == 2 for obj in object_list]): @@ -1059,5 +1059,5 @@ def sweep( new_faces = [face.clean() for face in new_faces] if new_solids: - return Part(Compound.make_compound(new_solids).wrapped) - return Sketch(Compound.make_compound(new_faces).wrapped) + return Part(Compound(new_solids).wrapped) + return Sketch(Compound(new_faces).wrapped) diff --git a/src/build123d/operations_part.py b/src/build123d/operations_part.py index 454cb56..0a46bf3 100644 --- a/src/build123d/operations_part.py +++ b/src/build123d/operations_part.py @@ -176,7 +176,7 @@ def extrude( if clean: new_solids = [solid.clean() for solid in new_solids] - return Part(Compound.make_compound(new_solids).wrapped) + return Part(Compound(new_solids).wrapped) def loft( @@ -250,7 +250,7 @@ def loft( elif clean: new_solid = new_solid.clean() - return Part(Compound.make_compound([new_solid]).wrapped) + return Part(Compound([new_solid]).wrapped) def make_brake_formed( @@ -356,7 +356,7 @@ def make_brake_formed( elif clean: new_solid = new_solid.clean() - return Part(Compound.make_compound([new_solid]).wrapped) + return Part(Compound([new_solid]).wrapped) def project_workplane( @@ -472,7 +472,7 @@ def revolve( new_solids.append(Solid.revolve(profile, angle, axis)) - new_solid = Compound.make_compound(new_solids) + new_solid = Compound(new_solids) if context is not None: context._add_to_context(*new_solids, clean=clean, mode=mode) elif clean: @@ -541,7 +541,7 @@ def section( if clean: new_objects = [r.clean() for r in new_objects] - return Sketch(Compound.make_compound(new_objects).wrapped) + return Sketch(Compound(new_objects).wrapped) def thicken( @@ -616,4 +616,4 @@ def thicken( if clean: new_solids = [solid.clean() for solid in new_solids] - return Part(Compound.make_compound(new_solids).wrapped) + return Part(Compound(new_solids).wrapped) diff --git a/src/build123d/operations_sketch.py b/src/build123d/operations_sketch.py index ce85e4b..ed6149d 100644 --- a/src/build123d/operations_sketch.py +++ b/src/build123d/operations_sketch.py @@ -66,7 +66,7 @@ def make_face( context._add_to_context(pending_face, mode=mode) context.pending_edges = ShapeList() - return Sketch(Compound.make_compound([pending_face]).wrapped) + return Sketch(Compound([pending_face]).wrapped) def make_hull( @@ -104,7 +104,7 @@ def make_hull( context._add_to_context(pending_face, mode=mode) context.pending_edges = ShapeList() - return Sketch(Compound.make_compound([pending_face]).wrapped) + return Sketch(Compound([pending_face]).wrapped) def trace( diff --git a/src/build123d/topology.py b/src/build123d/topology.py index ce16a55..4c41000 100644 --- a/src/build123d/topology.py +++ b/src/build123d/topology.py @@ -1417,7 +1417,6 @@ class Shape(NodeMixin): material: str = "", joints: dict[str, Joint] = None, parent: Compound = None, - children: list[Shape] = None, ): self.wrapped = downcast(obj) if obj is not None else None self.for_construction = False @@ -1429,11 +1428,6 @@ class Shape(NodeMixin): if isinstance(self, Solid): self.joints = joints if joints else {} - # Bind joints and children to Compounds (other Shapes can't have children) - if isinstance(self, Compound): - self.joints = joints if joints else {} - self.children = children if children else [] - # parent must be set following children as post install accesses children self.parent = parent @@ -1695,7 +1689,7 @@ class Shape(NodeMixin): elif isinstance(self, Sketch): new_shape = Sketch(new_shape.wrapped) elif isinstance(self, (Wire, Curve)): - new_shape = Curve(Compound.make_compound(new_shape.edges()).wrapped) + new_shape = Curve(Compound(new_shape.edges()).wrapped) return new_shape @@ -1727,7 +1721,7 @@ class Shape(NodeMixin): elif isinstance(self, Sketch): new_shape = Sketch(new_shape.wrapped) elif isinstance(self, (Wire, Curve)): - new_shape = Curve(Compound.make_compound(new_shape.edges()).wrapped) + new_shape = Curve(Compound(new_shape.edges()).wrapped) return new_shape @@ -1747,7 +1741,7 @@ class Shape(NodeMixin): elif isinstance(self, Sketch): new_shape = Sketch(new_shape.wrapped) elif isinstance(self, (Wire, Curve)): - new_shape = Curve(Compound.make_compound(new_shape.edges()).wrapped) + new_shape = Curve(Compound(new_shape.edges()).wrapped) return new_shape @@ -2760,12 +2754,12 @@ class Shape(NodeMixin): if len(tops) == 1: result = tops[0] else: - result = Compound.make_compound(tops) + result = Compound(tops) elif keep == Keep.BOTTOM: if len(bottoms) == 1: result = bottoms[0] else: - result = Compound.make_compound(bottoms) + result = Compound(bottoms) return result def distance(self, other: Shape) -> float: @@ -3093,7 +3087,7 @@ class Shape(NodeMixin): logger.debug("finished projecting '%d' faces", len(faces)) - return Compound.make_compound(projected_faces) + return Compound(projected_faces) def _extrude( self, direction: VectorLike @@ -3136,7 +3130,7 @@ class Shape(NodeMixin): topods_solid = downcast(explorer.Current()) solids.append(Solid(topods_solid)) explorer.Next() - result = Compound.make_compound(solids) + result = Compound(solids) else: raise RuntimeError("extrude produced an unexpected result") return result @@ -3791,6 +3785,105 @@ class Compound(Mixin3D, Shape): _dim = None + @overload + def __init__( + self, + obj: TopoDS_Shape = None, + label: str = "", + color: Color = None, + material: str = "", + joints: dict[str, Joint] = None, + parent: Compound = None, + children: Iterable[Shape] = None, + ): + """Build a Compound from an OCCT TopoDS_Shape/TopoDS_Compound + + Args: + obj (TopoDS_Shape, optional): OCCT Compound. Defaults to None. + label (str, optional): Defaults to ''. + color (Color, optional): Defaults to None. + material (str, optional): tag for external tools. Defaults to ''. + joints (dict[str, Joint], optional): names joints. Defaults to None. + parent (Compound, optional): assembly parent. Defaults to None. + children (Iterable[Shape], optional): assembly children. Defaults to None. + """ + + @overload + def __init__( + self, + shapes: Iterable[Shape], + label: str = "", + color: Color = None, + material: str = "", + joints: dict[str, Joint] = None, + parent: Compound = None, + children: Iterable[Shape] = None, + ): + """Build a Compound from Shapes + + Args: + shapes (Iterable[Shape]): shapes within the compound + label (str, optional): Defaults to ''. + color (Color, optional): Defaults to None. + material (str, optional): tag for external tools. Defaults to ''. + joints (dict[str, Joint], optional): names joints. Defaults to None. + parent (Compound, optional): assembly parent. Defaults to None. + children (Iterable[Shape], optional): assembly children. Defaults to None. + """ + + def __init__(self, *args, **kwargs): + shapes, obj, label, color, material, joints, parent, children = (None,) * 8 + + if args: + l_a = len(args) + if isinstance(args[0], TopoDS_Shape): + obj, label, color, material, joints, parent, children = args[:7] + ( + None, + ) * (7 - l_a) + elif isinstance(args[0], Iterable): + shapes, label, color, material, joints, parent, children = args[:7] + ( + None, + ) * (7 - l_a) + + unknown_args = ", ".join( + set(kwargs.keys()).difference( + [ + "shapes", + "obj", + "label", + "material", + "color", + "joints", + "parent", + "children", + ] + ) + ) + if unknown_args: + raise ValueError(f"Unexpected argument(s) {unknown_args}") + + obj = kwargs.get("obj", obj) + shapes = kwargs.get("shapes", shapes) + material = kwargs.get("material", material) + joints = kwargs.get("joints", joints) + label = kwargs.get("label", label) + color = kwargs.get("color", color) + parent = kwargs.get("parent", parent) + children = kwargs.get("children", children) + + if shapes: + obj = Compound._make_compound([s.wrapped for s in shapes]) + + super().__init__( + obj=obj, + label="" if label is None else label, + color=color, + material="" if material is None else material, + parent=parent, + ) + self.joints = {} if joints is None else joints + self.children = [] if children is None else children + def __repr__(self): """Return Compound info as string""" if hasattr(self, "label") and hasattr(self, "children"): @@ -3865,6 +3958,12 @@ class Compound(Mixin3D, Shape): shapes: Iterable[Shape]: Returns: """ + warnings.warn( + "make_compound() will be deprecated - use the Compound constructor instead", + DeprecationWarning, + stacklevel=2, + ) + return cls(Compound._make_compound([s.wrapped for s in shapes])) def _remove(self, shape: Shape) -> Compound: @@ -4079,9 +4178,7 @@ class Compound(Mixin3D, Shape): if text_path is not None: path_length = text_path.length - text_flat = Compound.make_compound( - [position_face(f) for f in text_flat.faces()] - ) + text_flat = Compound([position_face(f) for f in text_flat.faces()]) return text_flat @@ -5322,7 +5419,7 @@ class Face(Shape): inner_wires = inner_wires if inner_wires else [] # check if wires are coplanar - verification_compound = Compound.make_compound([outer_wire] + inner_wires) + verification_compound = Compound([outer_wire] + inner_wires) if not BRepLib_FindSurface( verification_compound.wrapped, OnlyPlane=True ).Found(): @@ -5739,9 +5836,7 @@ class Face(Shape): Returns: ShapeList[Face]: Face(s) projected on target object ordered by distance """ - max_dimension = ( - Compound.make_compound([self, target_object]).bounding_box().diagonal - ) + max_dimension = Compound([self, target_object]).bounding_box().diagonal if taper == 0: face_extruded = Solid.extrude(self, Vector(direction) * max_dimension) else: @@ -5823,7 +5918,7 @@ class Face(Shape): bool: indicating whether or not point is within Face """ - return Compound.make_compound([self]).is_inside(point, tolerance) + return Compound([self]).is_inside(point, tolerance) class Shell(Shape): @@ -6244,11 +6339,7 @@ class Solid(Mixin3D, Shape): # make straight spine straight_spine_e = Edge.make_line(center, center.add(normal)) - straight_spine_w = Wire.combine( - [ - straight_spine_e, - ] - )[0].wrapped + straight_spine_w = Wire.combine([straight_spine_e])[0].wrapped # make an auxiliary spine pitch = 360.0 / angle * normal.length @@ -6268,7 +6359,7 @@ class Solid(Mixin3D, Shape): ] # combine the inner solids into compound - inner_comp = Compound.make_compound(inner_solids).wrapped + inner_comp = Compound._make_compound(inner_solids) # subtract from the outer solid return Solid(BRepAlgoAPI_Cut(outer_solid, inner_comp).Shape()) @@ -6304,9 +6395,7 @@ class Solid(Mixin3D, Shape): direction *= -1 until = Until.NEXT if until == Until.PREVIOUS else Until.LAST - max_dimension = ( - Compound.make_compound([section, target_object]).bounding_box().diagonal - ) + max_dimension = Compound([section, target_object]).bounding_box().diagonal clipping_direction = ( direction * max_dimension if until == Until.NEXT @@ -6866,7 +6955,7 @@ class Wire(Mixin1D, Shape): edges_in = TopTools_HSequenceOfShape() wires_out = TopTools_HSequenceOfShape() - for edge in Compound.make_compound(wires).edges(): + for edge in Compound(wires).edges(): edges_in.Append(edge.wrapped) ShapeAnalysis_FreeBounds.ConnectEdgesToWires_s(edges_in, tol, False, wires_out) diff --git a/tests/test_build_generic.py b/tests/test_build_generic.py index 629bf9a..30b440a 100644 --- a/tests/test_build_generic.py +++ b/tests/test_build_generic.py @@ -107,7 +107,7 @@ class AddTests(unittest.TestCase): # Add Compound with BuildPart() as test: add( - Compound.make_compound( + Compound( [ Solid.make_box(10, 10, 10), Solid.make_box(5, 5, 5, Plane((20, 20, 20))), @@ -116,7 +116,7 @@ class AddTests(unittest.TestCase): ) self.assertAlmostEqual(test.part.volume, 1125, 5) with BuildPart() as test: - add(Compound.make_compound([Edge.make_line((0, 0), (1, 1))])) + add(Compound([Edge.make_line((0, 0), (1, 1))])) self.assertEqual(len(test.pending_edges), 1) # Add Wire @@ -435,7 +435,7 @@ class MirrorTests(unittest.TestCase): edge = Edge.make_line((1, 0), (2, 0)) wire = Wire.make_circle(1, Plane((5, 0, 0))) face = Face.make_rect(2, 2, Plane((8, 0))) - compound = Compound.make_compound( + compound = Compound( [ Face.make_rect(2, 2, Plane((8, 8))), Face.make_rect(2, 2, Plane((8, -8))), diff --git a/tests/test_direct_api.py b/tests/test_direct_api.py index 07cebc2..74d2808 100644 --- a/tests/test_direct_api.py +++ b/tests/test_direct_api.py @@ -740,32 +740,32 @@ class TestCompound(DirectApiTestCase): def test_fuse(self): box1 = Solid.make_box(1, 1, 1) box2 = Solid.make_box(1, 1, 1, Plane((1, 0, 0))) - combined = Compound.make_compound([box1]).fuse(box2, glue=True) + combined = Compound([box1]).fuse(box2, glue=True) self.assertTrue(combined.is_valid()) self.assertAlmostEqual(combined.volume, 2, 5) - fuzzy = Compound.make_compound([box1]).fuse(box2, tol=1e-6) + fuzzy = Compound([box1]).fuse(box2, tol=1e-6) self.assertTrue(fuzzy.is_valid()) self.assertAlmostEqual(fuzzy.volume, 2, 5) def test_remove(self): box1 = Solid.make_box(1, 1, 1) box2 = Solid.make_box(1, 1, 1, Plane((2, 0, 0))) - combined = Compound.make_compound([box1, box2]) + combined = Compound([box1, box2]) self.assertTrue(len(combined._remove(box2).solids()), 1) def test_repr(self): - simple = Compound.make_compound([Solid.make_box(1, 1, 1)]) + simple = Compound([Solid.make_box(1, 1, 1)]) simple_str = repr(simple).split("0x")[0] + repr(simple).split(", ")[1] self.assertEqual(simple_str, "Compound at label()") - assembly = Compound.make_compound([Solid.make_box(1, 1, 1)]) + assembly = Compound([Solid.make_box(1, 1, 1)]) assembly.children = [Solid.make_box(1, 1, 1)] assembly.label = "test" assembly_str = repr(assembly).split("0x")[0] + repr(assembly).split(", l")[1] self.assertEqual(assembly_str, "Compound at abel(test), #children(1)") def test_center(self): - test_compound = Compound.make_compound( + test_compound = Compound( [ Solid.make_box(2, 2, 2).locate(Location((-1, -1, -1))), Solid.make_box(1, 1, 1).locate(Location((8.5, -0.5, -0.5))), @@ -807,6 +807,10 @@ class TestCompound(DirectApiTestCase): self.assertAlmostEqual(c.volume, 3, 5) # N.B. b and bb overlap but still add to Compound volume + def test_constructor(self): + with self.assertRaises(ValueError): + Compound(bob="fred") + class TestEdge(DirectApiTestCase): def test_close(self): @@ -3666,4 +3670,4 @@ class TestWire(DirectApiTestCase): if __name__ == "__main__": - unittest.main() + unittest.main(failfast=True) diff --git a/tests/test_mesher.py b/tests/test_mesher.py index a061bb4..b707c5d 100644 --- a/tests/test_mesher.py +++ b/tests/test_mesher.py @@ -148,7 +148,7 @@ class TestAddShape(DirectApiTestCase): exporter = Mesher() box = Solid.make_box(1, 1, 1) cone = Solid.make_cone(1, 0, 2).locate(Location((0, -1, 0))) - shape_assembly = Compound.make_compound([box, cone]) + shape_assembly = Compound([box, cone]) exporter.add_shape(shape_assembly) exporter.write("test.3mf") importer = Mesher() diff --git a/tests/test_persistence.py b/tests/test_persistence.py index 01dc31d..8acee21 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -17,7 +17,7 @@ class TestPersistence(unittest.TestCase): wire = Wire.make_circle(10) face = Face.make_rect(10, 5) solid = Solid.make_box(10, 5, 2) - compound = Compound.make_compound([edge, wire, face, solid]) + compound = Compound([edge, wire, face, solid]) buffer = serialize_shape(edge.wrapped) retrived_edge = deserialize_shape(buffer)