extract_cells.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #include "extract_cells.h"
  2. #include "../extract_manifold_patches.h"
  3. #include "../facet_components.h"
  4. #include "../triangle_triangle_adjacency.h"
  5. #include "../unique_edge_map.h"
  6. #include "closest_facet.h"
  7. #include "order_facets_around_edge.h"
  8. #include "outer_facet.h"
  9. #include <vector>
  10. template<
  11. typename DerivedV,
  12. typename DerivedF,
  13. typename DerivedP,
  14. typename DeriveduE,
  15. typename uE2EType,
  16. typename DerivedEMAP,
  17. typename DerivedC >
  18. IGL_INLINE size_t igl::cgal::extract_cells_single_component(
  19. const Eigen::PlainObjectBase<DerivedV>& V,
  20. const Eigen::PlainObjectBase<DerivedF>& F,
  21. const Eigen::PlainObjectBase<DerivedP>& P,
  22. const Eigen::PlainObjectBase<DeriveduE>& uE,
  23. const std::vector<std::vector<uE2EType> >& uE2E,
  24. const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
  25. Eigen::PlainObjectBase<DerivedC>& cells) {
  26. typedef typename DerivedF::Scalar Index;
  27. const size_t num_faces = F.rows();
  28. auto edge_index_to_face_index = [&](size_t index) {
  29. return index % num_faces;
  30. };
  31. auto is_consistent = [&](const size_t fid, const size_t s, const size_t d) {
  32. if (F(fid, 0) == s && F(fid, 1) == d) return false;
  33. if (F(fid, 1) == s && F(fid, 2) == d) return false;
  34. if (F(fid, 2) == s && F(fid, 0) == d) return false;
  35. if (F(fid, 0) == d && F(fid, 1) == s) return true;
  36. if (F(fid, 1) == d && F(fid, 2) == s) return true;
  37. if (F(fid, 2) == d && F(fid, 0) == s) return true;
  38. throw "Invalid face!";
  39. return false;
  40. };
  41. const size_t num_unique_edges = uE.rows();
  42. const size_t num_patches = P.maxCoeff() + 1;
  43. std::vector<std::vector<size_t> > patch_edge_adj(num_patches);
  44. std::vector<Eigen::VectorXi> orders(num_unique_edges);
  45. std::vector<std::vector<bool> > orientations(num_unique_edges);
  46. for (size_t i=0; i<num_unique_edges; i++) {
  47. const size_t s = uE(i,0);
  48. const size_t d = uE(i,1);
  49. const auto adj_faces = uE2E[i];
  50. if (adj_faces.size() > 2) {
  51. std::vector<int> signed_adj_faces;
  52. for (auto ei : adj_faces) {
  53. const size_t fid = edge_index_to_face_index(ei);
  54. bool cons = is_consistent(fid, s, d);
  55. signed_adj_faces.push_back((fid+1)*(cons ? 1:-1));
  56. }
  57. auto& order = orders[i];
  58. igl::cgal::order_facets_around_edge(
  59. V, F, s, d, signed_adj_faces, order);
  60. auto& orientation = orientations[i];
  61. orientation.resize(order.size());
  62. std::transform(order.data(), order.data() + order.size(),
  63. orientation.begin(), [&](int index) { return
  64. signed_adj_faces[index] > 0; });
  65. std::transform(order.data(), order.data() + order.size(),
  66. order.data(), [&](int index) { return adj_faces[index]; });
  67. for (auto ei : adj_faces) {
  68. const size_t fid = edge_index_to_face_index(ei);
  69. patch_edge_adj[P[fid]].push_back(ei);
  70. }
  71. }
  72. }
  73. const int INVALID = std::numeric_limits<int>::max();
  74. cells.resize(num_patches, 2);
  75. cells.setConstant(INVALID);
  76. auto peel_cell_bd = [&](
  77. size_t seed_patch_id,
  78. short seed_patch_side,
  79. size_t cell_idx) {
  80. typedef std::pair<size_t, short> PatchSide;
  81. std::queue<PatchSide> Q;
  82. Q.emplace(seed_patch_id, seed_patch_side);
  83. cells(seed_patch_id, seed_patch_side) = cell_idx;
  84. while (!Q.empty()) {
  85. auto entry = Q.front();
  86. Q.pop();
  87. const size_t patch_id = entry.first;
  88. const short side = entry.second;
  89. const auto& adj_edges = patch_edge_adj[patch_id];
  90. for (const auto& ei : adj_edges) {
  91. const size_t uei = EMAP[ei];
  92. const auto& order = orders[uei];
  93. const auto& orientation = orientations[uei];
  94. const size_t edge_valance = order.size();
  95. size_t curr_i = 0;
  96. for (curr_i=0; curr_i < edge_valance; curr_i++) {
  97. if (order[curr_i] == ei) break;
  98. }
  99. assert(curr_i < edge_valance);
  100. const bool cons = orientation[curr_i];
  101. size_t next;
  102. if (side == 0) {
  103. next = (cons ? (curr_i + 1) :
  104. (curr_i + edge_valance - 1)) % edge_valance;
  105. } else {
  106. next = (cons ? (curr_i + edge_valance - 1) :
  107. (curr_i + 1)) % edge_valance;
  108. }
  109. const size_t next_ei = order[next];
  110. const bool next_cons = orientation[next];
  111. const size_t next_patch_id = P[next_ei % num_faces];
  112. const short next_patch_side = (next_cons != cons) ?
  113. side:abs(side-1);
  114. if (cells(next_patch_id, next_patch_side) == INVALID) {
  115. Q.emplace(next_patch_id, next_patch_side);
  116. cells(next_patch_id, next_patch_side) = cell_idx;
  117. } else {
  118. assert(cells(next_patch_id, next_patch_side) == cell_idx);
  119. }
  120. }
  121. }
  122. };
  123. size_t count=0;
  124. for (size_t i=0; i<num_patches; i++) {
  125. if (cells(i, 0) == INVALID) {
  126. peel_cell_bd(i, 0, count);
  127. count++;
  128. }
  129. if (cells(i, 1) == INVALID) {
  130. peel_cell_bd(i, 1, count);
  131. count++;
  132. }
  133. }
  134. return count;
  135. }
  136. template<
  137. typename DerivedV,
  138. typename DerivedF,
  139. typename DerivedP,
  140. typename DerivedE,
  141. typename DeriveduE,
  142. typename uE2EType,
  143. typename DerivedEMAP,
  144. typename DerivedC >
  145. IGL_INLINE size_t igl::cgal::extract_cells(
  146. const Eigen::PlainObjectBase<DerivedV>& V,
  147. const Eigen::PlainObjectBase<DerivedF>& F,
  148. const Eigen::PlainObjectBase<DerivedP>& P,
  149. const Eigen::PlainObjectBase<DerivedE>& E,
  150. const Eigen::PlainObjectBase<DeriveduE>& uE,
  151. const std::vector<std::vector<uE2EType> >& uE2E,
  152. const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
  153. Eigen::PlainObjectBase<DerivedC>& cells) {
  154. const size_t num_faces = F.rows();
  155. typedef typename DerivedF::Scalar Index;
  156. const size_t num_patches = P.maxCoeff()+1;
  157. DerivedC raw_cells;
  158. const size_t num_raw_cells =
  159. igl::cgal::extract_cells_single_component(
  160. V, F, P, uE, uE2E, EMAP, raw_cells);
  161. std::vector<std::vector<std::vector<Index > > > TT,_1;
  162. igl::triangle_triangle_adjacency(E, EMAP, uE2E, false, TT, _1);
  163. Eigen::VectorXi C, counts;
  164. igl::facet_components(TT, C, counts);
  165. const size_t num_components = counts.size();
  166. std::vector<std::vector<size_t> > components(num_components);
  167. for (size_t i=0; i<num_faces; i++) {
  168. components[C[i]].push_back(i);
  169. }
  170. std::vector<Eigen::VectorXi> Is(num_components);
  171. for (size_t i=0; i<num_components; i++) {
  172. Is[i].resize(components[i].size());
  173. std::copy(components[i].begin(), components[i].end(),
  174. Is[i].data());
  175. }
  176. Eigen::VectorXi outer_facets(num_components);
  177. Eigen::VectorXi outer_facet_orientation(num_components);
  178. Eigen::VectorXi outer_cells(num_components);
  179. for (size_t i=0; i<num_components; i++) {
  180. bool flipped;
  181. igl::cgal::outer_facet(V, F, Is[i], outer_facets[i], flipped);
  182. outer_facet_orientation[i] = flipped?1:0;
  183. outer_cells[i] = raw_cells(P[outer_facets[i]], outer_facet_orientation[i]);
  184. }
  185. auto get_triangle_center = [&](const size_t fid) {
  186. return ((V.row(F(fid, 0)) + V.row(F(fid, 1)) + V.row(F(fid, 2)))
  187. /3.0).eval();
  188. };
  189. std::vector<std::vector<size_t> > nested_cells(num_raw_cells);
  190. std::vector<std::vector<size_t> > ambient_cells(num_raw_cells);
  191. std::vector<std::vector<size_t> > ambient_comps(num_components);
  192. for (size_t i=0; i<num_components; i++) {
  193. DerivedV queries(num_components-1, 3);
  194. for (size_t j=0; j<num_components; j++) {
  195. if (i == j) continue;
  196. size_t index = j<i ? j:j-1;
  197. queries.row(index) = get_triangle_center(outer_facets[j]);
  198. }
  199. const auto& I = Is[i];
  200. Eigen::VectorXi closest_facets, closest_facet_orientations;
  201. igl::cgal::closest_facet(V, F, I, queries,
  202. closest_facets, closest_facet_orientations);
  203. for (size_t j=0; j<num_components; j++) {
  204. if (i == j) continue;
  205. size_t index = j<i ? j:j-1;
  206. const size_t closest_patch = P[closest_facets[index]];
  207. const size_t closest_patch_side = closest_facet_orientations[index]
  208. ? 0:1;
  209. const size_t ambient_cell = raw_cells(closest_patch,
  210. closest_patch_side);
  211. if (ambient_cell != outer_cells[i]) {
  212. nested_cells[ambient_cell].push_back(outer_cells[j]);
  213. ambient_cells[outer_cells[j]].push_back(ambient_cell);
  214. ambient_comps[j].push_back(i);
  215. }
  216. }
  217. }
  218. const size_t INVALID = std::numeric_limits<size_t>::max();
  219. const size_t INFINITE_CELL = num_raw_cells;
  220. std::vector<size_t> embedded_cells(num_raw_cells, INVALID);
  221. for (size_t i=0; i<num_components; i++) {
  222. const size_t outer_cell = outer_cells[i];
  223. const auto& ambient_comps_i = ambient_comps[i];
  224. const auto& ambient_cells_i = ambient_cells[outer_cell];
  225. const size_t num_ambient_comps = ambient_comps_i.size();
  226. assert(num_ambient_comps == ambient_cells_i.size());
  227. if (num_ambient_comps > 0) {
  228. size_t embedded_comp = INVALID;
  229. size_t embedded_cell = INVALID;
  230. for (size_t j=0; j<num_ambient_comps; j++) {
  231. if (ambient_comps[ambient_comps_i[j]].size() ==
  232. num_ambient_comps-1) {
  233. embedded_comp = ambient_comps_i[j];
  234. embedded_cell = ambient_cells_i[j];
  235. break;
  236. }
  237. }
  238. assert(embedded_comp != INVALID);
  239. assert(embedded_cell != INVALID);
  240. embedded_cells[outer_cell] = embedded_cell;
  241. } else {
  242. embedded_cells[outer_cell] = INFINITE_CELL;
  243. }
  244. }
  245. for (size_t i=0; i<num_patches; i++) {
  246. if (embedded_cells[raw_cells(i,0)] != INVALID) {
  247. raw_cells(i,0) = embedded_cells[raw_cells(i, 0)];
  248. }
  249. if (embedded_cells[raw_cells(i,1)] != INVALID) {
  250. raw_cells(i,1) = embedded_cells[raw_cells(i, 1)];
  251. }
  252. }
  253. size_t count = 0;
  254. std::vector<size_t> mapped_indices(num_raw_cells+1, INVALID);
  255. for (size_t i=0; i<num_patches; i++) {
  256. const size_t old_positive_cell_id = raw_cells(i, 0);
  257. const size_t old_negative_cell_id = raw_cells(i, 1);
  258. size_t positive_cell_id, negative_cell_id;
  259. if (mapped_indices[old_positive_cell_id] == INVALID) {
  260. mapped_indices[old_positive_cell_id] = count;
  261. positive_cell_id = count;
  262. count++;
  263. } else {
  264. positive_cell_id = mapped_indices[old_positive_cell_id];
  265. }
  266. if (mapped_indices[old_negative_cell_id] == INVALID) {
  267. mapped_indices[old_negative_cell_id] = count;
  268. negative_cell_id = count;
  269. count++;
  270. } else {
  271. negative_cell_id = mapped_indices[old_negative_cell_id];
  272. }
  273. raw_cells(i, 0) = positive_cell_id;
  274. raw_cells(i, 1) = negative_cell_id;
  275. }
  276. cells = raw_cells;
  277. return count;
  278. }
  279. template<
  280. typename DerivedV,
  281. typename DerivedF,
  282. typename DerivedC >
  283. IGL_INLINE size_t igl::cgal::extract_cells(
  284. const Eigen::PlainObjectBase<DerivedV>& V,
  285. const Eigen::PlainObjectBase<DerivedF>& F,
  286. Eigen::PlainObjectBase<DerivedC>& cells) {
  287. const size_t num_faces = F.rows();
  288. typedef typename DerivedF::Scalar Index;
  289. Eigen::MatrixXi E, uE;
  290. Eigen::VectorXi EMAP;
  291. std::vector<std::vector<size_t> > uE2E;
  292. igl::unique_edge_map(F, E, uE, EMAP, uE2E);
  293. Eigen::VectorXi P;
  294. const size_t num_patches = igl::extract_manifold_patches(F, EMAP, uE2E, P);
  295. DerivedC per_patch_cells;
  296. const size_t num_cells =
  297. igl::cgal::extract_cells(V, F, P, E, uE, uE2E, EMAP, per_patch_cells);
  298. cells.resize(num_faces, 2);
  299. for (size_t i=0; i<num_faces; i++) {
  300. cells.row(i) = per_patch_cells.row(P[i]);
  301. }
  302. return num_cells;
  303. }