edge_collapse_is_valid.cpp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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. // 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::MatrixXi & E,
  45. const Eigen::VectorXi & EMAP,
  46. const Eigen::MatrixXi & EF,
  47. const Eigen::MatrixXi & EI)
  48. {
  49. vector<int> N,uN;
  50. vector<int> V2Fe = circulation(e, ccw,F,E,EMAP,EF,EI);
  51. for(auto f : V2Fe)
  52. {
  53. N.push_back(F(f,0));
  54. N.push_back(F(f,1));
  55. N.push_back(F(f,2));
  56. }
  57. vector<size_t> _1,_2;
  58. igl::unique(N,uN,_1,_2);
  59. VectorXi uNm;
  60. list_to_matrix(uN,uNm);
  61. return uNm;
  62. };
  63. VectorXi Ns = neighbors(e, eflip,F,E,EMAP,EF,EI);
  64. VectorXi Nd = neighbors(e,!eflip,F,E,EMAP,EF,EI);
  65. VectorXi Nint = igl::intersect(Ns,Nd);
  66. if(Nint.size() != 4)
  67. {
  68. return false;
  69. }
  70. if(Ns.size() == 4 && Nd.size() == 4)
  71. {
  72. VectorXi NsNd(8);
  73. NsNd<<Ns,Nd;
  74. VectorXi Nun,_1,_2;
  75. igl::unique(NsNd,Nun,_1,_2);
  76. // single tet, don't collapse
  77. if(Nun.size() == 4)
  78. {
  79. return false;
  80. }
  81. }
  82. }
  83. return true;
  84. }