Skip to content

Broken Python bindings for 'VolumeSampling' utility. #367

@duburcqa

Description

@duburcqa

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions