split_nonmanifold.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. #include <test_common.h>
  2. #include <igl/split_nonmanifold.h>
  3. #include <igl/facet_components.h>
  4. #include <igl/is_edge_manifold.h>
  5. #include <igl/is_vertex_manifold.h>
  6. #include <igl/triangulated_grid.h>
  7. #include <igl/remove_duplicate_vertices.h>
  8. #include <igl/matlab_format.h>
  9. #include <igl/writePLY.h>
  10. #include <iostream>
  11. void check_same_but_manifold(
  12. const Eigen::MatrixXi & F,
  13. const Eigen::MatrixXi & SF,
  14. const Eigen::VectorXi & I)
  15. {
  16. // Check that new mesh has no non-manifold edges
  17. REQUIRE(igl::is_edge_manifold(SF));
  18. // Check that new mesh has no non-manifold vertices
  19. REQUIRE(igl::is_vertex_manifold(SF));
  20. // Check the new mesh references original vertex information
  21. Eigen::MatrixXi ISF(SF.rows(),SF.cols());
  22. for(int i = 0;i<ISF.rows();i++)
  23. {
  24. for(int j = 0;j<ISF.cols();j++)
  25. {
  26. ISF(i,j) = I(SF(i,j));
  27. }
  28. }
  29. test_common::assert_eq(F,ISF);
  30. }
  31. TEST_CASE("split_nonmanifold: edge-fan", "[igl]")
  32. {
  33. using namespace igl;
  34. Eigen::MatrixXi F(5,3);
  35. F<<0,1,3,
  36. 0,3,2,
  37. 0,4,3,
  38. 0,3,5,
  39. 0,3,6;
  40. Eigen::MatrixXd V(7,3);
  41. V << 0,0,0,
  42. 1,0,0,
  43. -1,0,0,
  44. 0,1,0,
  45. 0,0,1,
  46. 0,0,-1,
  47. 1,0,1;
  48. igl::writePLY("edge-fan.ply",V,F);
  49. Eigen::MatrixXd SV;
  50. Eigen::MatrixXi SF;
  51. Eigen::VectorXi SVI;
  52. igl::split_nonmanifold(F,SF,SVI);
  53. check_same_but_manifold(F,SF,SVI);
  54. }
  55. TEST_CASE("split_nonmanifold: vertex-boundary", "[igl]")
  56. {
  57. using namespace igl;
  58. Eigen::MatrixXd V(5,2);
  59. V << 0,0,
  60. 1,0,
  61. 0,1,
  62. 2,0,
  63. 1,1;
  64. Eigen::MatrixXi F(2,3);
  65. F<<0,1,2,
  66. 1,3,4;
  67. {
  68. Eigen::MatrixXd V3(V.rows(),3);
  69. V3<<V,Eigen::MatrixXd::Zero(V.rows(),1);
  70. igl::writePLY("vertex-boundary.ply",V3,F);
  71. }
  72. Eigen::MatrixXi SF;
  73. Eigen::VectorXi SVI;
  74. igl::split_nonmanifold(F,SF,SVI);
  75. REQUIRE(SVI.rows() == 6);
  76. check_same_but_manifold(F,SF,SVI);
  77. }
  78. TEST_CASE("split_nonmanifold: edge-disk-flap", "[igl]")
  79. {
  80. using namespace igl;
  81. Eigen::MatrixXi F(5,3);
  82. F<<
  83. 0,1,2,
  84. 0,2,3,
  85. 0,3,4,
  86. 0,4,1,
  87. 0,5,1;
  88. Eigen::MatrixXd V(6,3);
  89. V<<
  90. 0,0,0,
  91. 1,0,0,
  92. 0,1,0,
  93. -1,0,0,
  94. 0,-1,0,
  95. 0,0,1;
  96. igl::writePLY("edge-disk-flap.ply",V,F);
  97. Eigen::MatrixXi SF;
  98. Eigen::VectorXi SVI;
  99. igl::split_nonmanifold(F,SF,SVI);
  100. check_same_but_manifold(F,SF,SVI);
  101. }
  102. TEST_CASE("split_nonmanifold: edge-disk-tent", "[igl]")
  103. {
  104. using namespace igl;
  105. Eigen::MatrixXi F(5,3);
  106. F<<
  107. 0,1,2,
  108. 0,2,3,
  109. 0,3,1,
  110. 0,4,1,
  111. 1,4,3;
  112. Eigen::MatrixXd V(5,3);
  113. V<<
  114. 0,0,0,
  115. 1,0,0,
  116. -1,1,0,
  117. 0,-1,0,
  118. 0,0,1;
  119. igl::writePLY("edge-disk-tent.ply",V,F);
  120. Eigen::MatrixXi SF;
  121. Eigen::VectorXi SVI;
  122. igl::split_nonmanifold(F,SF,SVI);
  123. check_same_but_manifold(F,SF,SVI);
  124. }
  125. TEST_CASE("split_nonmanifold: vertex-kiss", "[igl]")
  126. {
  127. using namespace igl;
  128. Eigen::MatrixXi F(6,3);
  129. F<<
  130. 0,1,3,
  131. 1,2,3,
  132. 2,0,3,
  133. 4,5,3,
  134. 5,6,3,
  135. 6,4,3;
  136. Eigen::MatrixXd V(7,3);
  137. V<<
  138. 0,0,0,
  139. 1,0,0,
  140. 0,1,0,
  141. 0,0,1,
  142. 0,0,2,
  143. 1,0,2,
  144. 0,1,2;
  145. igl::writePLY("vertex-kiss.ply",V,F);
  146. Eigen::MatrixXi SF;
  147. Eigen::VectorXi SVI;
  148. igl::split_nonmanifold(F,SF,SVI);
  149. check_same_but_manifold(F,SF,SVI);
  150. }
  151. TEST_CASE("split_nonmanifold: non-orientable", "[igl]")
  152. {
  153. using namespace igl;
  154. Eigen::MatrixXi F(6,3);
  155. F<<
  156. 0,2,1,
  157. 2,3,1,
  158. 2,4,3,
  159. 4,5,3,
  160. 4,1,5,
  161. 1,0,5;
  162. Eigen::MatrixXd V(6,3);
  163. V<<
  164. 6, 0, 0,
  165. 4, 0, 0,
  166. -3, 5, 0,
  167. -2, 4, 0,
  168. -2,-4, 1,
  169. -3,-5,-1;
  170. igl::writePLY("non-orientable.ply",V,F);
  171. Eigen::MatrixXi SF;
  172. Eigen::VectorXi SVI;
  173. igl::split_nonmanifold(F,SF,SVI);
  174. check_same_but_manifold(F,SF,SVI);
  175. }
  176. TEST_CASE("split_nonmanifold: flap", "[igl]")
  177. {
  178. Eigen::MatrixXd V(12,3);
  179. V<<
  180. 1.5,0,0,
  181. 0.75,0,0.433,
  182. 0.75,0,-0.433,
  183. 0,1.5,0,
  184. 0,0.75,0.433,
  185. 0,0.75,-0.433,
  186. -1.5,0,0,
  187. -0.75,0,-0.433,
  188. -0,-1.5,0,
  189. -0,-0.75,0.433,
  190. 1.5,0,1,
  191. 0,1.5,1;
  192. Eigen::MatrixXi F(12,3);
  193. const auto check = [&F,&V]()
  194. {
  195. Eigen::MatrixXi SF;
  196. Eigen::VectorXi SVI;
  197. igl::split_nonmanifold(F,SF,SVI);
  198. igl::writePLY("flap.ply",V,F);
  199. check_same_but_manifold(F,SF,SVI);
  200. {
  201. Eigen::VectorXi C;
  202. const int nc = igl::facet_components(SF,C);
  203. REQUIRE(nc == 2);
  204. }
  205. };
  206. F<<
  207. 0,3,1,
  208. 3,4,1,
  209. 2,5,0,
  210. 5,3,0,
  211. 3,6,4,
  212. 5,7,3,
  213. 7,6,3,
  214. 8,0,9,
  215. 0,1,9,
  216. 2,0,8,
  217. 0,3,11,
  218. 0,11,10;
  219. check();
  220. F<<
  221. 0,3,11,
  222. 0,1,9,
  223. 2,5,0,
  224. 7,6,3,
  225. 0,3,1,
  226. 3,6,4,
  227. 5,3,0,
  228. 5,7,3,
  229. 8,0,9,
  230. 3,4,1,
  231. 2,0,8,
  232. 0,11,10;
  233. check();
  234. }
  235. TEST_CASE("split_nonmanifold: crosses", "[igl]")
  236. {
  237. for(int p = 1;p<7;p++)
  238. {
  239. Eigen::MatrixXd V;
  240. Eigen::MatrixXi F;
  241. // n = 2^p
  242. const int n = 1<<p;
  243. igl::triangulated_grid(n,3,V,F);
  244. V.array() -= 0.5;
  245. V.conservativeResize(V.rows(),3);
  246. V.col(2).setZero();
  247. Eigen::MatrixXd U(V.rows(),3);
  248. U << V.col(0),V.col(2),V.col(1);
  249. Eigen::MatrixXd VV(V.rows()*2,3);
  250. VV << V,U;
  251. Eigen::MatrixXi FF(F.rows()*2,3);
  252. FF << F,F.array()+V.rows();
  253. {
  254. Eigen::VectorXi I,J;
  255. igl::remove_duplicate_vertices(VV,FF,1e-10,V,I,J,F);
  256. }
  257. Eigen::MatrixXi SF;
  258. Eigen::VectorXi SVI;
  259. igl::split_nonmanifold(F,SF,SVI);
  260. check_same_but_manifold(F,SF,SVI);
  261. }
  262. }