boundary_vertices_sorted.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 Stefan Brugger <stefanbrugger@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 "boundary_vertices_sorted.h"
  9. #include "igl/tt.h"
  10. #include "igl/vf.h"
  11. IGL_INLINE void igl::boundary_vertices_sorted(
  12. const Eigen::MatrixXd& V,
  13. const Eigen::MatrixXi& F,
  14. Eigen::VectorXi& b)
  15. {
  16. std::vector<int> bnd;
  17. bnd.clear();
  18. std::vector<bool> isVisited(V.rows(),false);
  19. Eigen::MatrixXi TT,TTi;
  20. std::vector<std::vector<int> > VF, VFi;
  21. igl::tt(V,F,TT,TTi);
  22. igl::vf(V,F,VF,VFi);
  23. // Extract one boundary edge
  24. bool done = false;
  25. for (int i = 0; i < TT.rows() && !done; i++)
  26. {
  27. for (int j = 0; j < TT.cols(); j++)
  28. {
  29. if (TT(i,j) < 0)
  30. {
  31. int idx1, idx2;
  32. idx1 = F(i,j);
  33. idx2 = F(i,(j+1) % F.cols());
  34. bnd.push_back(idx1);
  35. bnd.push_back(idx2);
  36. isVisited[idx1] = true;
  37. isVisited[idx2] = true;
  38. done = true;
  39. break;
  40. }
  41. }
  42. }
  43. // Traverse boundary
  44. while(1)
  45. {
  46. bool changed = false;
  47. int lastV;
  48. lastV = bnd[bnd.size()-1];
  49. for (int i = 0; i < VF[lastV].size(); i++)
  50. {
  51. int curr_neighbor = VF[lastV][i];
  52. if (TT.row(curr_neighbor).minCoeff() < 0.) // Face contains boundary edge
  53. {
  54. int idx_lastV_in_face;
  55. if (F(curr_neighbor,0) == lastV) idx_lastV_in_face = 0;
  56. if (F(curr_neighbor,1) == lastV) idx_lastV_in_face = 1;
  57. if (F(curr_neighbor,2) == lastV) idx_lastV_in_face = 2;
  58. int idx_prev = (idx_lastV_in_face + F.cols()-1) % F.cols();
  59. int idx_next = (idx_lastV_in_face + 1) % F.cols();
  60. bool isPrevVisited = isVisited[F(curr_neighbor,idx_prev)];
  61. bool isNextVisited = isVisited[F(curr_neighbor,idx_next)];
  62. bool gotBndEdge = false;
  63. int next_bnd_vertex;
  64. if (!isNextVisited && TT(curr_neighbor,idx_lastV_in_face) < 0)
  65. {
  66. next_bnd_vertex = idx_next;
  67. gotBndEdge = true;
  68. }
  69. else if (!isPrevVisited && TT(curr_neighbor,(idx_lastV_in_face+2) % F.cols()) < 0)
  70. {
  71. next_bnd_vertex = idx_prev;
  72. gotBndEdge = true;
  73. }
  74. if (gotBndEdge)
  75. {
  76. changed = true;
  77. bnd.push_back(F(curr_neighbor,next_bnd_vertex));
  78. isVisited[F(curr_neighbor,next_bnd_vertex)] = true;
  79. break;
  80. }
  81. }
  82. }
  83. if (!changed)
  84. break;
  85. }
  86. b.resize(bnd.size());
  87. for(unsigned i=0;i<bnd.size();++i)
  88. b(i) = bnd[i];
  89. }