// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2018 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 "grad_intrinsic.h" #include "grad.h" template IGL_INLINE void igl::grad_intrinsic( const Eigen::MatrixBase&l, const Eigen::MatrixBase&F, Eigen::SparseMatrix &G) { assert(F.cols() ==3 && "Only triangles supported"); // number of vertices const int n = F.maxCoeff()+1; // number of faces const int m = F.rows(); // JD: There is a pretty subtle bug when using a fixed column size for this matrix. // When calling igl::grad(V, ...), the two code paths `grad_tet` and `grad_tri` // will be compiled. It turns out that `igl::grad_tet` calls `igl::volume`, which // reads the coordinates of the `V` matrix into `RowVector3d`. If the matrix `V` // has a known compile-time size of 2, this produces a compilation error when // libigl is compiled in header-only mode. In static mode this doesn't happen // because the matrix `V` is probably implicitly copied into a `Eigen::MatrixXd`. // This is a situation that could be solved using `if constexpr` in C++17. // In C++11, the alternative is to use SFINAE and `std::enable_if` (ugh). typedef Eigen::Matrix MatrixX2S; MatrixX2S V2 = MatrixX2S::Zero(3*m,2); // 1=[x,y] // /\ // l3 / \ l2 // / \ // / \ // 2-----------3 // l1 // // x = (l2²-l1²-l3²)/(-2*l1) // y = sqrt(l3² - x²) // // // Place 3rd vertex at [l(:,1) 0] V2.block(2*m,0,m,1) = l.col(0); // Place second vertex at [0 0] // Place third vertex at [x y] V2.block(0,0,m,1) = (l.col(1).cwiseAbs2()-l.col(0).cwiseAbs2()-l.col(2).cwiseAbs2()).array()/ (-2.*l.col(0)).array(); V2.block(0,1,m,1) = (l.col(2).cwiseAbs2() - V2.block(0,0,m,1).cwiseAbs2()).array().sqrt(); DerivedF F2(F.rows(),F.cols()); std::vector > Pijv; Pijv.reserve(F.size()); for(int f = 0;f P(m*3,n); P.setFromTriplets(Pijv.begin(),Pijv.end()); Eigen::SparseMatrix G2; grad(V2,F2,G2); G = G2*P; } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh template void igl::grad_intrinsic, Eigen::Matrix, double>(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::SparseMatrix&); // generated by autoexplicit.sh template void igl::grad_intrinsic, Eigen::Matrix, double>(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::SparseMatrix&); #endif