CadQuery / cadquery

A python parametric CAD scripting framework based on OCCT
https://cadquery.readthedocs.io
Other
2.98k stars 281 forks source link

Argument type of `cadquery.occ_impl.shapes.Solid.makeSolid` #1505

Open smurfix opened 6 months ago

smurfix commented 6 months ago

I'm calling cadquery.occ_impl.shapes.Solid.makeSolid with a cadquery.occ_impl.shapes.Shell object.

The body of this function is the one-liner

return cls(ShapeFix_Solid().SolidFromShell(shell.wrapped))

My problem is that SolidFromShell complains that it wants an OCP.TopoDS.TopoDS_Shell object as a parameter. shell.wrapped however contains an OCP.TopoDS.TopoDS_Compound:

TypeError: SolidFromShell(): incompatible function arguments. The following argument types aresupported:
    1. (self: OCP.ShapeFix.ShapeFix_Solid, shell: OCP.TopoDS.TopoDS_Shell) -> OCP.TopoDS.TopoDS_Solid

Invoked with: <OCP.ShapeFix.ShapeFix_Solid object at 0x7f6ef6fc3fb0>, <OCP.TopoDS.TopoDS_Compound object at 0x7f6ef6fbbf70>

Naïvely I'd assume that wrapping a shell returns, well, the appropriate shell object.

Is that a bug? if not how do I call this correctly?

My usecase is importing an STL mesh, using the script at https://github.com/JustinSDK/cqMore/blob/main/examples/import_stl.py – if there's another / better / less-buggy way of doing this I'm all ears.

lorenzncode commented 6 months ago

The import_stl script worked for me after splitting the original mesh (https://github.com/JustinSDK/cqMore/issues/7).

# numpy-stl 2.16 or later is required.
from stl.mesh import Mesh
from cqmore import Workplane

def import_stl(fileName):
    vectors = Mesh.from_file(fileName).vectors
    points = tuple(map(tuple, vectors.reshape((vectors.shape[0] * vectors.shape[1], 3))))
    faces = [(i, i + 1, i + 2) for i in range(0, len(points), 3)]
    return Workplane().polyhedron(points, faces)

# projection.stl from https://github.com/openscad/openscad/blob/master/examples/Basics/projection.stl
part0 = import_stl("projection_part_0.stl")
part1 = import_stl("projection_part_1.stl").translate((10, 0, 0))

Here shown in cq-editor and admeshgui (used to split mesh): image

smurfix commented 6 months ago

Owch. Is there a way to do the splitting in CQ? Telling people "no you can't import a mesh with more than one part" isn't what I'd like to be doing here.

lorenzncode commented 6 months ago

The import STL script function is a cqMore feature not a cadquery feature. Changes to cqMore are required to handle this STL without split.

Regarding cadquery Shell.makeShell, as tested here https://github.com/CadQuery/cadquery/blob/e9b8b31f6a5421c1692b4e722e89d64736e349ca/tests/test_cadquery.py#L3940 the wrapped object is TopoDS_Shell. I confirm that with multiple sets of faces, the wrapped object is a TopoDS_Compound - in the following example containing two shells.:

import cadquery as cq

b0 = cq.Workplane().box(10, 10, 10)
b1 = cq.Workplane().box(2, 2, 2)

f0 = b0.faces().vals()
f1 = b1.faces().vals()

#faces = f0
faces = f0.copy()
faces.extend(f1)

shell = cq.Shell.makeShell(faces)