cut_to_disk.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #include <igl/cut_to_disk.h>
  2. namespace igl {
  3. template <typename DerivedF, typename Index>
  4. void cut_to_disk(
  5. const Eigen::PlainObjectBase<DerivedF> &F,
  6. std::vector<std::vector<Index> > &cuts)
  7. {
  8. cuts.clear();
  9. Index nfaces = F.rows();
  10. if (nfaces == 0)
  11. return;
  12. std::map<std::pair<Index, Index>, std::vector<Index> > edges;
  13. // build edges
  14. for (Index i = 0; i < nfaces; i++)
  15. {
  16. for (int j = 0; j < 3; j++)
  17. {
  18. Index v0 = F(i, j);
  19. Index v1 = F(i, (j + 1) % 3);
  20. std::pair<Index, Index> e;
  21. e.first = std::min(v0, v1);
  22. e.second = std::max(v0, v1);
  23. edges[e].push_back(i);
  24. }
  25. }
  26. int nedges = edges.size();
  27. Eigen::Matrix<Index, -1, -1> edgeVerts(nedges,2);
  28. Eigen::Matrix<Index, -1, -1> edgeFaces(nedges,2);
  29. Eigen::Matrix<Index, -1, -1> faceEdges(nfaces, 3);
  30. std::set<Index> boundaryEdges;
  31. std::map<std::pair<Index, Index>, Index> edgeidx;
  32. Index idx = 0;
  33. for (auto it : edges)
  34. {
  35. edgeidx[it.first] = idx;
  36. edgeVerts(idx, 0) = it.first.first;
  37. edgeVerts(idx, 1) = it.first.second;
  38. edgeFaces(idx, 0) = it.second[0];
  39. if (it.second.size() > 1)
  40. {
  41. edgeFaces(idx, 1) = it.second[1];
  42. }
  43. else
  44. {
  45. edgeFaces(idx, 1) = -1;
  46. boundaryEdges.insert(idx);
  47. }
  48. idx++;
  49. }
  50. for (Index i = 0; i < nfaces; i++)
  51. {
  52. for (int j = 0; j < 3; j++)
  53. {
  54. Index v0 = F(i, j);
  55. Index v1 = F(i, (j + 1) % 3);
  56. std::pair<Index, Index> e;
  57. e.first = std::min(v0, v1);
  58. e.second = std::max(v0, v1);
  59. faceEdges(i, j) = edgeidx[e];
  60. }
  61. }
  62. bool *deleted = new bool[nfaces];
  63. for (Index i = 0; i < nfaces; i++)
  64. deleted[i] = false;
  65. std::set<Index> deletededges;
  66. // loop over faces
  67. for (Index face = 0; face < nfaces; face++)
  68. {
  69. // stop at first undeleted face
  70. if (deleted[face])
  71. continue;
  72. deleted[face] = true;
  73. std::deque<Index> processEdges;
  74. for (int i = 0; i < 3; i++)
  75. {
  76. Index e = faceEdges(face, i);
  77. if (boundaryEdges.count(e))
  78. continue;
  79. int ndeleted = 0;
  80. if (deleted[edgeFaces(e, 0)])
  81. ndeleted++;
  82. if (deleted[edgeFaces(e, 1)])
  83. ndeleted++;
  84. if (ndeleted == 1)
  85. processEdges.push_back(e);
  86. }
  87. // delete all faces adjacent to edges with exactly one adjacent face
  88. while (!processEdges.empty())
  89. {
  90. Index nexte = processEdges.front();
  91. processEdges.pop_front();
  92. Index todelete = nfaces;
  93. if (!deleted[edgeFaces(nexte, 0)])
  94. todelete = edgeFaces(nexte, 0);
  95. if (!deleted[edgeFaces(nexte, 1)])
  96. todelete = edgeFaces(nexte, 1);
  97. if (todelete != nfaces)
  98. {
  99. deletededges.insert(nexte);
  100. deleted[todelete] = true;
  101. for (int i = 0; i < 3; i++)
  102. {
  103. Index e = faceEdges(todelete, i);
  104. if (boundaryEdges.count(e))
  105. continue;
  106. int ndeleted = 0;
  107. if (deleted[edgeFaces(e, 0)])
  108. ndeleted++;
  109. if (deleted[edgeFaces(e, 1)])
  110. ndeleted++;
  111. if (ndeleted == 1)
  112. processEdges.push_back(e);
  113. }
  114. }
  115. }
  116. }
  117. delete[] deleted;
  118. // accumulated non-deleted edges
  119. std::vector<Index> leftedges;
  120. for (Index i = 0; i < nedges; i++)
  121. {
  122. if (!deletededges.count(i))
  123. leftedges.push_back(i);
  124. }
  125. deletededges.clear();
  126. // prune spines
  127. std::map<Index, std::vector<Index> > spinevertedges;
  128. for (Index i : leftedges)
  129. {
  130. spinevertedges[edgeVerts(i, 0)].push_back(i);
  131. spinevertedges[edgeVerts(i, 1)].push_back(i);
  132. }
  133. std::deque<Index> vertsProcess;
  134. std::map<Index, int> spinevertnbs;
  135. for (auto it : spinevertedges)
  136. {
  137. spinevertnbs[it.first] = it.second.size();
  138. if (it.second.size() == 1)
  139. vertsProcess.push_back(it.first);
  140. }
  141. while (!vertsProcess.empty())
  142. {
  143. Index vert = vertsProcess.front();
  144. vertsProcess.pop_front();
  145. for (Index e : spinevertedges[vert])
  146. {
  147. if (!deletededges.count(e))
  148. {
  149. deletededges.insert(e);
  150. for (int j = 0; j < 2; j++)
  151. {
  152. spinevertnbs[edgeVerts(e, j)]--;
  153. if (spinevertnbs[edgeVerts(e, j)] == 1)
  154. {
  155. vertsProcess.push_back(edgeVerts(e, j));
  156. }
  157. }
  158. }
  159. }
  160. }
  161. std::vector<Index> loopedges;
  162. for (Index i : leftedges)
  163. if (!deletededges.count(i))
  164. loopedges.push_back(i);
  165. Index nloopedges = loopedges.size();
  166. if (nloopedges == 0)
  167. return;
  168. std::map<Index, std::vector<Index> > loopvertedges;
  169. for (Index e : loopedges)
  170. {
  171. loopvertedges[edgeVerts(e, 0)].push_back(e);
  172. loopvertedges[edgeVerts(e, 1)].push_back(e);
  173. }
  174. std::set<Index> usededges;
  175. for (Index e : loopedges)
  176. {
  177. // make a cycle or chain starting from this edge
  178. while (!usededges.count(e))
  179. {
  180. std::vector<Index> cycleverts;
  181. std::vector<Index> cycleedges;
  182. cycleverts.push_back(edgeVerts(e, 0));
  183. cycleverts.push_back(edgeVerts(e, 1));
  184. cycleedges.push_back(e);
  185. std::map<Index, Index> cycleidx;
  186. cycleidx[cycleverts[0]] = 0;
  187. cycleidx[cycleverts[1]] = 1;
  188. Index curvert = edgeVerts(e, 1);
  189. Index cure = e;
  190. bool foundcycle = false;
  191. while (curvert != -1 && !foundcycle)
  192. {
  193. Index nextvert = -1;
  194. Index nexte = -1;
  195. for (Index cande : loopvertedges[curvert])
  196. {
  197. if (!usededges.count(cande) && cande != cure)
  198. {
  199. int vidx = 0;
  200. if (curvert == edgeVerts(cande, vidx))
  201. vidx = 1;
  202. nextvert = edgeVerts(cande, vidx);
  203. nexte = cande;
  204. break;
  205. }
  206. }
  207. if (nextvert != -1)
  208. {
  209. auto it = cycleidx.find(nextvert);
  210. if (it != cycleidx.end())
  211. {
  212. // we've hit outselves
  213. std::vector<Index> cut;
  214. for (Index i = it->second; i < cycleverts.size(); i++)
  215. {
  216. cut.push_back(cycleverts[i]);
  217. }
  218. cut.push_back(nextvert);
  219. cuts.push_back(cut);
  220. for (Index i = it->second; i < cycleedges.size(); i++)
  221. {
  222. usededges.insert(cycleedges[i]);
  223. }
  224. usededges.insert(nexte);
  225. foundcycle = true;
  226. }
  227. else
  228. {
  229. cycleidx[nextvert] = cycleverts.size();
  230. cycleverts.push_back(nextvert);
  231. cycleedges.push_back(nexte);
  232. }
  233. }
  234. curvert = nextvert;
  235. cure = nexte;
  236. }
  237. if (!foundcycle)
  238. {
  239. // we've hit a dead end. reverse and try the other direction
  240. std::reverse(cycleverts.begin(), cycleverts.end());
  241. std::reverse(cycleedges.begin(), cycleedges.end());
  242. curvert = cycleverts.back();
  243. cure = cycleedges.back();
  244. while (curvert != -1 && !foundcycle)
  245. {
  246. Index nextvert = -1;
  247. Index nexte = -1;
  248. for (Index cande : loopvertedges[curvert])
  249. {
  250. if (!usededges.count(cande) && cande != cure)
  251. {
  252. int vidx = 0;
  253. if (curvert == edgeVerts(cande, vidx))
  254. vidx = 1;
  255. nextvert = edgeVerts(cande, vidx);
  256. nexte = cande;
  257. break;
  258. }
  259. }
  260. if (nextvert != -1)
  261. {
  262. auto it = cycleidx.find(nextvert);
  263. if (it != cycleidx.end())
  264. {
  265. // we've hit outselves
  266. std::vector<int> cut;
  267. for (Index i = it->second; i < cycleverts.size(); i++)
  268. {
  269. cut.push_back(cycleverts[i]);
  270. }
  271. cut.push_back(nextvert);
  272. cuts.push_back(cut);
  273. for (Index i = it->second; i < cycleedges.size(); i++)
  274. {
  275. usededges.insert(cycleedges[i]);
  276. }
  277. usededges.insert(nexte);
  278. foundcycle = true;
  279. }
  280. else
  281. {
  282. cycleidx[nextvert] = cycleverts.size();
  283. cycleverts.push_back(nextvert);
  284. cycleedges.push_back(nexte);
  285. }
  286. }
  287. curvert = nextvert;
  288. cure = nexte;
  289. }
  290. if (!foundcycle)
  291. {
  292. // we've found a chain
  293. std::vector<Index> cut;
  294. for (Index i = 0; i < cycleverts.size(); i++)
  295. {
  296. cut.push_back(cycleverts[i]);
  297. }
  298. cuts.push_back(cut);
  299. for (Index i = 0; i < cycleedges.size(); i++)
  300. {
  301. usededges.insert(cycleedges[i]);
  302. }
  303. }
  304. }
  305. }
  306. }
  307. }
  308. }