flip_edge.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2016 Qingan Zhou <qnzhou@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 "flip_edge.h"
  9. template <
  10. typename DerivedF,
  11. typename DerivedE,
  12. typename DeriveduE,
  13. typename DerivedEMAP,
  14. typename uE2EType>
  15. IGL_INLINE void igl::flip_edge(
  16. Eigen::PlainObjectBase<DerivedF> & F,
  17. Eigen::PlainObjectBase<DerivedE> & E,
  18. Eigen::PlainObjectBase<DeriveduE> & uE,
  19. Eigen::PlainObjectBase<DerivedEMAP> & EMAP,
  20. std::vector<std::vector<uE2EType> > & uE2E,
  21. const size_t uei)
  22. {
  23. typedef typename DerivedF::Scalar Index;
  24. const size_t num_faces = F.rows();
  25. assert(F.cols() == 3);
  26. // Edge to flip [v1,v2] --> [v3,v4]
  27. // Before:
  28. // F(f1,:) = [v1,v2,v4] // in some cyclic order
  29. // F(f2,:) = [v1,v3,v2] // in some cyclic order
  30. // After:
  31. // F(f1,:) = [v1,v3,v4] // in *this* order
  32. // F(f2,:) = [v2,v4,v3] // in *this* order
  33. //
  34. // v1 v1
  35. // /|\ / \
  36. // / | \ /f1 \
  37. // v3 /f2|f1\ v4 => v3 /_____\ v4
  38. // \ | / \ f2 /
  39. // \ | / \ /
  40. // \|/ \ /
  41. // v2 v2
  42. auto& half_edges = uE2E[uei];
  43. if (half_edges.size() != 2) {
  44. throw "Cannot flip non-manifold or boundary edge";
  45. }
  46. const size_t f1 = half_edges[0] % num_faces;
  47. const size_t f2 = half_edges[1] % num_faces;
  48. const size_t c1 = half_edges[0] / num_faces;
  49. const size_t c2 = half_edges[1] / num_faces;
  50. assert(c1 < 3);
  51. assert(c2 < 3);
  52. assert(f1 != f2);
  53. const size_t v1 = F(f1, (c1+1)%3);
  54. const size_t v2 = F(f1, (c1+2)%3);
  55. const size_t v4 = F(f1, c1);
  56. const size_t v3 = F(f2, c2);
  57. assert(F(f2, (c2+2)%3) == v1);
  58. assert(F(f2, (c2+1)%3) == v2);
  59. const size_t e_12 = half_edges[0];
  60. const size_t e_24 = f1 + ((c1 + 1) % 3) * num_faces;
  61. const size_t e_41 = f1 + ((c1 + 2) % 3) * num_faces;
  62. const size_t e_21 = half_edges[1];
  63. const size_t e_13 = f2 + ((c2 + 1) % 3) * num_faces;
  64. const size_t e_32 = f2 + ((c2 + 2) % 3) * num_faces;
  65. assert(E(e_12, 0) == v1);
  66. assert(E(e_12, 1) == v2);
  67. assert(E(e_24, 0) == v2);
  68. assert(E(e_24, 1) == v4);
  69. assert(E(e_41, 0) == v4);
  70. assert(E(e_41, 1) == v1);
  71. assert(E(e_21, 0) == v2);
  72. assert(E(e_21, 1) == v1);
  73. assert(E(e_13, 0) == v1);
  74. assert(E(e_13, 1) == v3);
  75. assert(E(e_32, 0) == v3);
  76. assert(E(e_32, 1) == v2);
  77. const size_t ue_24 = EMAP(e_24);
  78. const size_t ue_41 = EMAP(e_41);
  79. const size_t ue_13 = EMAP(e_13);
  80. const size_t ue_32 = EMAP(e_32);
  81. F(f1, 0) = v1;
  82. F(f1, 1) = v3;
  83. F(f1, 2) = v4;
  84. F(f2, 0) = v2;
  85. F(f2, 1) = v4;
  86. F(f2, 2) = v3;
  87. uE(uei, 0) = v3;
  88. uE(uei, 1) = v4;
  89. const size_t new_e_34 = f1;
  90. const size_t new_e_41 = f1 + num_faces;
  91. const size_t new_e_13 = f1 + num_faces*2;
  92. const size_t new_e_43 = f2;
  93. const size_t new_e_32 = f2 + num_faces;
  94. const size_t new_e_24 = f2 + num_faces*2;
  95. E(new_e_34, 0) = v3;
  96. E(new_e_34, 1) = v4;
  97. E(new_e_41, 0) = v4;
  98. E(new_e_41, 1) = v1;
  99. E(new_e_13, 0) = v1;
  100. E(new_e_13, 1) = v3;
  101. E(new_e_43, 0) = v4;
  102. E(new_e_43, 1) = v3;
  103. E(new_e_32, 0) = v3;
  104. E(new_e_32, 1) = v2;
  105. E(new_e_24, 0) = v2;
  106. E(new_e_24, 1) = v4;
  107. EMAP(new_e_34) = uei;
  108. EMAP(new_e_43) = uei;
  109. EMAP(new_e_41) = ue_41;
  110. EMAP(new_e_13) = ue_13;
  111. EMAP(new_e_32) = ue_32;
  112. EMAP(new_e_24) = ue_24;
  113. auto replace = [](std::vector<Index>& array, Index old_v, Index new_v) {
  114. std::replace(array.begin(), array.end(), old_v, new_v);
  115. };
  116. replace(uE2E[uei], e_12, new_e_34);
  117. replace(uE2E[uei], e_21, new_e_43);
  118. replace(uE2E[ue_13], e_13, new_e_13);
  119. replace(uE2E[ue_32], e_32, new_e_32);
  120. replace(uE2E[ue_24], e_24, new_e_24);
  121. replace(uE2E[ue_41], e_41, new_e_41);
  122. #ifndef NDEBUG
  123. auto sanity_check = [&](size_t ue) {
  124. const auto& adj_faces = uE2E[ue];
  125. if (adj_faces.size() == 2) {
  126. const size_t first_f = adj_faces[0] % num_faces;
  127. const size_t first_c = adj_faces[0] / num_faces;
  128. const size_t second_f = adj_faces[1] % num_faces;
  129. const size_t second_c = adj_faces[1] / num_faces;
  130. const size_t vertex_0 = F(first_f, (first_c+1) % 3);
  131. const size_t vertex_1 = F(first_f, (first_c+2) % 3);
  132. assert(vertex_0 == F(second_f, (second_c+2) % 3));
  133. assert(vertex_1 == F(second_f, (second_c+1) % 3));
  134. }
  135. };
  136. sanity_check(uei);
  137. sanity_check(ue_13);
  138. sanity_check(ue_32);
  139. sanity_check(ue_24);
  140. sanity_check(ue_41);
  141. #endif
  142. }
  143. #ifdef IGL_STATIC_LIBRARY
  144. // Explicit template instantiation
  145. // generated by autoexplicit.sh
  146. template void igl::flip_edge<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, unsigned long);
  147. template void igl::flip_edge<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::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, unsigned long);
  148. #ifdef WIN32
  149. template void igl::flip_edge<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::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, unsigned __int64);
  150. template void igl::flip_edge<class Eigen::Matrix<int,-1,-1,0,-1,-1>,class Eigen::Matrix<int,-1,2,0,-1,2>,class Eigen::Matrix<int,-1,2,0,-1,2>,class Eigen::Matrix<int,-1,1,0,-1,1>,int>(class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> > &,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,2,0,-1,2> > &,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,2,0,-1,2> > &,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,1,0,-1,1> > &,class std::vector<class std::vector<int,class std::allocator<int> >,class std::allocator<class std::vector<int,class std::allocator<int> > > > &,unsigned __int64);
  151. #endif
  152. #endif