Skip to content

Commit

Permalink
more bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
alecjacobson committed Nov 23, 2024
1 parent 85f5d3f commit 0e5e621
Show file tree
Hide file tree
Showing 14 changed files with 456 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ option(LIBIGL_RESTRICTED_TRIANGLE "Build target igl_restricted::triangle" ON)
FetchContent_Declare(
libigl
GIT_REPOSITORY https://github.com/libigl/libigl.git
GIT_TAG f82ad2b463e0307c56f8101bcfe5c290c9cd30cd
GIT_TAG 753f4d3c88ddc9280696852d4740e58a815e365d
)
FetchContent_MakeAvailable(libigl)

Expand Down
34 changes: 34 additions & 0 deletions src/bounding_box.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "default_types.h"
#include <igl/bounding_box.h>
#include <nanobind/nanobind.h>
#include <nanobind/ndarray.h>
#include <nanobind/eigen/dense.h>
#include <nanobind/stl/tuple.h>

namespace nb = nanobind;
using namespace nb::literals;
namespace pyigl
{
auto bounding_box(
const nb::DRef<const Eigen::MatrixXN>& V,
const Numeric pad)
{
Eigen::MatrixXN BV;
Eigen::MatrixXI BF;
igl::bounding_box(V, pad, BV, BF);
return std::make_tuple(BV, BF);
}
}

