mikedh / trimesh

Python library for loading and using triangular meshes.
https://trimesh.org
MIT License
2.93k stars 573 forks source link

Question: Converting cadquery.occ_impl.shapes.Solid to an trimesh.Trimehs object or to trimesh.Scene #2255

Closed MenachemBerkovich closed 1 month ago

MenachemBerkovich commented 1 month ago

I have cadquery.occ_impl.shapes.Solid object that is extracted from some step file loading. I can create a trimesh object with my cadquery object data [like its vertices centers, faces ...]?

I tried this way but without success...

#cadquery Solid object
screw = solids.Solids()[0]
arr =[]
for vtx in screw.vertices().Vertices():
    arr += (vtx.Center().x, vtx.Center().y, vtx.Center().z)
import trimesh

t  = trimesh.Trimesh(vertices=arr)

But then:

t.show()

gives an error:

{
    "name": "IndexError",
    "message": "tuple index out of range",
    "stack": "---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Cell In[41], line 1
----> 1 t.show()

File e:\\Inabbeet\\web_apps_venv\\Lib\\site-packages\\trimesh\\base.py:2747, in Trimesh.show(self, **kwargs)
   2732 \"\"\"
   2733 Render the mesh in an opengl window. Requires pyglet.
   2734 
   (...)
   2744   Scene with current mesh in it
   2745 \"\"\"
   2746 scene = self.scene()
-> 2747 return scene.show(**kwargs)

File e:...Lib\\site-packages\\trimesh\\scene\\scene.py:1288, in Scene.show(self, viewer, **kwargs)
   1285 elif viewer == \"notebook\":
   1286     from ..viewer import scene_to_notebook
-> 1288     return scene_to_notebook(self, **kwargs)
   1289 elif callable(viewer):
   1290     # if a callable method like a custom class
   1291     # constructor was passed run using that
   1292     return viewer(self, **kwargs)

File e:...\\Lib\\site-packages\\trimesh\\viewer\
otebook.py:72, in scene_to_notebook(scene, height, **kwargs)
     69 from IPython import display
     71 # convert scene to a full HTML page
---> 72 as_html = scene_to_html(scene=scene)
     74 # escape the quotes in the HTML
     75 srcdoc = as_html.replace('\"', \""\")
----
File e:...\\Lib\\site-packages\\trimesh\\scene\\scene.py:342, in <dictcomp>(.0)
    332 vertices = {
    333     k: m.vertices
    334     for k, m in self.geometry.items()
    335     if hasattr(m, \"vertices\") and len(m.vertices) > 0
    336 }
    337 # handle 2D geometries
    338 vertices.update(
    339     {
    340         k: np.column_stack((v, np.zeros(len(v))))
    341         for k, v in vertices.items()
--> 342         if v.shape[1] == 2
    343     }
    344 )
    346 # loop through every node with geometry
    347 for node_name in self.graph.nodes_geometry:
    348     # access the transform and geometry name from node

IndexError: tuple index out of range"
}
Kiord commented 1 month ago

The first argument in Trimesh constructor must be of shape (V, 3) with V being the number of vertices. You provided a flat list x_1 y_1 z_1 ... x_n y_n z_n, of shape (V*3,). (the operator + between a list an a tuple appends its content at the end of the list)

Also you will need to get the vertex indices of the triangles and arrange them in a (T, 3) fashion. Then:

vertices = np.asarray(arr).reshape(-1,3) # your vertices but in a (V, 3) shape
faces = ... # faces in a (T, 3) fashion
mesh = trimesh.Trimesh(vertices, faces)
mikedh commented 1 month ago

Yeah @kiord is right you need to pass (n, 3) float vertices and (m, 3) int faces which are indexes of vertices. As a higher level note you may want to export the solid to a temporary file (i.e. a .GLB) and load that into trimesh, it is likely to be easier.