Skip to content

distance_to_medial_mesh

distance_to_medial_mesh(P, C, R, E=None, F=None, device='auto')

Signed distance from points to the volume of a medial mesh.

A medial mesh represents the union of its medial spheres, medial cones (convex hulls of the two spheres of an edge) and medial slabs (convex hulls of the three spheres of a face). This function returns, for every query point, the distance to that union and the closest primitive. It is the building block for measuring how well a medial mesh approximates a shape (e.g. the one-sided Hausdorff distance from surface samples).

Parameters:

Name Type Description Default
P (p,3) numpy double array

Query points.

required
C (n,3) numpy double array

Sphere centers.

required
R (n,) numpy double array

Sphere radii.

required
E (e,2) numpy int array, optional (default None)

Medial edges.

None
F (f,3) numpy int array, optional (default None)

Medial faces.

None
device (auto, cpu, cuda)

"cuda" runs the CUDA kernel (single precision, requires a build with CUDA), "cpu" runs a multi-threaded double precision implementation, "auto" uses CUDA when available.

"auto"

Returns:

Name Type Description
D (p,) numpy double array

Signed distances: positive outside the union, negative inside (inside it is the largest penetration depth over the primitives, not an exact signed distance).

prim_type (p,) numpy int array

Type of the closest primitive: 0 sphere, 1 cone, 2 slab.

prim_id (p,) numpy int array

Index of the closest primitive in C, E or F (by prim_type).

Notes

The cost is O(p * (n + e + f)): every point is tested against every primitive.

C++: void libmat::distance_to_medial_mesh(P, C, R, E, F, use_cuda, D, prim_type, prim_id) in <libmat/distance_to_medial_mesh.h>.

Examples:

import numpy as np
import libmat
SV, SF = libmat.read_surface_mesh("data/bug.obj")
V, R, E, F = libmat.read_ma("data/bug.ma")
D, prim_type, prim_id = libmat.distance_to_medial_mesh(SV, V, R, E, F)
print("max |distance| surface -> MAT:", np.abs(D).max())

CPU and CUDA

Runs on the CPU in every build, and on the GPU (device="cuda") when libmat is built with LIBMAT_WITH_CUDA=ON.

C++

#include <libmat/distance_to_medial_mesh.h>

// Signed distance from query points to the volume represented by a medial
// mesh: the union of all medial spheres, medial cones (edges) and medial
// slabs (faces). The distance is positive outside the union and negative
// inside (inside it is the largest penetration depth over all primitives,
// not an exact signed distance).
//
// Inputs:
//   P  #P by 3 query points
//   C  #V by 3 sphere centers
//   R  #V sphere radii
//   E  #E by 2 medial edges (can be empty)
//   F  #F by 3 medial faces (can be empty)
//   use_cuda  compute on the GPU (requires a build with LIBMAT_WITH_CUDA=ON,
//             computes in single precision), otherwise multi-threaded CPU
// Outputs:
//   D          #P signed distances
//   prim_type  #P type of the closest primitive: 0 sphere, 1 cone, 2 slab
//   prim_id    #P index of the closest primitive in C, E or F
void distance_to_medial_mesh(const Eigen::MatrixXd& P,
                             const Eigen::MatrixXd& C,
                             const Eigen::VectorXd& R,
                             const Eigen::MatrixXi& E,
                             const Eigen::MatrixXi& F, bool use_cuda,
                             Eigen::VectorXd& D, Eigen::VectorXi& prim_type,
                             Eigen::VectorXi& prim_id);