void bind_bounding_box(nb::module_ &m)
{
m.def("bounding_box", &pyigl::bounding_box,
"V"_a,
"pad"_a=0,
R"(Build a triangle mesh of the bounding box of a given list of vertices
@param[in] V #V by dim list of rest domain positions
@param[in] pad padding offset
@param[out] BV 2^dim by dim list of bounding box corners positions
@param[out] BF #BF by dim list of simplex facets )");
}
35 changes: 35 additions & 0 deletions src/circumradius.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "default_types.h"
#include <igl/circumradius.h>
#include <nanobind/nanobind.h>
#include <nanobind/ndarray.h>
#include <nanobind/eigen/dense.h>
#include <nanobind/stl/tuple.h>

namespace nb = nanobind;
using namespace nb::literals;
namespace pyigl
{
auto circumradius(
const nb::DRef<const Eigen::MatrixXN> & V ,
const nb::DRef<const Eigen::MatrixXI> & T)
{
Eigen::VectorXN R;
Eigen::MatrixXN C,B;
igl::circumradius(V, T, R, C, B);
return std::make_tuple(R, C, B);
}
}

void bind_circumradius(nb::module_ &m)
{
m.def("circumradius", &pyigl::circumradius,
""_a,
"F"_a,
R"(Compute the circumradius of each triangle in a mesh (V,F)
@param[in] V #V by dim list of mesh vertex positions
@param[in] F #F by 3 list of triangle indices into V
@param[out] R #F list of circumradius
@param[out] R #T list of circumradius
@param[out] C #T by dim list of circumcenter
@param[out] B #T by simplex-size list of barycentric coordinates of circumcenter)");
}
41 changes: 41 additions & 0 deletions src/crouzeix_raviart_cotmatrix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include "default_types.h"
#include <igl/crouzeix_raviart_cotmatrix.h>
#include <nanobind/nanobind.h>
#include <nanobind/ndarray.h>
#include <nanobind/eigen/dense.h>
#include <nanobind/eigen/sparse.h>
#include <nanobind/stl/tuple.h>

namespace nb = nanobind;
using namespace nb::literals;
namespace pyigl
{
auto crouzeix_raviart_cotmatrix(
const nb::DRef<const Eigen::MatrixXN> & V,
const nb::DRef<const Eigen::MatrixXI> & F,
const nb::DRef<const Eigen::MatrixXI> & E,
const nb::DRef<const Eigen::VectorXI> & EMAP)
{
Eigen::SparseMatrix<Numeric> L;
igl::crouzeix_raviart_cotmatrix(V, F, E, EMAP, L);
return L;
}
}

void bind_crouzeix_raviart_cotmatrix(nb::module_ &m)
{
m.def("crouzeix_raviart_cotmatrix", &pyigl::crouzeix_raviart_cotmatrix,
"V"_a,
"F"_a,
"E"_a,
"EMAP"_a,
R"(Compute the Crouzeix-Raviart cotangent stiffness matrix.
See for example "Discrete Quadratic Curvature Energies" [Wardetzky, Bergou,
Harmon, Zorin, Grinspun 2007]
@param[in] V #V by dim list of vertex positions
@param[in] F #F by 3/4 list of triangle/tetrahedron indices
@param[in] E #E by 2/3 list of edges/faces
@param[in] EMAP #F*3/4 list of indices mapping allE to E
@param[out] L #E by #E edge/face-based diagonal cotangent matrix
\see crouzeix_raviart_massmatrix)");
}
43 changes: 43 additions & 0 deletions src/crouzeix_raviart_massmatrix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include "default_types.h"
#include <igl/crouzeix_raviart_massmatrix.h>
#include <nanobind/nanobind.h>
#include <nanobind/ndarray.h>
#include <nanobind/eigen/dense.h>
#include <nanobind/eigen/sparse.h>
#include <nanobind/stl/tuple.h>

namespace nb = nanobind;
using namespace nb::literals;
namespace pyigl
{
auto crouzeix_raviart_massmatrix(
const nb::DRef<const Eigen::MatrixXN> & V,
const nb::DRef<const Eigen::MatrixXI> & F,
const nb::DRef<const Eigen::MatrixXI> & E,
const nb::DRef<const Eigen::VectorXI> & EMAP)
{
Eigen::SparseMatrix<Numeric> L;
igl::crouzeix_raviart_massmatrix(V, F, E, EMAP, L);
return L;
}
}

void bind_crouzeix_raviart_massmatrix(nb::module_ &m)
{
m.def("crouzeix_raviart_massmatrix", &pyigl::crouzeix_raviart_massmatrix,
"V"_a,
"F"_a,
"E"_a,
"EMAP"_a,
R"(CROUZEIX_RAVIART_MASSMATRIX Compute the Crouzeix-Raviart mass matrix where
M(e,e) is just the sum of the areas of the triangles on either side of an
edge e.
See for example "Discrete Quadratic Curvature Energies" [Wardetzky, Bergou,
Harmon, Zorin, Grinspun 2007]
@param[in] V #V by dim list of vertex positions
@param[in] F #F by 3/4 list of triangle/tetrahedron indices
@param[in] E #E by 2/3 list of edges/faces
@param[in] EMAP #F*3/4 list of indices mapping allE to E
@param[out] M #E by #E edge/face-based diagonal mass matrix
\see crouzeix_raviart_cotmatrix)");
}
37 changes: 37 additions & 0 deletions src/cut_mesh_from_singularities.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "default_types.h"
#include <igl/cut_mesh_from_singularities.h>
#include <nanobind/nanobind.h>
#include <nanobind/ndarray.h>
#include <nanobind/eigen/dense.h>
#include <nanobind/stl/tuple.h>

namespace nb = nanobind;
using namespace nb::literals;
namespace pyigl
{
auto cut_mesh_from_singularities(
const nb::DRef<const Eigen::MatrixXN> &V,
const nb::DRef<const Eigen::MatrixXI> &F,
const nb::DRef<const Eigen::MatrixXI> &MMatch)
{
Eigen::MatrixXB seams;
igl::cut_mesh_from_singularities(V, F, MMatch, seams);
return seams;
}
}

void bind_cut_mesh_from_singularities(nb::module_ &m)
{
m.def("cut_mesh_from_singularities", &pyigl::cut_mesh_from_singularities,
"V"_a,
"F"_a,
"MMatch"_a,
R"(Given a mesh (V,F) and the integer mismatch of a cross field per edge
(mismatch), finds the cut_graph connecting the singularities (seams) and the
degree of the singularities singularity_index
@param[in] V #V by 3 list of mesh vertex positions
@param[in] F #F by 3 list of faces
@param[in] mismatch #F by 3 list of per corner integer mismatch
@param[out] seams #F by 3 list of per corner booleans that denotes if an edge is a
seam or not)");
}
48 changes: 48 additions & 0 deletions src/cut_to_disk.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "default_types.h"
#include <igl/cut_to_disk.h>
#include <nanobind/nanobind.h>
#include <nanobind/ndarray.h>
#include <nanobind/eigen/dense.h>
#include <nanobind/stl/tuple.h>
#include <nanobind/stl/vector.h>

namespace nb = nanobind;
using namespace nb::literals;
namespace pyigl
{
auto cut_to_disk( const nb::DRef<const Eigen::MatrixXI> & F)
{
std::vector<std::vector<Integer>> cuts;
igl::cut_to_disk(F, cuts);
return cuts;
}
}

void bind_cut_to_disk(nb::module_ &m)
{
m.def("cut_to_disk", &pyigl::cut_to_disk,
"F"_a,
R"(Given a triangle mesh, computes a set of edge cuts sufficient to carve the
mesh into a topological disk, without disconnecting any connected components.
Nothing else about the cuts (including number, total length, or smoothness)
is guaranteed to be optimal.
Simply-connected components without boundary (topological spheres) are left
untouched (delete any edge if you really want a disk).
All other connected components are cut into disks. Meshes with boundary are
supported; boundary edges will be included as cuts.
The cut mesh itself can be materialized using cut_mesh().
Implements the triangle-deletion approach described by Gu et al's
"Geometry Images."
@tparam Index Integrable type large enough to represent the total number of faces
and edges in the surface represented by F, and all entries of F.
@param[in] F #F by 3 list of the faces (must be triangles)
@param[out] cuts List of cuts. Each cut is a sequence of vertex indices (where
pairs of consecutive vertices share a face), is simple, and is either
a closed loop (in which the first and last indices are identical) or
an open curve. Cuts are edge-disjoint.
)");
}
33 changes: 33 additions & 0 deletions src/cylinder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "default_types.h"
#include <igl/cylinder.h>
#include <nanobind/nanobind.h>
#include <nanobind/ndarray.h>
#include <nanobind/eigen/dense.h>
#include <nanobind/stl/tuple.h>

namespace nb = nanobind;
using namespace nb::literals;
namespace pyigl
{
auto cylinder(
int axis_devisions,
int height_devisions)
{
Eigen::MatrixXN V;
Eigen::MatrixXI F;
igl::cylinder(axis_devisions, height_devisions, V, F);
return std::make_tuple(V, F);
}
}

void bind_cylinder(nb::module_ &m)
{
m.def("cylinder", &pyigl::cylinder,
"axis_devisions"_a,
"height_devisions"_a,
R"(Construct a triangle mesh of a cylinder (without caps)
@param[in] axis_devisions number of vertices _around the cylinder_
@param[in] height_devisions number of vertices _up the cylinder_
@param[out] V #V by 3 list of mesh vertex positions
@param[out] F #F by 3 list of triangle indices into V)");
}
33 changes: 33 additions & 0 deletions src/dihedral_angles.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "default_types.h"
#include <igl/dihedral_angles.h>
#include <nanobind/nanobind.h>
#include <nanobind/ndarray.h>
#include <nanobind/eigen/dense.h>
#include <nanobind/stl/tuple.h>

namespace nb = nanobind;
using namespace nb::literals;
namespace pyigl
{
auto dihedral_angles(
const nb::DRef<const Eigen::MatrixXN>& V,
const nb::DRef<const Eigen::MatrixXI>& T)
{
Eigen::MatrixXN theta, cos_theta;
igl::dihedral_angles(V, T, theta, cos_theta);
return std::make_tuple(theta, cos_theta);

}
}

void bind_dihedral_angles(nb::module_ &m)
{
m.def("dihedral_angles", &pyigl::dihedral_angles,
"V"_a,
"T"_a,
R"(Compute dihedral angles for all tets of a given tet mesh (V,T).
@param[in] V #V by dim list of vertex positions
@param[in] T #V by 4 list of tet indices
@param[out] theta #T by 6 list of dihedral angles (in radians)
@param[out] cos_theta #T by 6 list of cosine of dihedral angles (in radians))");
}
34 changes: 34 additions & 0 deletions src/dihedral_angles_intrinsic.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "default_types.h"
#include <igl/dihedral_angles_intrinsic.h>
#include <nanobind/nanobind.h>
#include <nanobind/ndarray.h>
#include <nanobind/eigen/dense.h>
#include <nanobind/stl/tuple.h>

namespace nb = nanobind;
using namespace nb::literals;
namespace pyigl
{
auto dihedral_angles_intrinsic(
const nb::DRef<const Eigen::MatrixXN>& A,
const nb::DRef<const Eigen::MatrixXN>& L)
{
Eigen::MatrixXN theta, cos_theta;
igl::dihedral_angles_intrinsic(A, L, theta, cos_theta);
return std::make_tuple(theta, cos_theta);

}
}

void bind_dihedral_angles_intrinsic(nb::module_ &m)
{
m.def("dihedral_angles_intrinsic", &pyigl::dihedral_angles_intrinsic,
"A"_a,
"L"_a,
R"(Compute dihedral angles for all tets of a given tet mesh's intrinsics.
@param[in] V #V by dim list of vertex positions
@param[in] T #V by 4 list of tet indices
@param[out] theta #T by 6 list of dihedral angles (in radians)
@param[out] cos_theta #T by 6 list of cosine of dihedral angles (in radians))");
}

32 changes: 32 additions & 0 deletions src/face_areas.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include "default_types.h"
#include <igl/face_areas.h>
#include <nanobind/nanobind.h>
#include <nanobind/ndarray.h>
#include <nanobind/eigen/dense.h>
#include <nanobind/stl/tuple.h>

namespace nb = nanobind;
using namespace nb::literals;
namespace pyigl
{
auto face_areas(
const nb::DRef<const Eigen::MatrixXN>& V,
const nb::DRef<const Eigen::MatrixXI>& T)
{
Eigen::MatrixXN A;
igl::face_areas(V, T, A);
return A;
}
}

void bind_face_areas(nb::module_ &m)
{
m.def("face_areas", &pyigl::face_areas,
"V"_a,
"T"_a,
R"(Constructs a list of face areas of faces opposite each index in a tet list
@param[in] V #V by 3 list of mesh vertex positions
@param[in] T #T by 3 list of tet mesh indices into V
@param[out] A #T by 4 list of face areas corresponding to faces opposite vertices
0,1,2,3)");
}
Loading

0 comments on commit 0e5e621

Please sign in to comment.