Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 9 additions & 14 deletions cadquery/occ_impl/shapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -825,20 +825,15 @@ def _mass_calc_function(obj: Shape) -> Any:
# special handling of compounds - first non-compound child is assumed to define the type of the operation
if type_ == ta.TopAbs_COMPOUND:

# if the compound is not empty check its children
if obj:
# first child
child = next(iter(obj))

# if compound, go deeper
while child.ShapeType() == "Compound":
child = next(iter(child))

type_ = shapetype(child.wrapped)

# if the compound is empty assume it was meant to be a solid
else:
type_ = ta.TopAbs_SOLID
# descend to the first non-compound child, if any; the sentinel
# guards against an empty compound at the top level or nested inside
child = next(iter(obj), None)
while child is not None and child.ShapeType() == "Compound":
child = next(iter(child), None)

# an empty or empty-nested compound has no child to inspect;
# assume it was meant to be a solid (consistent with an empty compound)
type_ = ta.TopAbs_SOLID if child is None else shapetype(child.wrapped)

# get the function based on dimensionality of the object
return shape_properties_LUT[type_]
Expand Down
11 changes: 11 additions & 0 deletions tests/test_shapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,17 @@ def test_special():
assert cs[0].Volume() == approx(3 ** 3)


def test_nested_empty_compound_mass():

# a bare empty compound already resolves to zero mass
assert compound().Volume() == approx(0)

# a compound whose first child is an empty compound must not crash and
# must stay consistent with the bare empty compound (see issue #2078)
assert compound(compound()).Volume() == approx(0)
assert compound(compound()).Area() == approx(0)


def test_center():

v = vertex(1, 1, 1)
Expand Down