find_self_intersections.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #include "test_common.h"
  2. #include <igl/predicates/find_self_intersections.h>
  3. #include <igl/upsample.h>
  4. #include <igl/triangle_triangle_intersect.h>
  5. #include <igl/combine.h>
  6. #include <igl/sortrows.h>
  7. #include <igl/unique.h>
  8. #include <igl/matlab_format.h>
  9. #include <igl/PI.h>
  10. #include <iostream>
  11. #include <iomanip>
  12. TEST_CASE("find_self_intersections: cube", "[igl/predicates]")
  13. {
  14. Eigen::MatrixXd V;
  15. Eigen::MatrixXi F;
  16. igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F);
  17. Eigen::MatrixXi IF;
  18. Eigen::Array<bool,Eigen::Dynamic,1> CP;
  19. REQUIRE( !igl::predicates::find_self_intersections(V,F,true,IF,CP) );
  20. }
  21. TEST_CASE("find_self_intersections: cube-triangle", "[igl/predicates]")
  22. {
  23. Eigen::MatrixXd V;
  24. Eigen::MatrixXi F;
  25. igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F);
  26. auto dims=(V.colwise().maxCoeff()-V.colwise().minCoeff())*2;
  27. auto cz=(V.col(2).minCoeff()+V.col(2).maxCoeff())/2;
  28. // add a triangle intersecting cube
  29. Eigen::MatrixXd Vp(3,3);
  30. Vp << V.col(0).minCoeff()-dims(0), V.col(1).minCoeff()-dims(1), cz,
  31. V.col(0).minCoeff()-dims(0), V.col(1).maxCoeff()+dims(1)*3, cz,
  32. V.col(0).maxCoeff()+dims(0)*3, V.col(1).maxCoeff()-dims(1), cz;
  33. Eigen::MatrixXi Fp(1,3);
  34. Fp << 0,1,2;
  35. Eigen::MatrixXd V_;
  36. Eigen::MatrixXi F_;
  37. igl::combine<Eigen::MatrixXd,Eigen::MatrixXi>({V,Vp},{F,Fp}, V_,F_);
  38. Eigen::MatrixXi IF;
  39. Eigen::Array<bool,Eigen::Dynamic,1> CP;
  40. REQUIRE( igl::predicates::find_self_intersections(V_,F_,false,IF,CP) );
  41. {
  42. Eigen::VectorXi I;
  43. igl::unique(IF,I);
  44. // should have 9 triangles that are intersecting each other
  45. REQUIRE( I.size()==9 );
  46. // plane that we added intersects other triangles
  47. REQUIRE((IF.col(1).array()==(F_.rows()-1)).all() );
  48. }
  49. }
  50. TEST_CASE("find_self_intersections: rose", "[igl/predicates]")
  51. {
  52. Eigen::MatrixXd V(10,3);
  53. Eigen::MatrixXi F(9,3);
  54. for(int i=0;i<9;i++)
  55. {
  56. const double theta_i = 4.0*igl::PI*double(i)/9.0;
  57. V.row(i) << std::cos(theta_i), std::sin(theta_i), 1;
  58. F.row(i)<<9,i,(i+1)%9;
  59. }
  60. V.row(9) << 0,0,0;
  61. Eigen::MatrixXi IF;
  62. Eigen::Array<bool,Eigen::Dynamic,1> CP;
  63. REQUIRE( igl::predicates::find_self_intersections(V,F,false,IF,CP));
  64. Eigen::MatrixXi IF_gt(9,2);
  65. IF_gt<<
  66. 0,4,
  67. 0,5,
  68. 1,5,
  69. 1,6,
  70. 2,6,
  71. 2,7,
  72. 3,7,
  73. 3,8,
  74. 4,8;
  75. {
  76. Eigen::MatrixXi sIF;
  77. Eigen::VectorXi _;
  78. igl::sortrows(Eigen::MatrixXi(IF),true,sIF,_);
  79. test_common::assert_eq(IF_gt,sIF);
  80. }
  81. }
  82. TEST_CASE("find_self_intersections: shared-edge", "[igl/predicates]")
  83. {
  84. Eigen::MatrixXd V(4,3);
  85. V<<
  86. 0,0,0,
  87. 1,0,0,
  88. 0,1,0,
  89. -1,0,0;
  90. Eigen::MatrixXi F(2,3);
  91. F <<
  92. 0,1,2,
  93. 0,2,3;
  94. Eigen::MatrixXi IF;
  95. Eigen::Array<bool,Eigen::Dynamic,1> CP;
  96. REQUIRE(!igl::predicates::find_self_intersections(V,F,false,IF,CP));
  97. REQUIRE( IF.rows()==0 );
  98. REQUIRE( CP.rows()==0 );
  99. V.row(3) << 2.0,0,0;
  100. REQUIRE( igl::predicates::find_self_intersections(V,F,false,IF,CP));
  101. REQUIRE( IF.rows()==1 );
  102. REQUIRE( CP.rows()==1 );
  103. REQUIRE( CP(0) );
  104. }
  105. TEST_CASE("find_self_intersections: coplanar", "[igl/predicates]")
  106. {
  107. Eigen::MatrixXd V(6,3);
  108. V<<
  109. 0.30947001278400399,0.80785250663757346,0.47595100104808802,
  110. 0.299046009778976,0.79801350831985496,0.47843150794506101,
  111. 0.32418551295995701,0.79794725775718722,0.48203899711370451,
  112. 0.30425801128148999,0.80293300747871421,0.47719125449657451,
  113. 0.31897351145744302,0.79302775859832797,0.48327925056219101,
  114. 0.31376150995492902,0.78810825943946872,0.4845195040106775;
  115. Eigen::MatrixXi F(2,3);
  116. F<<
  117. 0,4,2,
  118. 1,5,3;
  119. Eigen::MatrixXi IF;
  120. Eigen::Array<bool,Eigen::Dynamic,1> CP;
  121. REQUIRE( !igl::predicates::find_self_intersections(V,F,false,IF,CP));
  122. REQUIRE( IF.rows()==0 );
  123. REQUIRE( CP.rows()==0 );
  124. }
  125. TEST_CASE("find_self_intersections: non-intersecting", "[igl/predicates]")
  126. {
  127. Eigen::MatrixXd V(6,3);
  128. V<<
  129. 0.39234799146652199,0.38443601131439198,0.44744500517845198,
  130. 0.38924700021743752,0.385637506842613,0.45762349665164948,
  131. 0.38700349628925301,0.38789276033639897,0.45634675025939975,
  132. 0.39079749584197976,0.38503675907850249,0.45253425091505073,
  133. 0.38769650459289529,0.38623825460672351,0.46271274238824822,
  134. 0.39279749989509577,0.37299175560474374,0.45553924888372399;
  135. Eigen::MatrixXi F(2,3);
  136. F<<
  137. 0,3,2,
  138. 1,5,4;
  139. Eigen::MatrixXi IF;
  140. Eigen::Array<bool,Eigen::Dynamic,1> CP;
  141. REQUIRE( !igl::predicates::find_self_intersections(V,F,false,IF,CP));
  142. REQUIRE( IF.rows()==0 );
  143. REQUIRE( CP.rows()==0 );
  144. }
  145. TEST_CASE("find_self_intersections: upsampled-knight", "[igl/predicates]")
  146. {
  147. Eigen::MatrixXd V;
  148. Eigen::MatrixXi F;
  149. igl::read_triangle_mesh(test_common::data_path("decimated-knight.obj"),V,F);
  150. Eigen::MatrixXi IF;
  151. Eigen::Array<bool,Eigen::Dynamic,1> CP;
  152. REQUIRE( !igl::predicates::find_self_intersections(V,F,false,IF,CP));
  153. REQUIRE( IF.rows()==0 );
  154. REQUIRE( CP.rows()==0 );
  155. igl::upsample(Eigen::MatrixXd(V),Eigen::MatrixXi(F),V,F);
  156. REQUIRE( !igl::predicates::find_self_intersections(V,F,false,IF,CP));
  157. REQUIRE( IF.rows()==0 );
  158. REQUIRE( CP.rows()==0 );
  159. igl::upsample(Eigen::MatrixXd(V),Eigen::MatrixXi(F),V,F);
  160. REQUIRE( !igl::predicates::find_self_intersections(V,F,false,IF,CP));
  161. REQUIRE( IF.rows()==0 );
  162. REQUIRE( CP.rows()==0 );
  163. }
  164. TEST_CASE("find_self_intersections: extract", "[igl/predicates]")
  165. {
  166. Eigen::MatrixXd V(4+3,3);
  167. V << 0,0,0,
  168. 1,0,0,
  169. 1,1,0,
  170. 0,1,0,
  171. 1,0,1,
  172. 0,1,1,
  173. 0.5,0.5,-1;
  174. Eigen::MatrixXi F(3,3);
  175. F << 0,1,2,
  176. 0,2,3,
  177. 4,5,6;
  178. Eigen::MatrixXi IF,EE; Eigen::MatrixXd EV;
  179. Eigen::Array<bool,Eigen::Dynamic,1> CP;
  180. bool found = igl::predicates::find_self_intersections(V,F,false,IF,CP);
  181. igl::triangle_triangle_intersect(V,F,IF,EV,EE);
  182. REQUIRE( (CP==false).all() );
  183. REQUIRE( found );
  184. REQUIRE( IF.rows() == 2);
  185. Eigen::MatrixXi IF_gt(2,2);
  186. IF_gt <<
  187. 0,2,
  188. 1,2;
  189. test_common::assert_near_rows(IF,IF_gt,0);
  190. Eigen::MatrixXd EV_gt(3,3);
  191. EV_gt<<
  192. 0.5 ,0.5,0,
  193. 0.25,0.75,0,
  194. 0.75,0.25,0;
  195. test_common::assert_near_rows(EV,EV_gt,0);
  196. REQUIRE( EE.rows() == 2);
  197. }