edge_exists_near.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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. // starting with the (2) faces incident on e, consider all faces
  29. // incident on edges containing either a or b.
  30. //
  31. // face_queue Queue containing faces incident on exactly one of a/b
  32. // Using a vector seems mildly faster
  33. assert(EMAP.size()%3 == 0);
  34. const Index num_faces = EMAP.size()/3;
  35. const Index f1 = uE2E[uei][0]%num_faces;
  36. const Index f2 = uE2E[uei][1]%num_faces;
  37. // map is faster than unordered_map here, and vector + brute force
  38. // is_member check is even faster
  39. face_queue.push_back(f1);
  40. pushed.push_back(f1);
  41. face_queue.push_back(f2);
  42. pushed.push_back(f2);
  43. while(!face_queue.empty())
  44. {
  45. const Index f = face_queue.back();
  46. face_queue.pop_back();
  47. // consider each edge of this face
  48. for(int c = 0;c<3;c++)
  49. {
  50. // Unique edge id
  51. const Index uec = EMAP(c*num_faces+f);
  52. const Index s = uE(uec,0);
  53. const Index d = uE(uec,1);
  54. const bool ona = s == a || d == a;
  55. const bool onb = s == b || d == b;
  56. // Is this the edge we're looking for?
  57. if(ona && onb)
  58. {
  59. return true;
  60. }
  61. // not incident on either?
  62. if(!ona && !onb)
  63. {
  64. continue;
  65. }
  66. // loop over all incident half-edges
  67. for(const auto & he : uE2E[uec])
  68. {
  69. // face of this he
  70. const Index fhe = he%num_faces;
  71. bool already_pushed = false;
  72. for(const auto & fp : pushed)
  73. {
  74. if(fp == fhe)
  75. {
  76. already_pushed = true;
  77. break;
  78. }
  79. }
  80. if(!already_pushed)
  81. {
  82. pushed.push_back(fhe);
  83. face_queue.push_back(fhe);
  84. }
  85. }
  86. }
  87. }
  88. return false;
  89. }
  90. #ifdef IGL_STATIC_LIBRARY
  91. // Explicit template instantiation
  92. // generated by autoexplicit.sh
  93. 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&);
  94. #endif