Skip to content

Wrong definition of the Compound #1817

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
XeuTap opened this issue Apr 24, 2025 · 3 comments
Closed

Wrong definition of the Compound #1817

XeuTap opened this issue Apr 24, 2025 · 3 comments
Labels
bug Something isn't working

Comments

@XeuTap
Copy link
Contributor

XeuTap commented Apr 24, 2025

The documentation says that Compound is "a collection of disconnected solids". But this is not the exact definition. If we refer to the OpenCascade documentation, we can find the following sentences:
"COMPOUND: A group of any of the shapes below."
TopAbs_ShapeEnum Description
"A TCompound is an all-purpose set of Shapes"
TopoDS_TCompound Description

This inaccuracy leads for the unexpected behavior.

Examples:

Compound's center of mass

sk = cadquery.Sketch().rect(50, 50).faces()
face1 = sk.val()
face2 = face1.copy().translate(Vector(100, 0, 0))
compound = cadquery.Compound.makeCompound([face1, face2])
compound_center = compound.Center()
Properties = GProp_GProps()
BRepGProp.SurfaceProperties_s(compound.wrapped, Properties)
expected_center = cadquery.Shape.CombinedCenter([face1, face2]) # Vector: (50, 0.0, 0.0)
actual_center = compound.Center() # Vector(0.0, 0.0, 0.0)

assert actual_center  == expected_center, "Incorrect center of mass of the compound, expected {}, got {}".format(expected_center, compound.Center())

The following code makes a compound consisting of 2 faces and calculates the center of mass. The problem is that shape_properties_LUT interpets TopAbs_COMPOUND as a volumetric shape and provides an incorrect result.

Shell

Similar behaviour occurs in the Shell.makeShell method

sk = cadquery.Sketch().rect(50, 50).faces()
face1 = sk.val()
face2 = face1.copy().translate(Vector(50, 0, 0))
face3 = face1.copy().translate(Vector(100, 0, 0))
shell_connected = cadquery.Shell.makeShell([face1, face2]) # TopoDS_Shell
assert isinstance(shell_connected.wrapped,TopoDS_Shell)
shell_disconnected = cadquery.Shell.makeShell([face1, face3]) # TopoDS_Compound
assert isinstance(shell_disconnected.wrapped, TopoDS_Shell), "Wrapped type mismatch, expected TopoDS_Shell, got {}".format(shell_disconnected.wrapped)

This code creates 2 shells: one from the connected faces, and another from disconnected. The type of the second shell is TopoDS_Compound, which corresponds to the OpenCascade definition. However, cadquery states that the wrapped attribute of the shell object should be TopoDS_Shell. If we call Center(), we'll get the same behaviour as in the previous example.

If this feedback is relevant, I’d be happy to open a PR with a solution that addresses the specific issue with Center(). However, I’m unsure whether other operations may also be affected by this underlying inconsistency.

@adam-urbanczyk adam-urbanczyk added the bug Something isn't working label Apr 24, 2025
@adam-urbanczyk
Copy link
Member

adam-urbanczyk commented Apr 24, 2025

Thanks, the Center() thing is definitely a bug. Regarding shell, I'd suggest using shell from the free function API. Parts of the cq.Shape API are rather dusty, and not really meant for end users.

Regarding PR, I'd rather reimplement Center() for cq.Compound.

@XeuTap
Copy link
Contributor Author

XeuTap commented Apr 25, 2025

Thank you, @adam-urbanczyk. I opened a PR where I reimplemented Center for cq.Compound. There is also a utility method that that inspects the Compound.
#1822

Regarding cq.Shell, in my opinion, this is not a major issue. Technically, it’s incorrect to attempt to create a shell from disconnected faces. A possible compromise from a UX perspective would be to handle this edge case and throw an exception.

@jmwright
Copy link
Member

This should be fixed via #1822

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants