// 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" template IGL_INLINE typename Kernel::FT igl::signed_distance_pseudonormal( const CGAL::AABB_tree< CGAL::AABB_traits >::iterator > > > & tree, const std::vector > & T, const Eigen::MatrixXi & F, const Eigen::MatrixXd & FN, const Eigen::MatrixXd & VN, const Eigen::MatrixXd & EN, const Eigen::VectorXi & EMAP, const typename Kernel::Point_3 & q) { using namespace Eigen; using namespace std; typedef typename Kernel::FT FT; typedef typename Kernel::Point_3 Point_3; typedef typename CGAL::Triangle_3 Triangle_3; typedef typename std::vector::iterator Iterator; typedef typename CGAL::AABB_triangle_primitive Primitive; typedef typename CGAL::AABB_traits AABB_triangle_traits; typedef typename CGAL::AABB_tree Tree; typedef typename Tree::Point_and_primitive_id Point_and_primitive_id; Point_and_primitive_id pp = tree.closest_point_and_primitive(q); Point_3 & p = pp.first; const auto & qp = q-p; const FT sqrd = qp.squared_length(); Vector3d v(qp.x(),qp.y(),qp.z()); const int f = pp.second - T.begin(); const Triangle_3 & t = *pp.second; // barycentric coordinates const auto & area = [&p,&t](const int i, const int j)->FT { return sqrt(Triangle_3(p,t.vertex(i),t.vertex(j)).squared_area()); }; Vector3d b(area(1,2),area(2,0),area(0,1)); b /= b.sum(); // Determine which normal to use Vector3d n; const double epsilon = 1e-12; const int type = (b.array()<=epsilon).cast().sum(); switch(type) { case 2: // Find vertex for(int c = 0;c<3;c++) { if(b(c)>epsilon) { n = VN.row(F(f,c)); break; } } break; case 1: // Find edge for(int c = 0;c<3;c++) { if(b(c)<=epsilon) { n = EN.row(EMAP(F.rows()*c+f)); break; } } break; default: assert(false && "all barycentric coords zero."); case 0: n = FN.row(f); break; } const double s = (v.dot(n) >= 0 ? 1. : -1.); return s*sqrt(sqrd); } template IGL_INLINE typename Kernel::FT igl::signed_distance_winding_number( const CGAL::AABB_tree< CGAL::AABB_traits >::iterator > > > & tree, const igl::WindingNumberAABB & hier, const typename Kernel::Point_3 & q) { typedef typename Kernel::FT FT; typedef typename Kernel::Point_3 Point_3; typedef typename CGAL::Triangle_3 Triangle_3; typedef typename std::vector::iterator Iterator; typedef typename CGAL::AABB_triangle_primitive Primitive; typedef typename CGAL::AABB_traits AABB_triangle_traits; typedef typename CGAL::AABB_tree Tree; typedef typename Tree::Point_and_primitive_id Point_and_primitive_id; using namespace Eigen; using namespace std; using namespace igl; Point_and_primitive_id pp = tree.closest_point_and_primitive(q); Point_3 & p = pp.first; const auto & qp = q-p; const Vector3d eq(q.x(),q.y(),q.z()); const FT sqrd = qp.squared_length(); const double w = hier.winding_number(eq); const FT s = 1.-2.*w; return s*sqrt(sqrd); } #ifdef IGL_STATIC_LIBRARY template CGAL::Epick::FT igl::signed_distance_winding_number(CGAL::AABB_tree, std::allocator > >::iterator, CGAL::Boolean_tag > > > const&, igl::WindingNumberAABB > const&, CGAL::Epick::Point_3 const&); template CGAL::Epick::FT igl::signed_distance_pseudonormal(CGAL::AABB_tree, std::allocator > >::iterator, CGAL::Boolean_tag > > > const&, std::vector, std::allocator > > const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, CGAL::Epick::Point_3 const&); #endif