edge_exists_near.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2018 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_exists_near.h"
  9. template <
  10. typename DeriveduE,
  11. typename DerivedEMAP,
  12. typename uE2EType,
  13. typename Index>
  14. IGL_INLINE bool igl::edge_exists_near(
  15. const Eigen::MatrixBase<DeriveduE> & uE,
  16. const Eigen::MatrixBase<DerivedEMAP> & EMAP,
  17. const std::vector<std::vector< uE2EType> > & uE2E,
  18. const Index & a,
  19. const Index & b,
  20. const Index & uei)
  21. {
  22. std::vector<Index> face_queue;
  23. face_queue.reserve(32);
  24. std::vector<Index> pushed;
  25. // 32 is faster than 8
  26. pushed.reserve(32);
  27. assert(a!=b);
  28. // Not handling case where (a,b) is edge on face incident on uei
  29. // since this can't happen for edge-flipping.
  30. assert(a!=uE(uei,0));
  31. assert(a!=uE(uei,1));
  32. assert(b!=uE(uei,0));
  33. assert(b!=uE(uei,1));
  34. // starting with the (2) faces incident on e, consider all faces
  35. // incident on edges containing either a or b.
  36. //
  37. // face_queue Queue containing faces incident on exactly one of a/b
  38. // Using a vector seems mildly faster
  39. assert(EMAP.size()%3 == 0);
  40. const Index num_faces = EMAP.size()/3;
  41. const Index f1 = uE2E[uei][0]%num_faces;
  42. const Index f2 = uE2E[uei][1]%num_faces;
  43. // map is faster than unordered_map here, and vector + brute force
  44. // is_member check is even faster
  45. face_queue.push_back(f1);
  46. pushed.push_back(f1);
  47. face_queue.push_back(f2);
  48. pushed.push_back(f2);
  49. while(!face_queue.empty())
  50. {
  51. const Index f = face_queue.back();
  52. face_queue.pop_back();
  53. // consider each edge of this face
  54. for(int c = 0;c<3;c++)
  55. {
  56. // Unique edge id
  57. const Index uec = EMAP(c*num_faces+f);
  58. const Index s = uE(uec,0);
  59. const Index d = uE(uec,1);
  60. const bool ona = s == a || d == a;
  61. const bool onb = s == b || d == b;
  62. // Is this the edge we're looking for?
  63. if(ona && onb)
  64. {
  65. return true;
  66. }
  67. // not incident on either?
  68. if(!ona && !onb)
  69. {
  70. continue;
  71. }
  72. // loop over all incident half-edges
  73. for(const auto & he : uE2E[uec])
  74. {
  75. // face of this he
  76. const Index fhe = he%num_faces;
  77. bool already_pushed = false;
  78. for(const auto & fp : pushed)
  79. {
  80. if(fp == fhe)
  81. {
  82. already_pushed = true;
  83. break;
  84. }
  85. }
  86. if(!already_pushed)
  87. {
  88. pushed.push_back(fhe);
  89. face_queue.push_back(fhe);
  90. }
  91. }
  92. }
  93. }
  94. return false;
  95. }
  96. #ifdef IGL_STATIC_LIBRARY
  97. // Explicit template instantiation
  98. // generated by autoexplicit.sh
  99. template bool igl::edge_exists_near<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, int const&, int const&, int const&);
  100. #endif