collapse_edge.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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 "collapse_edge.h"
  9. #include "circulation.h"
  10. #include "edge_collapse_is_valid.h"
  11. #include <vector>
  12. template <
  13. typename Derivedp,
  14. typename DerivedV,
  15. typename DerivedF,
  16. typename DerivedE,
  17. typename DerivedEMAP,
  18. typename DerivedEF,
  19. typename DerivedEI>
  20. IGL_INLINE bool igl::collapse_edge(
  21. const int e,
  22. const Eigen::MatrixBase<Derivedp> & p,
  23. Eigen::MatrixBase<DerivedV> & V,
  24. Eigen::MatrixBase<DerivedF> & F,
  25. Eigen::MatrixBase<DerivedE> & E,
  26. Eigen::MatrixBase<DerivedEMAP> & EMAP,
  27. Eigen::MatrixBase<DerivedEF> & EF,
  28. Eigen::MatrixBase<DerivedEI> & EI,
  29. int & e1,
  30. int & e2,
  31. int & f1,
  32. int & f2)
  33. {
  34. std::vector<int> /*Nse,*/Nsf,Nsv;
  35. circulation(e, true,F,EMAP,EF,EI,/*Nse,*/Nsv,Nsf);
  36. std::vector<int> /*Nde,*/Ndf,Ndv;
  37. circulation(e, false,F,EMAP,EF,EI,/*Nde,*/Ndv,Ndf);
  38. return collapse_edge(
  39. e,p,Nsv,Nsf,Ndv,Ndf,V,F,E,EMAP,EF,EI,e1,e2,f1,f2);
  40. }
  41. template
  42. <
  43. typename Derivedp,
  44. typename DerivedV,
  45. typename DerivedF,
  46. typename DerivedE,
  47. typename DerivedEMAP,
  48. typename DerivedEF,
  49. typename DerivedEI>
  50. IGL_INLINE bool igl::collapse_edge(
  51. const int e,
  52. const Eigen::MatrixBase<Derivedp> & p,
  53. /*const*/ std::vector<int> & Nsv,
  54. const std::vector<int> & Nsf,
  55. /*const*/ std::vector<int> & Ndv,
  56. const std::vector<int> & Ndf,
  57. Eigen::MatrixBase<DerivedV> & V,
  58. Eigen::MatrixBase<DerivedF> & F,
  59. Eigen::MatrixBase<DerivedE> & E,
  60. Eigen::MatrixBase<DerivedEMAP> & EMAP,
  61. Eigen::MatrixBase<DerivedEF> & EF,
  62. Eigen::MatrixBase<DerivedEI> & EI,
  63. int & a_e1,
  64. int & a_e2,
  65. int & a_f1,
  66. int & a_f2)
  67. {
  68. // Assign this to 0 rather than, say, -1 so that deleted elements will get
  69. // draw as degenerate elements at vertex 0 (which should always exist and
  70. // never get collapsed to anything else since it is the smallest index)
  71. const int eflip = E(e,0)>E(e,1);
  72. // source and destination
  73. const int s = eflip?E(e,1):E(e,0);
  74. const int d = eflip?E(e,0):E(e,1);
  75. if(!edge_collapse_is_valid(Nsv,Ndv))
  76. {
  77. return false;
  78. }
  79. // OVERLOAD: caller may have just computed this
  80. //
  81. // Important to grab neighbors of d before monkeying with edges
  82. const std::vector<int> & nV2Fd = (!eflip ? Nsf : Ndf);
  83. // The following implementation strongly relies on s<d
  84. assert(s<d && "s should be less than d");
  85. // move source and destination to placement
  86. V.row(s) = p;
  87. V.row(d) = p;
  88. // Helper function to replace edge and associate information with NULL
  89. const auto & kill_edge = [&E,&EI,&EF](const int e)
  90. {
  91. E(e,0) = IGL_COLLAPSE_EDGE_NULL;
  92. E(e,1) = IGL_COLLAPSE_EDGE_NULL;
  93. EF(e,0) = IGL_COLLAPSE_EDGE_NULL;
  94. EF(e,1) = IGL_COLLAPSE_EDGE_NULL;
  95. EI(e,0) = IGL_COLLAPSE_EDGE_NULL;
  96. EI(e,1) = IGL_COLLAPSE_EDGE_NULL;
  97. };
  98. // update edge info
  99. // for each flap
  100. const int m = F.rows();
  101. for(int side = 0;side<2;side++)
  102. {
  103. const int f = EF(e,side);
  104. const int v = EI(e,side);
  105. const int sign = (eflip==0?1:-1)*(1-2*side);
  106. // next edge emanating from d
  107. const int e1 = EMAP(f+m*((v+sign*1+3)%3));
  108. // prev edge pointing to s
  109. const int e2 = EMAP(f+m*((v+sign*2+3)%3));
  110. assert(E(e1,0) == d || E(e1,1) == d);
  111. assert(E(e2,0) == s || E(e2,1) == s);
  112. // face adjacent to f on e1, also incident on d
  113. const bool flip1 = EF(e1,1)==f;
  114. const int f1 = flip1 ? EF(e1,0) : EF(e1,1);
  115. assert(f1!=f);
  116. assert(F(f1,0)==d || F(f1,1)==d || F(f1,2) == d);
  117. // across from which vertex of f1 does e1 appear?
  118. const int v1 = flip1 ? EI(e1,0) : EI(e1,1);
  119. // Kill e1
  120. kill_edge(e1);
  121. // Kill f
  122. F(f,0) = IGL_COLLAPSE_EDGE_NULL;
  123. F(f,1) = IGL_COLLAPSE_EDGE_NULL;
  124. F(f,2) = IGL_COLLAPSE_EDGE_NULL;
  125. // map f1's edge on e1 to e2
  126. assert(EMAP(f1+m*v1) == e1);
  127. EMAP(f1+m*v1) = e2;
  128. // side opposite f2, the face adjacent to f on e2, also incident on s
  129. const int opp2 = (EF(e2,0)==f?0:1);
  130. assert(EF(e2,opp2) == f);
  131. EF(e2,opp2) = f1;
  132. EI(e2,opp2) = v1;
  133. // remap e2 from d to s
  134. E(e2,0) = E(e2,0)==d ? s : E(e2,0);
  135. E(e2,1) = E(e2,1)==d ? s : E(e2,1);
  136. if(side==0)
  137. {
  138. a_e1 = e1;
  139. a_f1 = f;
  140. }else
  141. {
  142. a_e2 = e1;
  143. a_f2 = f;
  144. }
  145. }
  146. // finally, reindex faces and edges incident on d. Do this last so asserts
  147. // make sense.
  148. //
  149. // Could actually skip first and last, since those are always the two
  150. // collpased faces. Nah, this is handled by (F(f,v) == d)
  151. //
  152. // Don't attempt to use Nde,Nse here because EMAP has changed
  153. {
  154. int p1 = -1;
  155. for(auto f : nV2Fd)
  156. {
  157. for(int v = 0;v<3;v++)
  158. {
  159. if(F(f,v) == d)
  160. {
  161. const int e1 = EMAP(f+m*((v+1)%3));
  162. const int flip1 = (EF(e1,0)==f)?1:0;
  163. assert( E(e1,flip1) == d || E(e1,flip1) == s);
  164. E(e1,flip1) = s;
  165. const int e2 = EMAP(f+m*((v+2)%3));
  166. // Skip if we just handled this edge (claim: this will be all except
  167. // for the first non-trivial face)
  168. if(e2 != p1)
  169. {
  170. const int flip2 = (EF(e2,0)==f)?0:1;
  171. assert( E(e2,flip2) == d || E(e2,flip2) == s);
  172. E(e2,flip2) = s;
  173. }
  174. F(f,v) = s;
  175. p1 = e1;
  176. break;
  177. }
  178. }
  179. }
  180. }
  181. // Finally, "remove" this edge and its information
  182. kill_edge(e);
  183. return true;
  184. }
  185. #ifdef IGL_STATIC_LIBRARY
  186. // Explicit template instantiation
  187. template bool igl::collapse_edge<Eigen::Matrix<double, 1, -1, 1, 1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(int, Eigen::MatrixBase<Eigen::Matrix<double, 1, -1, 1, 1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, int&, int&, int&, int&);
  188. template bool igl::collapse_edge<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(int, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false>> const&, std::vector<int, std::allocator<int>>&, std::vector<int, std::allocator<int>> const&, std::vector<int, std::allocator<int>>&, std::vector<int, std::allocator<int>> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, int&, int&, int&, int&);
  189. #endif