is_boundary_edge.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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 "is_boundary_edge.h"
  9. #include "unique_rows.h"
  10. #include "sort.h"
  11. template <
  12. typename DerivedF,
  13. typename DerivedE,
  14. typename DerivedB>
  15. void igl::is_boundary_edge(
  16. const Eigen::MatrixBase<DerivedE> & E,
  17. const Eigen::MatrixBase<DerivedF> & F,
  18. Eigen::PlainObjectBase<DerivedB> & B)
  19. {
  20. // Should be triangles
  21. assert(F.cols() == 3);
  22. // Should be edges
  23. assert(E.cols() == 2);
  24. // number of faces
  25. const int m = F.rows();
  26. // Collect all directed edges after E
  27. Eigen::MatrixXi EallE(E.rows()+3*m,2);
  28. EallE.block(0,0,E.rows(),E.cols()) = E;
  29. for(int e = 0;e<3;e++)
  30. {
  31. for(int f = 0;f<m;f++)
  32. {
  33. for(int c = 0;c<2;c++)
  34. {
  35. // 12 20 01
  36. EallE(E.rows()+m*e+f,c) = F(f,(c+1+e)%3);
  37. }
  38. }
  39. }
  40. // sort directed edges into undirected edges
  41. Eigen::MatrixXi sorted_EallE;
  42. {
  43. Eigen::MatrixXi _;
  44. sort(EallE,2,true,sorted_EallE,_);
  45. }
  46. // Determine unique undirected edges E and map to directed edges EMAP
  47. Eigen::MatrixXi uE;
  48. Eigen::VectorXi EMAP;
  49. {
  50. Eigen::VectorXi _;
  51. unique_rows(sorted_EallE,uE,_,EMAP);
  52. }
  53. // Counts of occurrences
  54. Eigen::VectorXi N = Eigen::VectorXi::Zero(uE.rows());
  55. for(int e = 0;e<EMAP.rows();e++)
  56. {
  57. N(EMAP(e))++;
  58. }
  59. B.resize(E.rows());
  60. // Look of occurrences of 2: one for original and another for boundary
  61. for(int e = 0;e<E.rows();e++)
  62. {
  63. B(e) = (N(EMAP(e)) == 2);
  64. }
  65. }
  66. template <
  67. typename DerivedF,
  68. typename DerivedE,
  69. typename DerivedB,
  70. typename DerivedEMAP>
  71. void igl::is_boundary_edge(
  72. const Eigen::MatrixBase<DerivedF> & F,
  73. Eigen::PlainObjectBase<DerivedB> & B,
  74. Eigen::PlainObjectBase<DerivedE> & E,
  75. Eigen::PlainObjectBase<DerivedEMAP> & EMAP)
  76. {
  77. // B and EMAP need to have RowsAtCompileTime == 1 or ColsAtCompileTime == 1
  78. static_assert(
  79. (DerivedB::RowsAtCompileTime == 1 || DerivedB::ColsAtCompileTime == 1) &&
  80. (DerivedEMAP::RowsAtCompileTime == 1 || DerivedEMAP::ColsAtCompileTime == 1),
  81. "B and EMAP need to have RowsAtCompileTime == 1 or ColsAtCompileTime == 1");
  82. // Should be triangles
  83. assert(F.cols() == 3);
  84. // number of faces
  85. const int m = F.rows();
  86. // Collect all directed edges after E
  87. Eigen::MatrixXi allE(3*m,2);
  88. for(int e = 0;e<3;e++)
  89. {
  90. for(int f = 0;f<m;f++)
  91. {
  92. for(int c = 0;c<2;c++)
  93. {
  94. // 12 20 01
  95. allE(m*e+f,c) = F(f,(c+1+e)%3);
  96. }
  97. }
  98. }
  99. // sort directed edges into undirected edges
  100. Eigen::MatrixXi sorted_allE;
  101. {
  102. Eigen::MatrixXi _;
  103. sort(allE,2,true,sorted_allE,_);
  104. }
  105. // Determine unique undirected edges E and map to directed edges EMAP
  106. {
  107. Eigen::VectorXi _;
  108. unique_rows(sorted_allE,E,_,EMAP);
  109. }
  110. // Counts of occurrences
  111. Eigen::VectorXi N = Eigen::VectorXi::Zero(E.rows());
  112. for(int e = 0;e<EMAP.rows();e++)
  113. {
  114. N(EMAP(e))++;
  115. }
  116. B.resize(E.rows());
  117. // Look of occurrences of 1
  118. for(int e = 0;e<E.rows();e++)
  119. {
  120. B(e) = N(e) == 1;
  121. }
  122. }
  123. #ifdef IGL_STATIC_LIBRARY
  124. // Explicit template instantiation
  125. // generated by autoexplicit.sh
  126. template void igl::is_boundary_edge<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Array<bool, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Array<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  127. template void igl::is_boundary_edge<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(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<bool, -1, 1, 0, -1, 1> >&);
  128. template void igl::is_boundary_edge<Eigen::Matrix<unsigned int, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<unsigned int, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
  129. template void igl::is_boundary_edge<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  130. template void igl::is_boundary_edge<Eigen::Matrix<unsigned int, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<unsigned int, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  131. #endif