Skip to content

Commit

Permalink
rm prints
Browse files Browse the repository at this point in the history
  • Loading branch information
alecjacobson committed Nov 12, 2024
1 parent 6d4854a commit 4c13728
Show file tree
Hide file tree
Showing 14 changed files with 581 additions and 9 deletions.
23 changes: 16 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ FetchContent_Declare(
FetchContent_MakeAvailable(nanobind)

# Download and set up libigl
option(LIBIGL_RESTRICTED_TRIANGLE "Build target igl_restricted::triangle" ON)
option(LIBIGL_COPYLEFT_CGAL "Build target igl_copyleft::cgal" ON)
option(LIBIGL_COPYLEFT_TETGEN "Build target igl_copyleft::tetgen" ON)
option(LIBIGL_COPYLEFT_CORE "Build target igl_copyleft::core" ON)
option(LIBIGL_RESTRICTED_TRIANGLE "Build target igl_restricted::triangle" ON)
option(LIBIGL_COPYLEFT_CGAL "Build target igl_copyleft::cgal" ON)
option(LIBIGL_COPYLEFT_TETGEN "Build target igl_copyleft::tetgen" ON)
FetchContent_Declare(
libigl
GIT_REPOSITORY https://github.com/libigl/libigl.git
GIT_TAG 0971aecc2349feed0dc010ed85dcece607cb0b14
GIT_TAG e60c377f953ae70e66ceefed42cec73aec044f92
)
FetchContent_MakeAvailable(libigl)

Expand Down Expand Up @@ -76,13 +77,18 @@ function(pyigl_include prefix name)
# if(LIBIGL${prefix_uc}_${name_uc}) or name == "core"
if(LIBIGL${prefix_uc}_${name_uc} OR name STREQUAL "core")
if("${prefix}" STREQUAL "copyleft")
set(subpath "copyleft/${name}")
if("${name}" STREQUAL "core")
set(subpath "copyleft")
else()
set(subpath "copyleft/${name}")
endif()
elseif("${name}" STREQUAL "core")
set(subpath "")
else() # "" or "restricted"
set(subpath "${name}")
endif()
file(GLOB sources "${CMAKE_CURRENT_SOURCE_DIR}/src/${subpath}/*.cpp")

set(BINDING_SOURCES ${sources})
list(FILTER BINDING_SOURCES EXCLUDE REGEX ".*/module\\.cpp$")
# Generate the function calls based on filenames
Expand All @@ -99,7 +105,6 @@ function(pyigl_include prefix name)
file(WRITE "${generated_dir}/BINDING_DECLARATIONS.in" "${BINDING_DECLARATIONS}")
file(WRITE "${generated_dir}/BINDING_INVOCATIONS.in" "${BINDING_INVOCATIONS}")


set(target_name "pyigl${prefix_lc}_${name}")
nanobind_add_module(${target_name} ${sources})

Expand All @@ -113,7 +118,7 @@ function(pyigl_include prefix name)
set(output_dir "${PYIGL_OUTPUT_DIRECTORY}/${subpath}")
file(MAKE_DIRECTORY ${output_dir})
file(WRITE "${output_dir}/__init__.py" "from .${target_name} import *\n")
if("${name}" STREQUAL "core")
if("${name}" STREQUAL "core" AND "${prefix}" STREQUAL "")
file(APPEND "${output_dir}/__init__.py" "from ._version import __version__\n")
endif()
set_target_properties(${target_name} PROPERTIES
Expand All @@ -132,6 +137,9 @@ function(pyigl_include prefix name)
endfunction()

pyigl_include("" "core")
if(LIBIGL_COPYLEFT_CORE)
pyigl_include("copyleft" "core")
endif()
if(LIBIGL_RESTRICTED_TRIANGLE)
pyigl_include("restricted" "triangle")
endif()
Expand All @@ -142,3 +150,4 @@ if(LIBIGL_COPYLEFT_TETGEN)
pyigl_include("copyleft" "tetgen")
endif()


5 changes: 5 additions & 0 deletions include/default_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
///////////////////////////////////////////////////////////////////////////////////
using Numeric = double;
using Integer = int64_t;
using Boolean = bool;
// When using `const nb::DRef<const Eigen::MatrixX*>` this `Options` does not
// affect the input types (either order should result in no copy if `dtype`s
// match). It does affect return types, `Eigen::MatrixXN X; … ; return X;`
Expand All @@ -18,10 +19,14 @@ namespace Eigen
{
typedef Matrix<Numeric, Dynamic, Dynamic, Options> MatrixXN;
typedef Matrix<Integer, Dynamic, Dynamic, Options> MatrixXI;
typedef Matrix<Boolean, Dynamic, Dynamic, Options> MatrixXB;
typedef Matrix<Numeric, Dynamic, 1, Eigen::ColMajor> VectorXN;
typedef Matrix<Integer, Dynamic, 1, Eigen::ColMajor> VectorXI;
typedef Matrix<Boolean, Dynamic, 1, Eigen::ColMajor> VectorXB;
typedef Matrix<Numeric, 1, Dynamic, Eigen::RowMajor> RowVectorXN;
typedef Matrix<Integer, 1, Dynamic, Eigen::RowMajor> RowVectorXI;
typedef Matrix<Boolean, 1, Dynamic, Eigen::RowMajor> RowVectorXB;
typedef SparseMatrix<Numeric> SparseMatrixN;
typedef SparseMatrix<Integer> SparseMatrixI;
typedef SparseMatrix<Boolean> SparseMatrixB;
}
1 change: 0 additions & 1 deletion src/arap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ namespace pyigl
igl::ARAPData &data,
const nb::DRef<const Eigen::MatrixXN> & U0)
{
printf("pyigl::arap_solve\n");
// igl::arap_solve expects U to be both the initial guess and the output
// not sure how to avoid this copy
Eigen::MatrixXN U = U0;
Expand Down
32 changes: 32 additions & 0 deletions src/copyleft/cgal/convex_hull.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include "default_types.h"
#include <igl/copyleft/cgal/convex_hull.h>
#include <nanobind/nanobind.h>
#include <nanobind/eigen/dense.h>
#include <tuple>

namespace nb = nanobind;
using namespace nb::literals;

namespace pyigl
{
// Second overload: convex_hull with only output F
auto convex_hull(const nb::DRef<const Eigen::MatrixXN> &V)
{
Eigen::MatrixXI F;
igl::copyleft::cgal::convex_hull(V, F);
return F;
}
}

// Bind the wrapper to the Python module
void bind_convex_hull(nb::module_ &m)
{
m.def(
"convex_hull",
&pyigl::convex_hull,
"V"_a,
R"(Compute the convex hull of a set of points, returning only the triangular faces of the hull.
@param[in] V #V by 3 matrix of input points
@return F: #F by 3 matrix of triangle indices into V)");
}
46 changes: 46 additions & 0 deletions src/copyleft/cgal/fast_winding_number.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "default_types.h"
#include <igl/copyleft/cgal/fast_winding_number.h>
#include <nanobind/nanobind.h>
#include <nanobind/eigen/dense.h>
#include <nanobind/stl/tuple.h>

namespace nb = nanobind;
using namespace nb::literals;

namespace pyigl
{
// Overload with `expansion_order` and `beta`
auto fast_winding_number(
const nb::DRef<const Eigen::MatrixXN> &P,
const nb::DRef<const Eigen::MatrixXN> &N,
const nb::DRef<const Eigen::MatrixXN> &Q,
int expansion_order,
double beta)
{
Eigen::VectorXd WN;
igl::copyleft::cgal::fast_winding_number(P, N, Q, expansion_order, beta, WN);
return WN;
}
}

// Bind the wrapper to the Python module
void bind_fast_winding_number(nb::module_ &m)
{
m.def(
"fast_winding_number",
&pyigl::fast_winding_number,
"P"_a,
"N"_a,
"Q"_a,
"expansion_order"_a = 2,
"beta"_a = 2.0,
R"(Evaluate the fast winding number for point data with adjustable accuracy.
@param[in] P #P by 3 list of point locations
@param[in] N #P by 3 list of point normals
@param[in] Q #Q by 3 list of query points for the winding number
@param[in] expansion_order Order of the Taylor expansion (0, 1, or 2)
@param[in] beta Barnes-Hut style accuracy parameter (recommended: 2)
@return Vector of winding number values for each query point)");

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

namespace nb = nanobind;
using namespace nb::literals;

namespace pyigl
{
// First overload: intersect_other with detailed outputs
auto intersect_other(
const nb::DRef<const Eigen::MatrixXN> &VA,
const nb::DRef<const Eigen::MatrixXI> &FA,
const nb::DRef<const Eigen::MatrixXN> &VB,
const nb::DRef<const Eigen::MatrixXI> &FB,
const bool detect_only,
const bool first_only,
const bool stitch_all,
const bool slow_and_more_precise_rounding,
const int cutoff)
{
Eigen::MatrixXI IF;
Eigen::MatrixXN VVAB;
Eigen::MatrixXI FFAB;
Eigen::VectorXI JAB;
Eigen::VectorXI IMAB;

igl::copyleft::cgal::RemeshSelfIntersectionsParam params(
detect_only, first_only, stitch_all, slow_and_more_precise_rounding, cutoff);
const bool success = igl::copyleft::cgal::intersect_other(
VA, FA, VB, FB, params, IF, VVAB, FFAB, JAB, IMAB);

return std::make_tuple(IF, VVAB, FFAB, JAB, IMAB);
}

}

// Bind the wrapper to the Python module
void bind_intersect_other(nb::module_ &m)
{
// First overload
m.def(
"intersect_other",
&pyigl::intersect_other,
"VA"_a,
"FA"_a,
"VB"_a,
"FB"_a,
"detect_only"_a=false,
"first_only"_a=false,
"stitch_all"_a=false,
"slow_and_more_precise_rounding"_a=false,
"cutoff"_a=1000,
R"(Detect intersecting faces between two triangle meshes, providing detailed output.
@param[in] VA #V by 3 list of vertices for first mesh
@param[in] FA #F by 3 list of faces for first mesh
@param[in] VB #V by 3 list of vertices for second mesh
@param[in] FB #F by 3 list of faces for second mesh
@param[in] detect_only only detect intersections, do not resolve
@param[in] first_only only return first intersection
@param[in] stitch_all stitch all intersections
@param[in] slow_and_more_precise_rounding use slow and more precise rounding
@param[in] cutoff maximum number of intersections to resolve
@return Tuple containing:
- success: bool indicating if the operation succeeded
- IF: # intersecting face pairs
- VVAB: list of intersection vertex positions
- FFAB: list of triangle indices into VVAB
- JAB: list of indices into [FA;FB] denoting the birth triangle
- IMAB: indices stitching duplicates from intersections)");

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

namespace nb = nanobind;
using namespace nb::literals;

namespace pyigl
{
// Overload with point and normal
auto intersect_with_half_space_point_normal(
const nb::DRef<const Eigen::MatrixXN> &V,
const nb::DRef<const Eigen::MatrixXI> &F,
const nb::DRef<const Eigen::VectorXN> &p,
const nb::DRef<const Eigen::VectorXN> &n)
{
Eigen::MatrixXN VC;
Eigen::MatrixXI FC;
Eigen::VectorXI J;

if(!igl::copyleft::cgal::intersect_with_half_space(V, F, p, n, VC, FC, J))
{
throw std::runtime_error("Failed to intersect with half space");
}
return std::make_tuple(VC, FC, J);
}

// Overload with plane equation
auto intersect_with_half_space_equation(
const nb::DRef<const Eigen::MatrixXN> &V,
const nb::DRef<const Eigen::MatrixXI> &F,
const nb::DRef<const Eigen::VectorXN> &equ)
{
Eigen::MatrixXN VC;
Eigen::MatrixXI FC;
Eigen::VectorXI J;

if(!igl::copyleft::cgal::intersect_with_half_space(V, F, equ, VC, FC, J))
{
throw std::runtime_error("Failed to intersect with half space");
}
return std::make_tuple( VC, FC, J);
}

}

// Bind the wrapper to the Python module
void bind_intersect_with_half_space(nb::module_ &m)
{
m.def(
"intersect_with_half_space",
&pyigl::intersect_with_half_space_point_normal,
"V"_a,
"F"_a,
"p"_a,
"n"_a,
R"(Intersect a PWN mesh with a half-space using a point and normal.
@param[in] V #V by 3 list of mesh vertex positions
@param[in] F #F by 3 list of triangle indices
@param[in] p 3D point on plane
@param[in] n 3D normal vector
@return Tuple containing:
- success: bool, true if successful
- VC: vertices of resulting mesh
- FC: face indices of resulting mesh
- J: birth facet indices)");

m.def(
"intersect_with_half_space",
&pyigl::intersect_with_half_space_equation,
"V"_a,
"F"_a,
"equ"_a,
R"(Intersect a PWN mesh with a half-space using the plane equation.
@param[in] V #V by 3 list of mesh vertex positions
@param[in] F #F by 3 list of triangle indices
@param[in] equ Plane equation coefficients (a, b, c, d)
@return Tuple containing:
- success: bool, true if successful
- VC: vertices of resulting mesh
- FC: face indices of resulting mesh
- J: birth facet indices)");
}
Loading

0 comments on commit 4c13728

Please sign in to comment.