voronoi_mass.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #include "voronoi_mass.h"
  2. #include "circumradius.h"
  3. #include "centroid.h"
  4. #include "unique_simplices.h"
  5. template <
  6. typename DerivedV,
  7. typename DerivedT,
  8. typename DerivedM>
  9. void igl::voronoi_mass(
  10. const Eigen::MatrixBase<DerivedV> & V,
  11. const Eigen::MatrixBase<DerivedT> & T,
  12. Eigen::PlainObjectBase<DerivedM> & M)
  13. {
  14. // DerivedM::Scalar must be same as DerivedV::Scalar
  15. static_assert(std::is_same<typename DerivedM::Scalar, typename DerivedV::Scalar>::value, "DerivedM::Scalar must be same as DerivedV::Scalar");
  16. // DerivedM must be a vector (rows or cols at compile time = 1)
  17. static_assert(DerivedM::RowsAtCompileTime == 1 || DerivedM::ColsAtCompileTime == 1, "DerivedM must be a vector (rows or cols at compile time = 1)");
  18. // DerivedT must have Dynamic or 4 cols
  19. static_assert(DerivedT::ColsAtCompileTime == Eigen::Dynamic || DerivedT::ColsAtCompileTime == 4, "DerivedT must have Dynamic or 4 cols");
  20. assert(T.cols() == 4 && "Tetrahedra should have 4 vertices");
  21. // DerivedV must have Dynamic or 3 cols
  22. static_assert(DerivedV::ColsAtCompileTime == Eigen::Dynamic || DerivedV::ColsAtCompileTime == 3, "DerivedV must have Dynamic or 3 cols");
  23. assert(V.cols() == 3 && "V should have 3 columns");
  24. using Scalar = typename DerivedV::Scalar;
  25. using VectorXS = Eigen::Matrix<Scalar,Eigen::Dynamic,1>;
  26. using MatrixX3S = Eigen::Matrix<Scalar,Eigen::Dynamic,3>;
  27. using MatrixX4S = Eigen::Matrix<Scalar,Eigen::Dynamic,4>;
  28. using MatrixX3I = Eigen::Matrix<int,Eigen::Dynamic,3>;
  29. using MatrixX4I = Eigen::Matrix<int,Eigen::Dynamic,4>;
  30. MatrixX3I F;
  31. MatrixX4I I;
  32. {
  33. MatrixX3I allF(T.rows()*T.cols(),3);
  34. for(int i = 0;i<T.rows();i++)
  35. {
  36. for(int j = 0;j<T.cols();j++)
  37. {
  38. allF.row(j*T.rows()+i) <<
  39. T(i,(j+1)%T.cols()),
  40. T(i,(j+2)%T.cols()),
  41. T(i,(j+3)%T.cols());
  42. }
  43. }
  44. Eigen::VectorXi _;
  45. Eigen::VectorXi Ivec;
  46. igl::unique_simplices(allF,F,_,Ivec);
  47. I = Ivec.reshaped(T.rows(),T.cols());
  48. }
  49. // Face circumcenters
  50. MatrixX3S CF;
  51. {
  52. VectorXS R;
  53. MatrixX3S B;
  54. circumradius(V,F,R,CF,B);
  55. for(int i = 0;i<F.rows();i++)
  56. {
  57. int j;
  58. // Snap to edge "circumcenter"
  59. if(B.row(i).minCoeff(&j) < 0)
  60. {
  61. CF.row(i) = (V.row(F(i,(j+1)%3)) + V.row(F(i,(j+2)%3)))*0.5;
  62. }
  63. }
  64. }
  65. MatrixX3S CT;
  66. {
  67. VectorXS R;
  68. MatrixX4S B;
  69. circumradius(V,T,R,CT,B);
  70. for(int i = 0;i<T.rows();i++)
  71. {
  72. int j;
  73. // Snap to face "circumcenter"
  74. if(B.row(i).minCoeff(&j) < 0)
  75. {
  76. CT.row(i) = CF.row(I(i,j));
  77. }
  78. }
  79. }
  80. M.setZero(V.rows());
  81. for(int i = 0;i<T.rows();i++)
  82. {
  83. for(int j = 0;j<4;j++)
  84. {
  85. Eigen::Matrix<Scalar,8,3> U(8,V.cols());
  86. U.row(0) = V.row(T(i,j));
  87. // edge circumcenters
  88. for(int k = 1;k<4;k++)
  89. {
  90. U.row(k) = 0.5*(U.row(0) + V.row(T(i,(j+k)%4)));
  91. }
  92. // face circumcenters
  93. {
  94. U.block(4,0,3,V.cols()) <<
  95. CF.row(I(i,(j+1)%4)),
  96. CF.row(I(i,(j+2)%4)),
  97. CF.row(I(i,(j+3)%4));
  98. }
  99. // Tet circumcenter
  100. {
  101. U.row(7) = CT.row(i);
  102. }
  103. Eigen::Matrix<int,12,3> Fij(12,3);
  104. Fij<<
  105. 4,2,0,
  106. 5,3,0,
  107. 6,1,0,
  108. 7,2,4,
  109. 7,3,5,
  110. 7,1,6,
  111. 4,0,3,
  112. 5,0,1,
  113. 6,0,2,
  114. 7,4,3,
  115. 7,5,1,
  116. 7,6,2;
  117. if(j%2)
  118. {
  119. Fij = Fij.rowwise().reverse().eval();
  120. }
  121. Scalar vol;
  122. {
  123. Eigen::Matrix<Scalar,1,3> cen;
  124. igl::centroid(U,Fij,cen,vol);
  125. }
  126. M(T(i,j)) += vol;
  127. }
  128. }
  129. }
  130. #ifdef IGL_STATIC_LIBRARY
  131. // Explicit template instantiation
  132. template void igl::voronoi_mass<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
  133. template void igl::voronoi_mass<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
  134. template void igl::voronoi_mass<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
  135. template void igl::voronoi_mass<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 4, 0, -1, 4>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
  136. #endif