refine.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #include <test_common.h>
  2. #include <igl/triangle/refine.h>
  3. #include <igl/triangle/triangulate.h>
  4. #include <igl/matlab_format.h>
  5. #include <igl/find.h>
  6. #include <igl/barycenter.h>
  7. #include <igl/winding_number.h>
  8. #include <igl/doublearea.h>
  9. #include <iostream>
  10. TEST_CASE("refine", "[igl][triangle]") {
  11. Eigen::MatrixXd V(3,2);
  12. V <<
  13. 0,0,
  14. 1,0,
  15. 0,1;
  16. Eigen::MatrixXi F(1,3);
  17. F<<0,1,2;
  18. std::string flags = "a0.0625Q";
  19. Eigen::MatrixXd V2;
  20. Eigen::MatrixXi F2;
  21. igl::triangle::refine(V,F,flags,V2,F2);
  22. REQUIRE(F2.rows()>1);
  23. Eigen::VectorXd A2;
  24. igl::doublearea(V2,F2,A2);
  25. REQUIRE((A2.array()<2*0.0625).all());
  26. }
  27. TEST_CASE("refine-inner-pinch", "[igl][triangle]") {
  28. // Mesh an outline that looks like:
  29. //
  30. // o-----------------o
  31. // | |
  32. // | o o |
  33. // | |\ /| |
  34. // | | \ / | |
  35. // | | \ / | |
  36. // | | \ / | |
  37. // | | o | |
  38. // | o---------o |
  39. // | |
  40. // o-----------------o
  41. //
  42. // If we mesh the whole convex hull and then remove the inner cavity we'll get
  43. // over-refinement near the sharp corner.
  44. //
  45. // We could tell triangle a point inside this cavity but that's not often easy
  46. // to do robustly/for broken input. Instead we can use a trivial mesh of the
  47. // whole domain, remove the cavity with the winding number and then refine
  48. // what's left.
  49. //
  50. Eigen::MatrixXd V(9,2);
  51. V <<
  52. 0,0,
  53. 3,0,
  54. 3,3,
  55. 0,3,
  56. 1,1,
  57. 2,1,
  58. 2,2,
  59. 1.5,1.00000001,
  60. 1,2;
  61. Eigen::MatrixXi E(9,2);
  62. E <<
  63. 0,1,
  64. 1,2,
  65. 2,3,
  66. 3,0,
  67. 8,7,
  68. 7,6,
  69. 6,5,
  70. 5,4,
  71. 4,8;
  72. Eigen::MatrixXd H(0,2);
  73. const auto filter = [&V,&E](
  74. const Eigen::MatrixXd & Vc,
  75. Eigen::MatrixXi & Fc)
  76. {
  77. Eigen::MatrixXd BC;
  78. igl::barycenter(Vc,Fc,BC);
  79. Eigen::VectorXd W;
  80. // This is sadly O(|E| ⋅ |BC|) for 2D inputs.
  81. igl::winding_number(V,E,BC,W);
  82. auto keep = igl::find((W.array().abs() > 0.5).eval());
  83. Fc = Fc(keep,Eigen::all).eval();
  84. };
  85. Eigen::MatrixXd Vq;
  86. Eigen::MatrixXi Fq;
  87. igl::triangle::triangulate(V,E,H,"cq33a0.0625Q",Vq,Fq);
  88. filter(Vq,Fq);
  89. //std::cout<<igl::matlab_format(Vq,"Vq")<<std::endl;
  90. //std::cout<<igl::matlab_format_index(Fq,"Fq")<<std::endl;
  91. Eigen::MatrixXd Vc;
  92. Eigen::MatrixXi Fc;
  93. igl::triangle::triangulate(V,E,H,"cQ",Vc,Fc);
  94. REQUIRE(V.rows() == Vc.rows());
  95. REQUIRE(Fc.rows() == 12);
  96. filter(Vc,Fc);
  97. REQUIRE(Fc.rows() == 9);
  98. //std::cout<<igl::matlab_format(Vc,"Vc")<<std::endl;
  99. //std::cout<<igl::matlab_format_index(Fc,"Fc")<<std::endl;
  100. Eigen::MatrixXd Vr;
  101. Eigen::MatrixXi Fr;
  102. igl::triangle::refine(Vc,Fc,"q33a0.0625Q",Vr,Fr);
  103. //std::cout<<igl::matlab_format(Vr,"Vr")<<std::endl;
  104. //std::cout<<igl::matlab_format_index(Fr,"Fr")<<std::endl;
  105. REQUIRE(Fr.rows() > Fc.rows());
  106. REQUIRE(Fr.rows() < 0.15 * Fq.rows());
  107. }