edge_collapse_is_valid.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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 "edge_collapse_is_valid.h"
  9. #include "collapse_edge.h"
  10. #include "circulation.h"
  11. #include "intersect.h"
  12. #include "unique.h"
  13. #include "list_to_matrix.h"
  14. #include <vector>
  15. IGL_INLINE bool igl::edge_collapse_is_valid(
  16. const int e,
  17. const Eigen::MatrixXi & F,
  18. const Eigen::MatrixXi & E,
  19. const Eigen::VectorXi & EMAP,
  20. const Eigen::MatrixXi & EF,
  21. const Eigen::MatrixXi & EI)
  22. {
  23. using namespace Eigen;
  24. using namespace std;
  25. // For consistency with collapse_edge.cpp, let's determine edge flipness
  26. // (though not needed to check validity)
  27. const int eflip = E(e,0)>E(e,1);
  28. // source and destination
  29. const int s = eflip?E(e,1):E(e,0);
  30. const int d = eflip?E(e,0):E(e,1);
  31. if(s == IGL_COLLAPSE_EDGE_NULL && d==IGL_COLLAPSE_EDGE_NULL)
  32. {
  33. return false;
  34. }
  35. // check if edge collapse is valid: intersection of vertex neighbors of s and
  36. // d should be exactly 2+(s,d) = 4
  37. // http://stackoverflow.com/a/27049418/148668
  38. {
  39. // all vertex neighbors around edge, including the two vertices of the edge
  40. const auto neighbors = [](
  41. const int e,
  42. const bool ccw,
  43. const Eigen::MatrixXi & F,
  44. const Eigen::VectorXi & EMAP,
  45. const Eigen::MatrixXi & EF,
  46. const Eigen::MatrixXi & EI)
  47. {
  48. vector<int> N,uN;
  49. vector<int> V2Fe = circulation(e, ccw,EMAP,EF,EI);
  50. for(auto f : V2Fe)
  51. {
  52. N.push_back(F(f,0));
  53. N.push_back(F(f,1));
  54. N.push_back(F(f,2));
  55. }
  56. vector<size_t> _1,_2;
  57. igl::unique(N,uN,_1,_2);
  58. VectorXi uNm;
  59. list_to_matrix(uN,uNm);
  60. return uNm;
  61. };
  62. VectorXi Ns = neighbors(e, eflip,F,EMAP,EF,EI);
  63. VectorXi Nd = neighbors(e,!eflip,F,EMAP,EF,EI);
  64. VectorXi Nint = igl::intersect(Ns,Nd);
  65. if(Nint.size() != 4)
  66. {
  67. return false;
  68. }
  69. if(Ns.size() == 4 && Nd.size() == 4)
  70. {
  71. VectorXi NsNd(8);
  72. NsNd<<Ns,Nd;
  73. VectorXi Nun,_1,_2;
  74. igl::unique(NsNd,Nun,_1,_2);
  75. // single tet, don't collapse
  76. if(Nun.size() == 4)
  77. {
  78. return false;
  79. }
  80. }
  81. }
  82. return true;
  83. }
  84. IGL_INLINE bool igl::edge_collapse_is_valid(
  85. std::vector<int> & Nsv,
  86. std::vector<int> & Ndv)
  87. {
  88. // Do we really need to check if edge is IGL_COLLAPSE_EDGE_NULL ?
  89. if(Nsv.size()<2 || Ndv.size()<2)
  90. {
  91. // Bogus data
  92. assert(false);
  93. return false;
  94. }
  95. // determine if the first two vertices are the same before reordering.
  96. // If they are and there are 3 each, then (I claim) this is an edge on a
  97. // single tet.
  98. const bool first_two_same = (Nsv[0] == Ndv[0]) && (Nsv[1] == Ndv[1]);
  99. if(Nsv.size() == 3 && Ndv.size() == 3 && first_two_same)
  100. {
  101. // single tet
  102. return false;
  103. }
  104. // https://stackoverflow.com/a/19483741/148668
  105. std::sort(Nsv.begin(), Nsv.end());
  106. std::sort(Ndv.begin(), Ndv.end());
  107. std::vector<int> Nint;
  108. std::set_intersection(
  109. Nsv.begin(), Nsv.end(), Ndv.begin(), Ndv.end(), std::back_inserter(Nint));
  110. // check if edge collapse is valid: intersection of vertex neighbors of s and
  111. // d should be exactly 2+(s,d) = 4
  112. // http://stackoverflow.com/a/27049418/148668
  113. if(Nint.size() != 2)
  114. {
  115. return false;
  116. }
  117. return true;
  118. }