// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2014 Alec Jacobson // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "signed_distance.h" #include "get_seconds.h" #include "per_edge_normals.h" #include "parallel_for.h" #include "per_face_normals.h" #include "per_vertex_normals.h" #include "point_mesh_squared_distance.h" #include "pseudonormal_test.h" #include "fast_winding_number.h" namespace { template < typename DerivedP, typename DerivedV, typename DerivedF, typename DerivedS, typename DerivedI, typename DerivedC, typename DerivedN> void signed_distance_3( const Eigen::MatrixBase & P, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const igl::SignedDistanceType sign_type, const typename DerivedV::Scalar lower_bound, const typename DerivedV::Scalar upper_bound, Eigen::PlainObjectBase & S, Eigen::PlainObjectBase & I, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & N) { using namespace igl; AABB tree; tree.init(V,F); Eigen::Matrix FN,VN,EN; Eigen::Matrix E; Eigen::Matrix EMAP; typedef Eigen::Matrix RowVectorS; WindingNumberAABB hier3; igl::FastWindingNumberBVH fwn_bvh; Eigen::VectorXf W; switch(sign_type) { default: assert(false && "Unknown SignedDistanceType"); case SIGNED_DISTANCE_TYPE_UNSIGNED: // do nothing break; case SIGNED_DISTANCE_TYPE_DEFAULT: case SIGNED_DISTANCE_TYPE_WINDING_NUMBER: hier3.set_mesh(V,F); hier3.grow(); break; case SIGNED_DISTANCE_TYPE_FAST_WINDING_NUMBER: igl::fast_winding_number(V.template cast().eval(), F, 2, fwn_bvh); case SIGNED_DISTANCE_TYPE_PSEUDONORMAL: // "Signed Distance Computation Using the Angle Weighted Pseudonormal" // [Bærentzen & Aanæs 2005] igl::per_face_normals(V,F,FN); igl::per_vertex_normals(V,F,PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE,FN,VN); igl::per_edge_normals( V,F,PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM,FN,EN,E,EMAP); N.resize(P.rows(),3); break; } // convert to bounds on (unsiged) squared distances typedef typename DerivedV::Scalar Scalar; const Scalar max_abs = std::max(std::abs(lower_bound),std::abs(upper_bound)); const Scalar up_sqr_d = std::pow(max_abs,2.0); const Scalar low_sqr_d = std::pow(std::max(max_abs-(upper_bound-lower_bound),(Scalar)0.0),2.0); S.resize(P.rows(),1); I.resize(P.rows(),1); C.resize(P.rows(),3); igl::parallel_for(P.rows(),[&](const int p) //for(int p = 0;p= up_sqr_d || sqrd < low_sqr_d) { // Out of bounds gets a nan (nans on grids can be flood filled later using // igl::flood_fill) S(p) = std::numeric_limits::quiet_NaN(); I(p) = F.rows()+1; C.row(p).setConstant(0); }else { // Determine sign switch(sign_type) { default: assert(false && "Unknown SignedDistanceType"); case SIGNED_DISTANCE_TYPE_UNSIGNED: break; case SIGNED_DISTANCE_TYPE_DEFAULT: case SIGNED_DISTANCE_TYPE_WINDING_NUMBER: s = 1.-2.*hier3.winding_number(q.transpose()); break; case SIGNED_DISTANCE_TYPE_FAST_WINDING_NUMBER: { Scalar w = fast_winding_number(fwn_bvh, 2, q.template cast().eval()); s = 1.-2.*std::abs(w); break; } case SIGNED_DISTANCE_TYPE_PSEUDONORMAL: { RowVectorS n; pseudonormal_test(V,F,FN,VN,EN,EMAP,q,i,c,s,n); N.row(p) = n.template cast(); break; } } I(p) = i; S(p) = s*sqrt(sqrd); C.row(p) = c.template cast(); } } ,10000); } template < typename DerivedP, typename DerivedV, typename DerivedF, typename DerivedS, typename DerivedI, typename DerivedC, typename DerivedN> void signed_distance_2( const Eigen::MatrixBase & P, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const igl::SignedDistanceType sign_type, const typename DerivedV::Scalar lower_bound, const typename DerivedV::Scalar upper_bound, Eigen::PlainObjectBase & S, Eigen::PlainObjectBase & I, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & N) { using namespace igl; AABB tree; tree.init(V,F); Eigen::Matrix FN,VN,EN; Eigen::Matrix E; Eigen::Matrix EMAP; switch(sign_type) { default: assert(false && "Unknown or unsupported SignedDistanceType for 2D"); case SIGNED_DISTANCE_TYPE_DEFAULT: case SIGNED_DISTANCE_TYPE_WINDING_NUMBER: case SIGNED_DISTANCE_TYPE_UNSIGNED: // no precomp for 2D break; case SIGNED_DISTANCE_TYPE_PSEUDONORMAL: // "Signed Distance Computation Using the Angle Weighted Pseudonormal" // [Bærentzen & Aanæs 2005] FN.resize(F.rows(),2); VN = DerivedV::Zero(V.rows(),2); for(int e = 0;e RowVectorS; igl::parallel_for(P.rows(),[&](const int p) //for(int p = 0;p= up_sqr_d || sqrd < low_sqr_d) { // Out of bounds gets a nan (nans on grids can be flood filled later using // igl::flood_fill) S(p) = std::numeric_limits::quiet_NaN(); I(p) = F.rows()+1; C.row(p).setConstant(0); }else { // Determine sign switch(sign_type) { default: assert(false && "Unknown SignedDistanceType"); case SIGNED_DISTANCE_TYPE_UNSIGNED: break; case SIGNED_DISTANCE_TYPE_DEFAULT: case SIGNED_DISTANCE_TYPE_WINDING_NUMBER: assert(!V.derived().IsRowMajor); assert(!F.derived().IsRowMajor); s = 1.-2.*winding_number(V,F,q); break; case SIGNED_DISTANCE_TYPE_PSEUDONORMAL: { RowVectorS n; pseudonormal_test(V,F,FN,VN,q,i,c,s,n); N.row(p) = n.template cast(); break; } } I(p) = i; S(p) = s*sqrt(sqrd); C.row(p) = c.template cast(); } } ,10000); } // Class whose templates can be specialized on whether all inputs have dynamic // columns or not. template < typename DerivedP, typename DerivedV, typename DerivedF, typename DerivedS, typename DerivedI, typename DerivedC, typename DerivedN, int ColsAtCompileTime> struct signed_distance_DIM_Handler; // All inputs have dynamic number of columns template < typename DerivedP, typename DerivedV, typename DerivedF, typename DerivedS, typename DerivedI, typename DerivedC, typename DerivedN> struct signed_distance_DIM_Handler< DerivedP, DerivedV, DerivedF, DerivedS, DerivedI, DerivedC, DerivedN, Eigen::Dynamic> { static void compute( const Eigen::MatrixBase & P, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const igl::SignedDistanceType sign_type, const typename DerivedV::Scalar lower_bound, const typename DerivedV::Scalar upper_bound, Eigen::PlainObjectBase & S, Eigen::PlainObjectBase & I, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & N) { // Just need to check P as V and F are checked in signed_distance if(P.cols() == 3) { signed_distance_3(P,V,F,sign_type,lower_bound,upper_bound,S,I,C,N); }else if(P.cols() == 2) { signed_distance_2(P,V,F,sign_type,lower_bound,upper_bound,S,I,C,N); }else { assert(false && "P should have 3d or 2d positions"); } } }; // Some input is 3D template < typename DerivedP, typename DerivedV, typename DerivedF, typename DerivedS, typename DerivedI, typename DerivedC, typename DerivedN> struct signed_distance_DIM_Handler< DerivedP, DerivedV, DerivedF, DerivedS, DerivedI, DerivedC, DerivedN, 3> { static void compute( const Eigen::MatrixBase & P, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const igl::SignedDistanceType sign_type, const typename DerivedV::Scalar lower_bound, const typename DerivedV::Scalar upper_bound, Eigen::PlainObjectBase & S, Eigen::PlainObjectBase & I, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & N) { signed_distance_3(P,V,F,sign_type,lower_bound,upper_bound,S,I,C,N); } }; // Some input is 2D template < typename DerivedP, typename DerivedV, typename DerivedF, typename DerivedS, typename DerivedI, typename DerivedC, typename DerivedN> struct signed_distance_DIM_Handler< DerivedP, DerivedV, DerivedF, DerivedS, DerivedI, DerivedC, DerivedN, 2> { static void compute( const Eigen::MatrixBase & P, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const igl::SignedDistanceType sign_type, const typename DerivedV::Scalar lower_bound, const typename DerivedV::Scalar upper_bound, Eigen::PlainObjectBase & S, Eigen::PlainObjectBase & I, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & N) { signed_distance_2(P,V,F,sign_type,lower_bound,upper_bound,S,I,C,N); } }; } template < typename DerivedP, typename DerivedV, typename DerivedF, typename DerivedS, typename DerivedI, typename DerivedC, typename DerivedN> IGL_INLINE void igl::signed_distance( const Eigen::MatrixBase & P, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const SignedDistanceType sign_type, const typename DerivedV::Scalar lower_bound, const typename DerivedV::Scalar upper_bound, Eigen::PlainObjectBase & S, Eigen::PlainObjectBase & I, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & N) { constexpr int DIM = DerivedP::ColsAtCompileTime != Eigen::Dynamic ? DerivedP::ColsAtCompileTime : DerivedV::ColsAtCompileTime != Eigen::Dynamic ? DerivedV::ColsAtCompileTime : DerivedF::ColsAtCompileTime != Eigen::Dynamic ? DerivedF::ColsAtCompileTime : DerivedN::ColsAtCompileTime != Eigen::Dynamic ? DerivedN::ColsAtCompileTime : DerivedC::ColsAtCompileTime != Eigen::Dynamic ? DerivedC::ColsAtCompileTime : Eigen::Dynamic; static_assert(DIM == 3 || DIM == 2 || DIM == Eigen::Dynamic,"DIM should be 2 or 3 or Dynamic"); assert(V.cols() == P.cols() && "V should have same dimension as P"); assert(V.cols() == F.cols() || sign_type == SIGNED_DISTANCE_TYPE_UNSIGNED && "V and F should have same number of columns"); if (sign_type == SIGNED_DISTANCE_TYPE_FAST_WINDING_NUMBER){ assert(V.cols() == 3 && "V should be 3D for fast winding number"); } if(F.rows() == 0) { S.setConstant(P.rows(),1,std::numeric_limits::quiet_NaN()); I.setConstant(P.rows(),1,-1); C.setConstant(P.rows(),P.cols(),std::numeric_limits::quiet_NaN()); N.setConstant(P.rows(),P.cols(),std::numeric_limits::quiet_NaN()); return; } signed_distance_DIM_Handler< DerivedP, DerivedV, DerivedF, DerivedS, DerivedI, DerivedC, DerivedN, DIM>::compute(P,V,F,sign_type,lower_bound,upper_bound,S,I,C,N); } template < typename DerivedP, typename DerivedV, typename DerivedF, typename DerivedS, typename DerivedI, typename DerivedC, typename DerivedN> IGL_INLINE void igl::signed_distance( const Eigen::MatrixBase & P, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const SignedDistanceType sign_type, Eigen::PlainObjectBase & S, Eigen::PlainObjectBase & I, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & N) { typedef typename DerivedV::Scalar Scalar; Scalar lower = std::numeric_limits::min(); Scalar upper = std::numeric_limits::max(); return signed_distance(P,V,F,sign_type,lower,upper,S,I,C,N); } template < typename DerivedV, typename DerivedF, typename DerivedFN, typename DerivedVN, typename DerivedEN, typename DerivedEMAP, typename Derivedq> IGL_INLINE typename DerivedV::Scalar igl::signed_distance_pseudonormal( const AABB & tree, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const Eigen::MatrixBase & FN, const Eigen::MatrixBase & VN, const Eigen::MatrixBase & EN, const Eigen::MatrixBase & EMAP, const Eigen::MatrixBase & q) { typename DerivedV::Scalar s,sqrd; Eigen::Matrix n,c; int i = -1; signed_distance_pseudonormal(tree,V,F,FN,VN,EN,EMAP,q,s,sqrd,i,c,n); return s*sqrt(sqrd); } template < typename DerivedP, typename DerivedV, typename DerivedF, typename DerivedFN, typename DerivedVN, typename DerivedEN, typename DerivedEMAP, typename DerivedS, typename DerivedI, typename DerivedC, typename DerivedN> IGL_INLINE void igl::signed_distance_pseudonormal( const Eigen::MatrixBase & P, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const AABB & tree, const Eigen::MatrixBase & FN, const Eigen::MatrixBase & VN, const Eigen::MatrixBase & EN, const Eigen::MatrixBase & EMAP, Eigen::PlainObjectBase & S, Eigen::PlainObjectBase & I, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & N) { using namespace Eigen; const size_t np = P.rows(); S.resize(np,1); I.resize(np,1); N.resize(np,3); C.resize(np,3); typedef typename AABB::RowVectorDIMS RowVector3S; parallel_for(np,[&](const int p) { typename DerivedV::Scalar s,sqrd; RowVector3S n,c; int i = -1; RowVector3S q = P.row(p); signed_distance_pseudonormal(tree,V,F,FN,VN,EN,EMAP,q,s,sqrd,i,c,n); S(p) = s*sqrt(sqrd); I(p) = i; N.row(p) = n; C.row(p) = c; },1000); } template < typename DerivedV, typename DerivedF, typename DerivedFN, typename DerivedVN, typename DerivedEN, typename DerivedEMAP, typename Derivedq, typename Scalar, typename Derivedc, typename Derivedn> IGL_INLINE void igl::signed_distance_pseudonormal( const AABB & tree, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const Eigen::MatrixBase & FN, const Eigen::MatrixBase & VN, const Eigen::MatrixBase & EN, const Eigen::MatrixBase & EMAP, const Eigen::MatrixBase & q, Scalar & s, Scalar & sqrd, int & i, Eigen::PlainObjectBase & c, Eigen::PlainObjectBase & n) { static_assert( DerivedV::ColsAtCompileTime == 3 || DerivedV::ColsAtCompileTime == Eigen::Dynamic, "V should have 3 or Dynamic columns"); using namespace Eigen; using namespace std; //typedef Eigen::Matrix RowVector3S; // Alec: Why was this constructor around q necessary? //sqrd = tree.squared_distance(V,F,RowVector3S(q),i,(RowVector3S&)c); // Alec: Why was this constructor around c necessary? //sqrd = tree.squared_distance(V,F,q,i,(RowVector3S&)c); sqrd = tree.squared_distance(V,F,q,i,c); pseudonormal_test(V,F,FN,VN,EN,EMAP,q,i,c,s,n); } template < typename DerivedV, typename DerivedE, typename DerivedEN, typename DerivedVN, typename Derivedq, typename Scalar, typename Derivedc, typename Derivedn> IGL_INLINE void igl::signed_distance_pseudonormal( const AABB & tree, const Eigen::MatrixBase & V, const Eigen::MatrixBase & E, const Eigen::MatrixBase & EN, const Eigen::MatrixBase & VN, const Eigen::MatrixBase & q, Scalar & s, Scalar & sqrd, int & i, Eigen::PlainObjectBase & c, Eigen::PlainObjectBase & n) { static_assert( DerivedV::ColsAtCompileTime == 2 || DerivedV::ColsAtCompileTime == Eigen::Dynamic, "V should have 2 or Dynamic columns"); using namespace Eigen; using namespace std; typedef Eigen::Matrix RowVector2S; sqrd = tree.squared_distance(V,E,RowVector2S(q),i,(RowVector2S&)c); pseudonormal_test(V,E,EN,VN,q,i,c,s,n); } template < typename DerivedV, typename DerivedF, typename Derivedq> IGL_INLINE typename DerivedV::Scalar igl::signed_distance_winding_number( const AABB & tree, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const igl::WindingNumberAABB & hier, const Eigen::MatrixBase & q) { static_assert( DerivedV::ColsAtCompileTime == 3 || DerivedV::ColsAtCompileTime == Eigen::Dynamic, "V should have 3 or Dynamic columns"); typedef typename DerivedV::Scalar Scalar; Scalar s,sqrd; Eigen::Matrix c; int i=-1; signed_distance_winding_number(tree,V,F,hier,q,s,sqrd,i,c); return s*sqrt(sqrd); } template < typename DerivedV, typename DerivedF, typename Derivedq, typename Scalar, typename Derivedc> IGL_INLINE void igl::signed_distance_winding_number( const AABB & tree, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const igl::WindingNumberAABB & hier, const Eigen::MatrixBase & q, Scalar & s, Scalar & sqrd, int & i, Eigen::PlainObjectBase & c) { static_assert( DerivedV::ColsAtCompileTime == 3 || DerivedV::ColsAtCompileTime == Eigen::Dynamic, "V should have 3 or Dynamic columns"); using namespace Eigen; using namespace std; typedef Eigen::Matrix RowVector3S; sqrd = tree.squared_distance(V,F,RowVector3S(q),i,(RowVector3S&)c); const Scalar w = hier.winding_number(q.transpose()); s = 1.-2.*w; } template < typename DerivedV, typename DerivedF, typename Derivedq, typename Scalar, typename Derivedc> IGL_INLINE void igl::signed_distance_winding_number( const AABB & tree, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const Eigen::MatrixBase & q, Scalar & s, Scalar & sqrd, int & i, Eigen::PlainObjectBase & c) { static_assert( DerivedV::ColsAtCompileTime == 2 || DerivedV::ColsAtCompileTime == Eigen::Dynamic, "V should have 2 or Dynamic columns"); using namespace Eigen; using namespace std; typedef Eigen::Matrix RowVector2S; sqrd = tree.squared_distance(V,F,RowVector2S(q),i,(RowVector2S&)c); // TODO: using .data() like this is very dangerous... This is assuming // colmajor order assert(!V.derived().IsRowMajor); assert(!F.derived().IsRowMajor); s = 1.-2.*winding_number(V,F,q); } //Multi point by parrallel for on single point template < typename DerivedP, typename DerivedV, typename DerivedF, typename DerivedS> IGL_INLINE void igl::signed_distance_fast_winding_number( const Eigen::MatrixBase & P, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const AABB & tree, const igl::FastWindingNumberBVH & fwn_bvh, Eigen::PlainObjectBase & S) { static_assert( DerivedP::ColsAtCompileTime == 3 || DerivedP::ColsAtCompileTime == Eigen::Dynamic, "P should have 3 or Dynamic columns"); typedef Eigen::Matrix RowVector3S; S.resize(P.rows(),1); int min_parallel = 10000; parallel_for(P.rows(), [&](const int p) { RowVector3S q; q.head(P.row(p).size()) = P.row(p); // get sdf for single point, update result matrix S(p) = signed_distance_fast_winding_number(q, V, F, tree,fwn_bvh); } ,min_parallel); } //Single Point template < typename Derivedq, typename DerivedV, typename DerivedF> IGL_INLINE typename DerivedV::Scalar igl::signed_distance_fast_winding_number( const Eigen::MatrixBase & q, const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const AABB & tree, const igl::FastWindingNumberBVH & fwn_bvh) { static_assert( DerivedV::ColsAtCompileTime == 3 || DerivedV::ColsAtCompileTime == Eigen::Dynamic, "V should have 3 or Dynamic columns"); typedef typename DerivedV::Scalar Scalar; Scalar sqrd; Eigen::Matrix c; int i = -1; sqrd = tree.squared_distance(V,F,q,i,c); Scalar w = fast_winding_number(fwn_bvh,2,q.template cast()); //0.5 is on surface return sqrt(sqrd)*(1.-2.*std::abs(w)); } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation template void igl::signed_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::SignedDistanceType, Eigen::Matrix::Scalar, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::signed_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::SignedDistanceType, Eigen::Matrix::Scalar, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::signed_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::SignedDistanceType, Eigen::Matrix::Scalar, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::signed_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::SignedDistanceType, Eigen::Matrix::Scalar, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::signed_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::SignedDistanceType, Eigen::Matrix::Scalar, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::signed_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::SignedDistanceType, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::signed_distance_pseudonormal, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, double, Eigen::Matrix, Eigen::Matrix >(igl::AABB, 3> const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, double&, double&, int&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::signed_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::SignedDistanceType, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template Eigen::Matrix::Scalar igl::signed_distance_pseudonormal, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(igl::AABB, 3> const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); template void igl::signed_distance_pseudonormal, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::AABB, 3> const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::signed_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::SignedDistanceType, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::signed_distance_winding_number, Eigen::Matrix, Eigen::Matrix, double, Eigen::Matrix >(igl::AABB, 3> const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::WindingNumberAABB, Eigen::Matrix, Eigen::Matrix > const&, Eigen::MatrixBase > const&, double&, double&, int&, Eigen::PlainObjectBase >&); template Eigen::Matrix::Scalar igl::signed_distance_winding_number, Eigen::Matrix, Eigen::Matrix >(igl::AABB, 3> const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::WindingNumberAABB, Eigen::Matrix, Eigen::Matrix > const&, Eigen::MatrixBase > const&); template void igl::signed_distance_fast_winding_number, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::AABB, 3> const&, igl::FastWindingNumberBVH const&, Eigen::PlainObjectBase >&); #endif