circulation.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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 "circulation.h"
  9. #include "list_to_matrix.h"
  10. #include <cassert>
  11. template <typename DerivedEMAP, typename DerivedEF, typename DerivedEI>
  12. IGL_INLINE std::vector<int> igl::circulation(
  13. const int e,
  14. const bool ccw,
  15. const Eigen::MatrixBase<DerivedEMAP> & EMAP,
  16. const Eigen::MatrixBase<DerivedEF> & EF,
  17. const Eigen::MatrixBase<DerivedEI> & EI)
  18. {
  19. // prepare output
  20. std::vector<int> N;
  21. N.reserve(6);
  22. const int m = EMAP.size()/3;
  23. assert(m*3 == EMAP.size());
  24. const auto & step = [&](
  25. const int e,
  26. const int ff,
  27. int & ne,
  28. int & nf)
  29. {
  30. assert((EF(e,1) == ff || EF(e,0) == ff) && "e should touch ff");
  31. //const int fside = EF(e,1)==ff?1:0;
  32. const int nside = EF(e,0)==ff?1:0;
  33. const int nv = EI(e,nside);
  34. // get next face
  35. nf = EF(e,nside);
  36. // get next edge
  37. const int dir = ccw?-1:1;
  38. ne = EMAP(nf+m*((nv+dir+3)%3));
  39. };
  40. // Always start with first face (ccw in step will be sure to turn right
  41. // direction)
  42. const int f0 = EF(e,0);
  43. int fi = f0;
  44. int ei = e;
  45. while(true)
  46. {
  47. step(ei,fi,ei,fi);
  48. N.push_back(fi);
  49. // back to start?
  50. if(fi == f0)
  51. {
  52. assert(ei == e);
  53. break;
  54. }
  55. }
  56. return N;
  57. }
  58. template <typename DerivedEMAP, typename DerivedEF, typename DerivedEI, typename DerivedvN>
  59. IGL_INLINE void igl::circulation(
  60. const int e,
  61. const bool ccw,
  62. const Eigen::MatrixBase<DerivedEMAP> & EMAP,
  63. const Eigen::MatrixBase<DerivedEF> & EF,
  64. const Eigen::MatrixBase<DerivedEI> & EI,
  65. Eigen::PlainObjectBase<DerivedvN> & vN)
  66. {
  67. std::vector<int> N = circulation(e,ccw,EMAP,EF,EI);
  68. igl::list_to_matrix(N,vN);
  69. }
  70. template <typename DerivedF, typename DerivedEMAP, typename DerivedEF, typename DerivedEI, typename Nv_type>
  71. IGL_INLINE void igl::circulation(
  72. const int e,
  73. const bool ccw,
  74. const Eigen::MatrixBase<DerivedF> & F,
  75. const Eigen::MatrixBase<DerivedEMAP> & EMAP,
  76. const Eigen::MatrixBase<DerivedEF> & EF,
  77. const Eigen::MatrixBase<DerivedEI> & EI,
  78. /*std::vector<int> & Ne,*/
  79. std::vector<Nv_type> & Nv,
  80. std::vector<Nv_type> & Nf)
  81. {
  82. //
  83. // for e --> (bf) and ccw=true
  84. //
  85. // c---d
  86. // ╱ ╲ ╱ ╲
  87. // a---b-e-f
  88. // ╲ ╱ ╲ ╱
  89. // g---h
  90. //
  91. // // (might start with {bhf} depending on edge)
  92. // Ne = […] -> [fd db dc cb ca ab ag gb gh hb hf fb]
  93. // {upto cylic order}
  94. // Nf = […] -> [{bfd}, {bdc}, {bca}, {bag}, {bgh}, {bhf}]
  95. // Nv = [d c a g h f]
  96. //
  97. // prepare output
  98. //Ne.clear();Ne.reserve(2*10);
  99. Nv.clear();Nv.reserve(10);
  100. Nf.clear();Nf.reserve(10);
  101. const int m = EMAP.size()/3;
  102. assert(m*3 == EMAP.size());
  103. const auto & step = [&](
  104. const int e,
  105. const int ff,
  106. int & ne,
  107. //int & re,
  108. int & rv,
  109. int & nf)
  110. {
  111. assert((EF(e,1) == ff || EF(e,0) == ff) && "e should touch ff");
  112. //const int fside = EF(e,1)==ff?1:0;
  113. const int nside = EF(e,0)==ff?1:0;
  114. const int nv = EI(e,nside);
  115. // get next face
  116. nf = EF(e,nside);
  117. // get next edge
  118. const int dir = ccw?-1:1;
  119. rv = F(nf,nv);
  120. ne = EMAP(nf+m*((nv+dir+3)%3));
  121. //re = EMAP(nf+m*((nv+2*dir+3)%3));
  122. };
  123. // Always start with first face (ccw in step will be sure to turn right
  124. // direction)
  125. const int f0 = EF(e,0);
  126. int fi = f0;
  127. int ei = e;
  128. while(true)
  129. {
  130. int rv;
  131. step(ei,fi,ei/*,re*/,rv,fi);
  132. Nf.push_back(fi);
  133. //Ne.push_back(re);
  134. //Ne.push_back(ei);
  135. Nv.push_back(rv);
  136. // back to start?
  137. if(fi == f0)
  138. {
  139. assert(ei == e);
  140. break;
  141. }
  142. }
  143. }
  144. #ifdef IGL_STATIC_LIBRARY
  145. // Explicit template specialization
  146. template std::vector<int, std::allocator<int>> igl::circulation<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(int, bool, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&);
  147. template void igl::circulation<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>>(int, bool, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&);
  148. template void igl::circulation<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, int>(int, bool, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, std::vector<int, std::allocator<int>>&, std::vector<int, std::allocator<int>>&);
  149. #endif