jimy-byerley / pymadcad

Simple yet powerful CAD (Computer Aided Design) library, written with Python.
https://madcad.netlify.app/
GNU Lesser General Public License v3.0
211 stars 17 forks source link

Ask for example: mesh interoperation through vertices and faces with other libraries #91

Open 1939938853 opened 1 year ago

1939938853 commented 1 year ago

Hello,

Just wonder if it is possible to construct a madcad mesh with just numpy array vertices and numpy array faces, and also back to numpy array vertices and numpy array faces from madcad mesh.

Thanks

jimy-byerley commented 1 year ago

Hello, Of course it is possible to numpy arrays.

madcad meshes are using typedlist to store vertices and faces, because it directly works with pyglm and because lists can be resized. If you need to convert it to numpy you can because typedlist supports the buffer protocol. This will provide you a numpy array with a structured dtype (x,y,z).

To ease the conversion to unstructured dtypes (which are more common), there is functions typedlist_to_numpy() and numpy_to_typedlist()

>>> cube = mc.brick(width=vec3(1))

# extract points
>>> print(cube.points)
typedlist([dvec3( 0.5, -0.5, -0.5 ), ...])

# convert it to structured numpy
>>> np.asarray(cube.points)
array([( 0.5, -0.5, -0.5), ...],
      dtype=[('f0', '<f8'), ('f1', '<f8'), ('f2', '<f8')])

# convert it to unstructured numpy
>>> mc.typedlist_to_numpy(cube.points, 'f8')
array([[ 0.5, -0.5, -0.5], ...], dtype=float64)

Now to convert a whole mesh from and to other libraries formats, you will need to cast the foreign mesh from/to numpy arrays yourself. madcad does not provide conversions into other libraries proper data formats.

import madcad, pymesh
from madcad.mesh import numpy_to_typedlist, typedlist_to_numpy

# assuming you have data from pymesh
pymesh_source = pymesh.load_mesh("cube.obj")
pymadcad_object = madcad.Mesh(numpy_to_typedlist(pymesh_source.vertices, vec3), numpy_to_typedlist(pymesh_source.faces, uvec3))
pymesh_back = pymesh.form_mesh(typedlist_to_numpy(pymadcad_object.points, 'f4'), typedlist_to_numpy(pymadcad_object.faces, 'u4'))

edit: forgot dtypes in pymesh conversions

1939938853 commented 1 year ago

Great. Thank you Jimy!

jimy-byerley commented 1 year ago

I think such conversion is easy enough to not write an example program in folder examples, but We might add it to the documentation's guide :thinking:

1939938853 commented 1 year ago

I tried to convert open3d mesh to madcad mesh without success.

` import madcad as mc

import open3d as o3d

import numpy as np

vertices = np.asarray( o3d_mesh.vertices,dtype=np.float32) faces = np.asarray(o3d_mesh.triangles, dtype=np.uint)

mc_mesh = mc.Mesh(mc.mesh.numpy_to_typedlist(vertices, dtype=np.float32), mc.mesh.numpy_to_typedlist(faces), dtype=np.uint)

mc.show([mc_mesh])

` The error message is

File "D:\Anaconda3\envs\sp1\lib\site-packages\pymadcad-0.15.1-py3.9-win-amd64.egg\madcad\mesh\container.py", line 264, in numpy_to_typedlist ndtype = np.array(typedlist(dtype)).dtype File "arrex/list.pyx", line 155, in arrex.list.typedlist.__init__ File "arrex/dtypes.pyx", line 357, in arrex.dtypes.declared File "arrex/dtypes.pyx", line 339, in arrex.dtypes.declare File "arrex/dtypes.pyx", line 110, in arrex.dtypes.DDTypeClass ValueError: dsize must not be null, __packlayout__ or __packsize__ must be correctly defined in the given type

jimy-byerley commented 1 year ago

you should try the triple backticks ``` to escape code and backtraces, and don't forget the syntax highlight which makes it easier to read