normal_derivative.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
  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 "normal_derivative.h"
  9. #include "cotmatrix_entries.h"
  10. #include "slice.h"
  11. #include <cassert>
  12. template <
  13. typename DerivedV,
  14. typename DerivedEle,
  15. typename Scalar>
  16. IGL_INLINE void igl::normal_derivative(
  17. const Eigen::PlainObjectBase<DerivedV> & V,
  18. const Eigen::PlainObjectBase<DerivedEle> & Ele,
  19. Eigen::SparseMatrix<Scalar>& DD)
  20. {
  21. using namespace Eigen;
  22. using namespace std;
  23. // Element simplex-size
  24. const size_t ss = Ele.cols();
  25. assert( ((ss==3) || (ss==4)) && "Only triangles or tets");
  26. // cotangents
  27. Matrix<Scalar,Dynamic,Dynamic> C;
  28. cotmatrix_entries(V,Ele,C);
  29. vector<Triplet<Scalar> > IJV;
  30. // Number of elements
  31. const size_t m = Ele.rows();
  32. // Number of vertices
  33. const size_t n = V.rows();
  34. switch(ss)
  35. {
  36. default:
  37. assert(false);
  38. return;
  39. case 4:
  40. {
  41. const MatrixXi DDJ =
  42. slice(
  43. Ele,
  44. (VectorXi(24)<<
  45. 1,0,2,0,3,0,2,1,3,1,0,1,3,2,0,2,1,2,0,3,1,3,2,3).finished(),
  46. 2);
  47. MatrixXi DDI(m,24);
  48. for(size_t f = 0;f<4;f++)
  49. {
  50. const auto & I = (VectorXi::LinSpaced(m,0,m-1).array()+f*m).eval();
  51. for(size_t r = 0;r<6;r++)
  52. {
  53. DDI.col(f*6+r) = I;
  54. }
  55. }
  56. const DiagonalMatrix<Scalar,24,24> S =
  57. (Matrix<Scalar,2,1>(1,-1).template replicate<12,1>()).asDiagonal();
  58. Matrix<Scalar,Dynamic,Dynamic> DDV =
  59. slice(
  60. C,
  61. (VectorXi(24)<<
  62. 2,2,1,1,3,3,0,0,4,4,2,2,5,5,1,1,0,0,3,3,4,4,5,5).finished(),
  63. 2);
  64. DDV *= S;
  65. IJV.reserve(DDV.size());
  66. for(size_t f = 0;f<6*4;f++)
  67. {
  68. for(size_t e = 0;e<m;e++)
  69. {
  70. IJV.push_back(Triplet<Scalar>(DDI(e,f),DDJ(e,f),DDV(e,f)));
  71. }
  72. }
  73. DD.resize(m*4,n);
  74. DD.setFromTriplets(IJV.begin(),IJV.end());
  75. break;
  76. }
  77. case 3:
  78. {
  79. const MatrixXi DDJ =
  80. slice(Ele,(VectorXi(12)<<2,0,1,0,0,1,2,1,1,2,0,2).finished(),2);
  81. MatrixXi DDI(m,12);
  82. for(size_t f = 0;f<3;f++)
  83. {
  84. const auto & I = (VectorXi::LinSpaced(m,0,m-1).array()+f*m).eval();
  85. for(size_t r = 0;r<4;r++)
  86. {
  87. DDI.col(f*4+r) = I;
  88. }
  89. }
  90. const DiagonalMatrix<Scalar,12,12> S =
  91. (Matrix<Scalar,2,1>(1,-1).template replicate<6,1>()).asDiagonal();
  92. Matrix<Scalar,Dynamic,Dynamic> DDV =
  93. slice(C,(VectorXi(12)<<1,1,2,2,2,2,0,0,0,0,1,1).finished(),2);
  94. DDV *= S;
  95. IJV.reserve(DDV.size());
  96. for(size_t f = 0;f<12;f++)
  97. {
  98. for(size_t e = 0;e<m;e++)
  99. {
  100. IJV.push_back(Triplet<Scalar>(DDI(e,f),DDJ(e,f),DDV(e,f)));
  101. }
  102. }
  103. DD.resize(m*3,n);
  104. DD.setFromTriplets(IJV.begin(),IJV.end());
  105. break;
  106. }
  107. }
  108. }
  109. #ifdef IGL_STATIC_LIBRARY
  110. // Explicit template specialization
  111. template void igl::normal_derivative<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&);
  112. #endif