From 0bc0f3ea0a82af801b5e0f610e1a128ff09dd0f4 Mon Sep 17 00:00:00 2001 From: Aman Jain Date: Sat, 18 Jul 2026 17:48:09 -0700 Subject: [PATCH 1/2] fix: make box() parameter names consistent with Workplane.box and Solid.makeBox The standalone `box(w, l, h)` function used `w` (width) for the X axis and `l` (length) for the Y axis, which is the opposite convention from `Workplane.box(length, width, height)` and `Solid.makeBox(length, width, height)` where length=X and width=Y. Rename parameters to `box(length, width, height)` with docstring specifying axis mapping, matching the rest of the API. This is backward-compatible since all existing callers use positional arguments. Addresses #2011 --- cadquery/occ_impl/shapes.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/cadquery/occ_impl/shapes.py b/cadquery/occ_impl/shapes.py index 7d3c665a9..72c5cf5db 100644 --- a/cadquery/occ_impl/shapes.py +++ b/cadquery/occ_impl/shapes.py @@ -6553,14 +6553,21 @@ def plane() -> Face: return _shape(BRepBuilderAPI_MakeFace(pln_geom, -INF, INF, -INF, INF).Face(), Face) -def box(w: float, l: float, h: float) -> Solid: +def box(length: float, width: float, height: float) -> Solid: """ - Construct a solid box. + Construct a solid box centered on the XY plane. + + :param length: box size along the X axis + :param width: box size along the Y axis + :param height: box size along the Z axis """ return _shape( BRepPrimAPI_MakeBox( - gp_Ax2(Vector(-w / 2, -l / 2, 0).toPnt(), Vector(0, 0, 1).toDir()), w, l, h + gp_Ax2(Vector(-length / 2, -width / 2, 0).toPnt(), Vector(0, 0, 1).toDir()), + length, + width, + height, ).Shape(), Solid, ) From 7de0785db8ae052665976d225d79288ba2ec966c Mon Sep 17 00:00:00 2001 From: Aman Jain Date: Sat, 18 Jul 2026 17:49:33 -0700 Subject: [PATCH 2/2] feat: add toBOM() method to Assembly for bill of materials export Adds a toBOM() method to the Assembly class that generates a flat list of BOM line items from the assembly tree. Each entry includes the component name, nesting level, and whether it has geometry attached. This provides a structured way to extract a bill of materials from a CadQuery assembly, enabling integration with inventory/PLM systems like InvenTree or other downstream manufacturing tools. --- cadquery/assembly.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/cadquery/assembly.py b/cadquery/assembly.py index fdf98dd73..0e79f3f55 100644 --- a/cadquery/assembly.py +++ b/cadquery/assembly.py @@ -627,6 +627,37 @@ def export( return self + def toBOM( + self, + indent: int = 0, + _result: Optional[List[Dict[str, Any]]] = None, + ) -> List[Dict[str, Any]]: + """ + Generate a Bill of Materials (BOM) for this assembly. + + Returns a flat list of dictionaries, one per component, with fields: + - name: component name + - level: nesting depth (0 = root) + - has_shape: whether the component has geometry + + :param indent: current nesting level (used internally for recursion) + :return: list of BOM line items + """ + + if _result is None: + _result = [] + + _result.append({ + "name": self.name, + "level": indent, + "has_shape": self.obj is not None, + }) + + for child in self.children: + child.toBOM(indent=indent + 1, _result=_result) + + return _result + @classmethod def importStep(cls, path: str, unit: UnitLiterals = "MM") -> Self: """