orient_halfedges.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #include <test_common.h>
  2. #include <igl/orient_halfedges.h>
  3. #include <igl/is_border_vertex.h>
  4. #include <igl/edges.h>
  5. #include <igl/remove_unreferenced.h>
  6. #include <igl/triangle_triangle_adjacency.h>
  7. #include <igl/EPS.h>
  8. #include <vector>
  9. TEST_CASE("orient_halfedges: sanity checks", "[igl]")
  10. {
  11. const auto meshes = test_common::manifold_meshes();
  12. for(const auto& mesh : meshes) {
  13. Eigen::MatrixXd V;
  14. Eigen::MatrixXi F;
  15. igl::read_triangle_mesh(test_common::data_path(mesh), V, F);
  16. Eigen::MatrixXi I;
  17. igl::remove_unreferenced(Eigen::MatrixXd(V), Eigen::MatrixXi(F), V, F,
  18. I);
  19. Eigen::MatrixXi TT, TTi;
  20. igl::triangle_triangle_adjacency(F, TT, TTi);
  21. // Fix mis-match convention
  22. {
  23. Eigen::PermutationMatrix<3,3> perm(3);
  24. perm.indices() = Eigen::Vector3i(1,2,0);
  25. TT = (TT*perm).eval();
  26. TTi = (TTi*perm).eval();
  27. for(int i=0;i<TTi.rows();i++) {
  28. for(int j=0;j<TTi.cols();j++) {
  29. TTi(i,j)=TTi(i,j)==-1?-1:(TTi(i,j)+3-1)%3;
  30. }
  31. }
  32. }
  33. Eigen::MatrixXi E, oE;
  34. igl::orient_halfedges(F, E, oE);
  35. const int m = E.maxCoeff()+1;
  36. std::vector<bool> b(m);
  37. for(int i=0; i<F.rows(); ++i) {
  38. for(int j=0; j<3; ++j) {
  39. b[E(i,j)] = TT(i,j)<0;
  40. }
  41. }
  42. int nb = 0;
  43. for(int i=0; i<b.size(); ++i) {
  44. if(b[i]) {
  45. ++nb;
  46. }
  47. }
  48. //Perform a variety of sanity checks.
  49. //Correct number of edges
  50. Eigen::MatrixXi sanityEdges;
  51. igl::edges(F, sanityEdges);
  52. REQUIRE(m == sanityEdges.rows());
  53. //All border halfedges edges have orientation 1 only, all others
  54. // orientations 1 and -1, so oE must sum to the number of border
  55. // edges.
  56. REQUIRE(nb == oE.array().sum());
  57. //Every border halfedge has orientation 1. Every other edge appeats
  58. // with orientation 1 and -1.
  59. std::vector<int> appeared1(m,0), appearedm1(m,0);
  60. for(int i=0; i<F.rows(); ++i) {
  61. for(int j=0; j<3; ++j) {
  62. if(oE(i,j)==1) {
  63. ++appeared1[E(i,j)];
  64. } else if(oE(i,j)==-1) {
  65. ++appearedm1[E(i,j)];
  66. } else {
  67. REQUIRE(false); //Only 1 and -1 should occur.
  68. }
  69. }
  70. }
  71. for(int i=0; i<m; ++i) {
  72. REQUIRE(appeared1[i]==1);
  73. if(b[i]) {
  74. REQUIRE(appearedm1[i]==0);
  75. } else {
  76. REQUIRE(appearedm1[i]==1);
  77. }
  78. }
  79. //Two opposite halfedges always map to the same edge
  80. for(int i=0; i<F.rows(); ++i) {
  81. for(int j=0; j<3; ++j) {
  82. if(TT(i,j)>=0) {
  83. REQUIRE(E(i,j) == E(TT(i,j),TTi(i,j)));
  84. }
  85. }
  86. }
  87. }
  88. }