normal_derivative.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 Alec Jacobson <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "LinSpaced.h"
  9. #include "normal_derivative.h"
  10. #include "cotmatrix_entries.h"
  11. #include "placeholders.h"
  12. #include <cassert>
  13. template <
  14. typename DerivedV,
  15. typename DerivedEle,
  16. typename Scalar>
  17. IGL_INLINE void igl::normal_derivative(
  18. const Eigen::MatrixBase<DerivedV> & V,
  19. const Eigen::MatrixBase<DerivedEle> & Ele,
  20. Eigen::SparseMatrix<Scalar>& DD)
  21. {
  22. // Element simplex-size
  23. const size_t ss = Ele.cols();
  24. assert( ((ss==3) || (ss==4)) && "Only triangles or tets");
  25. // cotangents
  26. Eigen::Matrix<Scalar ,Eigen::Dynamic ,Eigen::Dynamic> C;
  27. cotmatrix_entries(V,Ele,C);
  28. std::vector<Eigen::Triplet<Scalar> > IJV;
  29. // Number of elements
  30. const size_t m = Ele.rows();
  31. // Number of vertices
  32. const size_t n = V.rows();
  33. switch(ss)
  34. {
  35. default:
  36. assert(false);
  37. return;
  38. case 4:
  39. {
  40. const Eigen::MatrixXi DDJ =
  41. Ele(igl::placeholders::all,{1,0,2,0,3,0,2,1,3,1,0,1,3,2,0,2,1,2,0,3,1,3,2,3});
  42. Eigen::MatrixXi DDI(m,24);
  43. for(size_t f = 0;f<4;f++)
  44. {
  45. const auto & I = (igl::LinSpaced<Eigen::VectorXi >(m,0,m-1).array()+f*m).eval();
  46. for(size_t r = 0;r<6;r++)
  47. {
  48. DDI.col(f*6+r) = I;
  49. }
  50. }
  51. const Eigen::DiagonalMatrix<Scalar,24,24> S =
  52. (Eigen::Matrix<Scalar,2,1>(1,-1).template replicate<12,1>()).asDiagonal();
  53. Eigen::Matrix<Scalar ,Eigen::Dynamic ,Eigen::Dynamic> DDV =
  54. C(igl::placeholders::all,{2,2,1,1,3,3,0,0,4,4,2,2,5,5,1,1,0,0,3,3,4,4,5,5});
  55. DDV *= S;
  56. IJV.reserve(DDV.size());
  57. for(size_t f = 0;f<6*4;f++)
  58. {
  59. for(size_t e = 0;e<m;e++)
  60. {
  61. IJV.push_back(Eigen::Triplet<Scalar>(DDI(e,f),DDJ(e,f),DDV(e,f)));
  62. }
  63. }
  64. DD.resize(m*4,n);
  65. DD.setFromTriplets(IJV.begin(),IJV.end());
  66. break;
  67. }
  68. case 3:
  69. {
  70. const Eigen::MatrixXi DDJ = Ele(igl::placeholders::all,{2,0,1,0,0,1,2,1,1,2,0,2});
  71. Eigen::MatrixXi DDI(m,12);
  72. for(size_t f = 0;f<3;f++)
  73. {
  74. const auto & I = (igl::LinSpaced<Eigen::VectorXi >(m,0,m-1).array()+f*m).eval();
  75. for(size_t r = 0;r<4;r++)
  76. {
  77. DDI.col(f*4+r) = I;
  78. }
  79. }
  80. const Eigen::DiagonalMatrix<Scalar,12,12> S =
  81. (Eigen::Matrix<Scalar,2,1>(1,-1).template replicate<6,1>()).asDiagonal();
  82. Eigen::Matrix<Scalar ,Eigen::Dynamic ,Eigen::Dynamic> DDV = C(igl::placeholders::all,{1,1,2,2,2,2,0,0,0,0,1,1});
  83. DDV *= S;
  84. IJV.reserve(DDV.size());
  85. for(size_t f = 0;f<12;f++)
  86. {
  87. for(size_t e = 0;e<m;e++)
  88. {
  89. IJV.push_back(Eigen::Triplet<Scalar>(DDI(e,f),DDJ(e,f),DDV(e,f)));
  90. }
  91. }
  92. DD.resize(m*3,n);
  93. DD.setFromTriplets(IJV.begin(),IJV.end());
  94. break;
  95. }
  96. }
  97. }
  98. #ifdef IGL_STATIC_LIBRARY
  99. // Explicit template instantiation
  100. template void igl::normal_derivative<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&);
  101. #endif