upsample.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 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 "upsample.h"
  9. #include "triangle_triangle_adjacency.h"
  10. template <
  11. typename DerivedF,
  12. typename SType,
  13. typename DerivedNF>
  14. IGL_INLINE void igl::upsample(
  15. const int n_verts,
  16. const Eigen::MatrixBase<DerivedF>& F,
  17. Eigen::SparseMatrix<SType>& S,
  18. Eigen::PlainObjectBase<DerivedNF>& NF)
  19. {
  20. typedef Eigen::Triplet<SType> Triplet_t;
  21. Eigen::Matrix< typename DerivedF::Scalar,Eigen::Dynamic,Eigen::Dynamic>
  22. FF,FFi;
  23. triangle_triangle_adjacency(F,FF,FFi);
  24. // TODO: Cache optimization missing from here, it is a mess
  25. // Compute the number and positions of the vertices to insert (on edges)
  26. Eigen::MatrixXi NI = Eigen::MatrixXi::Constant(FF.rows(),FF.cols(),-1);
  27. Eigen::MatrixXi NIdoubles = Eigen::MatrixXi::Zero(FF.rows(), FF.cols());
  28. int counter = 0;
  29. for(int i=0;i<FF.rows();++i)
  30. {
  31. for(int j=0;j<3;++j)
  32. {
  33. if(NI(i,j) == -1)
  34. {
  35. NI(i,j) = counter;
  36. NIdoubles(i,j) = 0;
  37. if (FF(i,j) != -1) {
  38. //If it is not a boundary
  39. NI(FF(i,j), FFi(i,j)) = counter;
  40. NIdoubles(i,j) = 1;
  41. }
  42. ++counter;
  43. }
  44. }
  45. }
  46. const int& n_odd = n_verts;
  47. const int& n_even = counter;
  48. const int n_newverts = n_odd + n_even;
  49. //Construct vertex positions
  50. std::vector<Triplet_t> tripletList;
  51. // Fill the odd vertices position
  52. for (int i=0; i<n_odd; ++i)
  53. {
  54. tripletList.emplace_back(i, i, 1.);
  55. }
  56. for(int i=0;i<FF.rows();++i)
  57. {
  58. for(int j=0;j<3;++j)
  59. {
  60. if(NIdoubles(i,j)==0) {
  61. tripletList.emplace_back(NI(i,j) + n_odd, F(i,j), 1./2.);
  62. tripletList.emplace_back(NI(i,j) + n_odd, F(i,(j+1)%3), 1./2.);
  63. }
  64. }
  65. }
  66. S.resize(n_newverts, n_verts);
  67. S.setFromTriplets(tripletList.begin(), tripletList.end());
  68. // Build the new topology (Every face is replaced by four)
  69. NF.resize(F.rows()*4,3);
  70. for(int i=0; i<F.rows();++i)
  71. {
  72. Eigen::Matrix<typename DerivedF::Scalar, 1, 6> VI(6);
  73. VI << F(i,0), F(i,1), F(i,2), NI(i,0) + n_odd, NI(i,1) + n_odd, NI(i,2) + n_odd;
  74. Eigen::Matrix<typename DerivedNF::Scalar, 1, 3> f0(3), f1(3), f2(3), f3(3);
  75. f0 << VI(0), VI(3), VI(5);
  76. f1 << VI(1), VI(4), VI(3);
  77. f2 << VI(3), VI(4), VI(5);
  78. f3 << VI(4), VI(2), VI(5);
  79. NF.row((i*4)+0) = f0;
  80. NF.row((i*4)+1) = f1;
  81. NF.row((i*4)+2) = f2;
  82. NF.row((i*4)+3) = f3;
  83. }
  84. }
  85. template <
  86. typename DerivedV,
  87. typename DerivedF,
  88. typename DerivedNV,
  89. typename DerivedNF>
  90. IGL_INLINE void igl::upsample(
  91. const Eigen::MatrixBase<DerivedV>& V,
  92. const Eigen::MatrixBase<DerivedF>& F,
  93. Eigen::PlainObjectBase<DerivedNV>& NV,
  94. Eigen::PlainObjectBase<DerivedNF>& NF,
  95. const int number_of_subdivs)
  96. {
  97. NV = V;
  98. NF = F;
  99. for(int i=0; i<number_of_subdivs; ++i)
  100. {
  101. DerivedNF tempF = NF;
  102. Eigen::SparseMatrix<typename DerivedV::Scalar >S;
  103. upsample(NV.rows(), tempF, S, NF);
  104. // This .eval is super important
  105. NV = (S*NV).eval();
  106. }
  107. }
  108. template <
  109. typename MatV,
  110. typename MatF>
  111. IGL_INLINE void igl::upsample(
  112. MatV& V,
  113. MatF& F,
  114. const int number_of_subdivs)
  115. {
  116. const MatV V_copy = V;
  117. const MatF F_copy = F;
  118. return upsample(V_copy,F_copy,V,F,number_of_subdivs);
  119. }
  120. #ifdef IGL_STATIC_LIBRARY
  121. // Explicit template instantiation
  122. template void igl::upsample<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::Matrix<int, -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> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, int);
  123. template void igl::upsample<Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(int, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  124. template void igl::upsample<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::Matrix<int, -1, -1, 0, -1, -1>&, int);
  125. #endif