edge_collapse_is_valid.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 Alec Jacobson <alecjacobson@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 "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. using namespace igl;
  26. // For consistency with collapse_edge.cpp, let's determine edge flipness
  27. // (though not needed to check validity)
  28. const int eflip = E(e,0)>E(e,1);
  29. // source and destination
  30. const int s = eflip?E(e,1):E(e,0);
  31. const int d = eflip?E(e,0):E(e,1);
  32. if(s == IGL_COLLAPSE_EDGE_NULL && d==IGL_COLLAPSE_EDGE_NULL)
  33. {
  34. return false;
  35. }
  36. // check if edge collapse is valid: intersection of vertex neighbors of s and
  37. // d should be exactly 2+(s,d) = 4
  38. // http://stackoverflow.com/a/27049418/148668
  39. {
  40. // all vertex neighbors around edge, including the two vertices of the edge
  41. const auto neighbors = [](
  42. const int e,
  43. const bool ccw,
  44. const Eigen::MatrixXi & F,
  45. const Eigen::MatrixXi & E,
  46. const Eigen::VectorXi & EMAP,
  47. const Eigen::MatrixXi & EF,
  48. const Eigen::MatrixXi & EI)
  49. {
  50. vector<int> N,uN;
  51. vector<int> V2Fe = circulation(e, ccw,F,E,EMAP,EF,EI);
  52. for(auto f : V2Fe)
  53. {
  54. N.push_back(F(f,0));
  55. N.push_back(F(f,1));
  56. N.push_back(F(f,2));
  57. }
  58. vector<size_t> _1,_2;
  59. igl::unique(N,uN,_1,_2);
  60. VectorXi uNm;
  61. list_to_matrix(uN,uNm);
  62. return uNm;
  63. };
  64. VectorXi Ns = neighbors(e, eflip,F,E,EMAP,EF,EI);
  65. VectorXi Nd = neighbors(e,!eflip,F,E,EMAP,EF,EI);
  66. VectorXi Nint = igl::intersect(Ns,Nd);
  67. if(Nint.size() != 4)
  68. {
  69. return false;
  70. }
  71. if(Ns.size() == 4 && Nd.size() == 4)
  72. {
  73. VectorXi NsNd(8);
  74. NsNd<<Ns,Nd;
  75. VectorXi Nun,_1,_2;
  76. igl::unique(NsNd,Nun,_1,_2);
  77. // single tet, don't collapse
  78. if(Nun.size() == 4)
  79. {
  80. return false;
  81. }
  82. }
  83. }
  84. return true;
  85. }