From f376514fb7bfa190343736cb3fb9e0d43cc031ff Mon Sep 17 00:00:00 2001 From: Alex Kaszynski Date: Thu, 8 Jan 2026 17:19:48 -0700 Subject: [PATCH 1/2] Add is_intrinsic_delaunay function --- src/is_intrinsic_delaunay.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/is_intrinsic_delaunay.cpp diff --git a/src/is_intrinsic_delaunay.cpp b/src/is_intrinsic_delaunay.cpp new file mode 100644 index 00000000..2d118f58 --- /dev/null +++ b/src/is_intrinsic_delaunay.cpp @@ -0,0 +1,33 @@ +#include "default_types.h" +#include +#include +#include +#include + +namespace nb = nanobind; +using namespace nb::literals; +namespace pyigl +{ + auto is_intrinsic_delaunay( + const nb::DRef &l, + const nb::DRef &F) + { + Eigen::Matrix D; + igl::is_intrinsic_delaunay(l, F, D); + return D; + } +} + +void bind_is_intrinsic_delaunay(nb::module_ &m) +{ + m.def("is_intrinsic_delaunay", &pyigl::is_intrinsic_delaunay, + "l"_a, + "F"_a, + R"(Determine if each edge in the mesh (V,F) is Delaunay. +@param[in] l #l by dim list of edge lengths +@param[in] F #F by 3 list of triangles indices +@param[out] D D #F by 3 list of bools revealing whether edges corresponding + 23 31 12 are locally Delaunay. Boundary edges are by definition Delaunay. + Non-Manifold edges are by definition not Delaunay. +)"); +} From fc8010eb2657392ed1a4b633cfa6294ddc6e77c2 Mon Sep 17 00:00:00 2001 From: Alex Kaszynski Date: Fri, 9 Jan 2026 08:42:06 -0700 Subject: [PATCH 2/2] Add test for is_intrinsic_delaunay function --- tests/test_all.py | 61 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/tests/test_all.py b/tests/test_all.py index b666a4e7..e035c9f1 100644 --- a/tests/test_all.py +++ b/tests/test_all.py @@ -600,3 +600,64 @@ def udf_sphere(Q): unique_ijk, J, unique_corners = igl.unique_sparse_voxel_corners(origin,h0,max_depth,ijk) unique_S = sdf_sphere(unique_corners) V,F = igl.marching_cubes(unique_S,unique_corners,J,0.0) + +def test_is_intrinsic_delaunay() -> None: + # vs and fs come from a simple plane from pyvista + # mesh = pv.Plane(i_resolution=3, j_resolution=2, i_size=2).triangulate() + # fs = mesh._connectivity_array.reshape(-1, 3).astype(np.int32) + # vs = mesh.points.astype(np.float64) + + fs = np.array( + [ + [0, 1, 4], + [1, 5, 4], + [1, 2, 5], + [2, 6, 5], + [2, 3, 6], + [3, 7, 6], + [4, 5, 8], + [5, 9, 8], + [5, 6, 9], + [6, 10, 9], + [6, 7, 10], + [7, 11, 10], + ] + ) + + vs = np.array( + [ + [-1.0, -0.5, 0.0], + [-0.33333334, -0.5, 0.0], + [0.33333334, -0.5, 0.0], + [1.0, -0.5, 0.0], + [-1.0, 0.0, 0.0], + [-0.33333334, 0.0, 0.0], + [0.33333334, 0.0, 0.0], + [1.0, 0.0, 0.0], + [-1.0, 0.5, 0.0], + [-0.33333334, 0.5, 0.0], + [0.33333334, 0.5, 0.0], + [1.0, 0.5, 0.0], + ] + ) + + lin = igl.edge_lengths(vs, fs) + mask = igl.is_intrinsic_delaunay(lin, fs).astype(bool) + + expected_mask = np.array( + [ + [0, 1, 1], + [1, 0, 1], + [1, 1, 1], + [1, 1, 1], + [0, 1, 1], + [1, 0, 1], + [0, 1, 1], + [1, 0, 1], + [1, 1, 1], + [1, 1, 1], + [0, 1, 1], + [1, 0, 1], + ] + ) + assert np.array_equal(mask, expected_mask)