-
Notifications
You must be signed in to change notification settings - Fork 309
Description
Although Python bindings have been exported for 'VolumeSampling', they are actually unusable:
The expected is as follows:
1. (arg0: typing.SupportsInt, arg1: typing.Annotated[numpy.typing.ArrayLike, numpy.float32, "[3, 1]"], arg2: typing.SupportsInt, arg3: typing.SupportsInt, arg4: typing.SupportsFloat, arg5: Eigen::AlignedBox<float, 3>, arg6: typing.Annotated[collections.abc.Sequence[typing.SupportsInt], "FixedSize(3)"], arg7: bool, arg8: typing.SupportsInt, arg9: pysplishsplash.Utilities.VecVector3r) -> None
But there is no way to specify such input arguments, in particular Eigen::AlignedBox
, which is not exposed in Python. Anyway, this signature looks plain wrong anyway, given that the original C++ signature is the following:
void VolumeSampling::sampleMesh(const unsigned int numVertices, const Vector3r *vertices,
const unsigned int numFaces, const unsigned int *faces,
const Real radius, const AlignedBox3r *region,
const std::array<unsigned int, 3> &resolution, const bool invert,
const unsigned int sampleMode,
std::vector<Vector3r> &samples)
This way of passing C++ pointers to arrays is fragile from Python, if not completely broken. I think it should be possible to pass the low-level c memory address for faces, and what to specify for vertices is very much unclear.
Here is what I tried, without success:
import numpy as np
import pysplishsplash
# Define cube vertices
vertices = np.array([
[-0.5, -0.5, -0.5],
[ 0.5, -0.5, -0.5],
[ 0.5, 0.5, -0.5],
[-0.5, 0.5, -0.5],
[-0.5, -0.5, 0.5],
[ 0.5, -0.5, 0.5],
[ 0.5, 0.5, 0.5],
[-0.5, 0.5, 0.5],
], dtype=np.float32)
# Define faces as a single, flattened list of indices
faces = np.array([
0, 1, 2, # Front face
0, 2, 3,
4, 6, 5, # Back face
4, 7, 6,
0, 4, 5, # Bottom face
0, 5, 1,
1, 5, 6, # Right face
1, 6, 2,
2, 6, 7, # Top face
2, 7, 3,
3, 7, 4, # Left face
3, 4, 0,
], dtype=np.uint32)
samples = pysplishsplash.Utilities.VecVector3r()
faces = mesh.faces.astype(np.int32)
vertices_vec = pysplishsplash.Utilities.VecVector3r()
for vert in vertices:
vertices_vec.append(vert)
pysplishsplash.Utilities.VolumeSampling.sampleMesh(
len(vertices), # 'numVertices'
vertices_vec, # vertices, # 'vertices'
len(faces), # 'numFaces'
faces.ctypes.data, # 'faces' (array ptr)
1.0, # 'radius'
np.array([[-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]], dtype=np.float32), # 'region'
(32, 32, 32), # 'resolution'
False, # 'invert'
4, # 'sampleMode'
samples, # 'samples'
)
for sample in samples:
print(sample)
Finally, pysplishsplash.Utilities.VolumeSampling.sampleMesh
is not the same as the command line VolumeSampling
utility, which is what I'm looking for. It appears there is no programmatic Python way to do the same without resorting to calling subprocess. Typically there is no bindings for SPHVolumeSampling
, which is what VolumeSampling
is using by default under the hood.
Once least-effort fix would be to ship these binary utilities as part of the Python wheels, so that one can call them by simply instead a python package without having to compile from source.