orient_halfedges.cpp 2.5 KB

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