// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2013 Alec Jacobson // 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 "cotmatrix_entries.h" #include "doublearea.h" #include "squared_edge_lengths.h" #include "edge_lengths.h" #include "face_areas.h" #include "volume.h" #include "dihedral_angles.h" #include "verbose.h" template IGL_INLINE void igl::cotmatrix_entries( const Eigen::MatrixBase& V, const Eigen::MatrixBase& F, Eigen::PlainObjectBase& C) { using namespace std; using namespace Eigen; // simplex size (3: triangles, 4: tetrahedra) int simplex_size = F.cols(); // Number of elements int m = F.rows(); // Law of cosines + law of sines switch(simplex_size) { case 3: { // Triangles //Compute Squared Edge lengths Matrix l2; igl::squared_edge_lengths(V,F,l2); //Compute Edge lengths Matrix l; l = l2.array().sqrt(); // double area Matrix dblA; doublearea(l,0.,dblA); // cotangents and diagonal entries for element matrices // correctly divided by 4 (alec 2010) C.resize(m,3); for(int i = 0;i l; edge_lengths(V,F,l); Matrix s; face_areas(l,s); Matrix cos_theta,theta; dihedral_angles_intrinsic(l,s,theta,cos_theta); // volume Matrix vol; volume(l,vol); // Law of sines // http://mathworld.wolfram.com/Tetrahedron.html Matrix sin_theta(m,6); sin_theta.col(0) = vol.array() / ((2./(3.*l.col(0).array())).array() * s.col(1).array() * s.col(2).array()); sin_theta.col(1) = vol.array() / ((2./(3.*l.col(1).array())).array() * s.col(2).array() * s.col(0).array()); sin_theta.col(2) = vol.array() / ((2./(3.*l.col(2).array())).array() * s.col(0).array() * s.col(1).array()); sin_theta.col(3) = vol.array() / ((2./(3.*l.col(3).array())).array() * s.col(3).array() * s.col(0).array()); sin_theta.col(4) = vol.array() / ((2./(3.*l.col(4).array())).array() * s.col(3).array() * s.col(1).array()); sin_theta.col(5) = vol.array() / ((2./(3.*l.col(5).array())).array() * s.col(3).array() * s.col(2).array()); // http://arxiv.org/pdf/1208.0354.pdf Page 18 C = (1./6.) * l.array() * cos_theta.array() / sin_theta.array(); break; } default: { fprintf(stderr, "cotmatrix_entries.h: Error: Simplex size (%d) not supported\n", simplex_size); assert(false); } } } template IGL_INLINE void igl::cotmatrix_entries( const Eigen::MatrixBase& l, Eigen::PlainObjectBase& C) { using namespace Eigen; const int m = l.rows(); assert(l.cols() == 3 && "Only triangles accepted"); //Compute squared Edge lengths Matrix l2; l2 = l.array().square(); // Alec: It's a little annoying that there's duplicate code here. The // "extrinic" version above is first computing squared edge lengths, taking // the square root and calling this. We can't have a cotmatrix_entries(l,l2,C) // overload because it will confuse Eigen with the cotmatrix_entries(V,F,C) // overload. In the end, I'd like to be convinced that using l2 directly above // is actually better numerically (or significantly faster) than just calling // edge_lengths and this cotmatrix_entries(l,C); // // double area Matrix dblA; doublearea(l,0.,dblA); // cotangents and diagonal entries for element matrices // correctly divided by 4 (alec 2010) C.resize(m,3); for(int i = 0;i, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::cotmatrix_entries, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::cotmatrix_entries, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::cotmatrix_entries, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::cotmatrix_entries, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::cotmatrix_entries, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::cotmatrix_entries, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif