circulation.cpp 3.3 KB

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