36 template<
typename IterFaceType,
typename Po
intMap >
41 auto pm_new =
get(boost::vertex_point, res);
42 std::map<vertex_descriptor, vertex_descriptor> from_current_to_new;
44 for (; iter_f != end; ++iter_f)
46 std::vector<vertex_descriptor> face_vertices;
48 auto iter_v = vertex_range.begin();
49 for (; iter_v != vertex_range.end(); ++iter_v)
51 if (from_current_to_new.find(*iter_v) == from_current_to_new.end())
54 from_current_to_new[*iter_v] = v_n;
55 auto p =
get(pm, *iter_v);
58 face_vertices.push_back(from_current_to_new[*iter_v]);
65 template<
typename Po
intMap>
75 template<
typename Po
intMap>
77 typename boost::graph_traits< AIFMeshT >::edge_descriptor e,
81 typedef typename boost::graph_traits< AIFMeshT >::face_descriptor face_descriptor;
86 std::set<face_descriptor>
faces(face_range_s.begin(), face_range_s.end());
87 faces.insert(face_range_t.begin(), face_range_t.end());
92 static bool argument_analysis(std::string& arg,
const std::string& arg_name,
bool update_arg_tolower_case =
true)
94 if (arg !=
"y" && arg !=
"n" &&
95 arg !=
"Y" && arg !=
"N")
97 std::cerr <<
"Cannot understand input for " + arg_name +
". "
98 "Please use either \"y\" or \"n\" "
102 else if (update_arg_tolower_case)
113 static void replace(std::string& to_modify,
const std::string& substring_to_search,
const std::string& substring_to_use)
115 size_t pos = to_modify.find(substring_to_search);
116 while (pos != std::string::npos)
118 to_modify.replace(pos, substring_to_search.size(), substring_to_use);
119 pos = to_modify.find(substring_to_search, pos + substring_to_use.size());
124 template<
typename MutableFaceInc
identGraph >
125 typename boost::graph_traits<MutableFaceIncidentGraph >::edge_descriptor
128 typedef boost::graph_traits< MutableFaceIncidentGraph > GraphTraits;
141 template<
typename MutableFaceInc
identGraph >
143 std::vector<
typename boost::graph_traits<MutableFaceIncidentGraph >::edge_descriptor >& selected_edges_to_make_independent,
144 std::vector<
typename boost::graph_traits<MutableFaceIncidentGraph >::edge_descriptor>& removed_edges)
146 typedef boost::graph_traits< MutableFaceIncidentGraph > GraphTraits;
152 removed_edges.clear();
153 std::set< edge_descriptor > set_removed_edges;
154 auto iter_e = selected_edges_to_make_independent.begin(), iter_e_e = selected_edges_to_make_independent.end();
155 while (iter_e != iter_e_e)
157 if (set_removed_edges.find(*iter_e) != set_removed_edges.end())
166 auto iter_e2 = edges_pair.first;
167 for (; iter_e2 != edges_pair.second; ++iter_e2)
169 if (*iter_e2 == *iter_e)
179 set_removed_edges.insert(*iter_e2);
182 set_removed_edges.insert(res_edges.begin(), res_edges.end());
185 iter_e2 = edges_pair.first;
186 for (; iter_e2 != edges_pair.second; ++iter_e2)
188 if (*iter_e2 == *iter_e)
198 set_removed_edges.insert(*iter_e2);
201 set_removed_edges.insert(res_edges.begin(), res_edges.end());
205 auto iter_e_s = set_removed_edges.begin();
206 auto iter_e_s_e = set_removed_edges.end();
207 for (; iter_e_s != iter_e_s_e; ++iter_e_s)
209 auto iter_res = std::find(selected_edges_to_make_independent.begin(), selected_edges_to_make_independent.end(), *iter_e_s);
210 if (iter_res != selected_edges_to_make_independent.end())
212 removed_edges.push_back(*iter_res);
213 selected_edges_to_make_independent.erase(iter_res);
218 template<
typename MutableFaceInc
identGraph >
220 typename boost::graph_traits<MutableFaceIncidentGraph >::edge_descriptor e
223 std::set<int> segment_indices;
224 auto src_incident_faces_pair =
in_edges(e,
g);
225 auto iter_f = src_incident_faces_pair.first;
226 for (; iter_f != src_incident_faces_pair.second; ++iter_f)
228 int current_face_id =
g.template GetProperty< AIFMeshT::face_type::ptr, int >(
229 "f:2_manifold_component_seg", (*iter_f)->GetIndex());
231 segment_indices.insert(current_face_id);
233 return segment_indices.size();
235 template<
typename MutableFaceInc
identGraph >
237 typename boost::graph_traits<MutableFaceIncidentGraph >::edge_descriptor e,
241 auto src_incident_faces_pair =
in_edges(e,
g);
242 auto iter_f = src_incident_faces_pair.first;
243 for (; iter_f != src_incident_faces_pair.second; ++iter_f)
245 int current_face_id =
g.template GetProperty< AIFMeshT::face_type::ptr, int >(
246 "f:2_manifold_component_seg", (*iter_f)->GetIndex());
248 if (current_face_id == index)
253 template<
typename MutableFaceInc
identGraph >
255 typename boost::graph_traits<MutableFaceIncidentGraph >::edge_descriptor e,
259 auto src_incident_faces_pair =
in_edges(e,
g);
260 auto iter_f = src_incident_faces_pair.first;
261 for (; iter_f != src_incident_faces_pair.second; ++iter_f)
263 int current_face_id =
g.template GetProperty< AIFMeshT::face_type::ptr, int >(
264 "f:2_manifold_component_seg", (*iter_f)->GetIndex());
266 if (current_face_id != index)
271 template<
typename MutableFaceInc
identGraph >
275 typename boost::graph_traits<MutableFaceIncidentGraph >::face_descriptor current_f,
276 const std::vector<
typename boost::graph_traits<MutableFaceIncidentGraph >::edge_descriptor >&
280 typedef boost::graph_traits< MutableFaceIncidentGraph > GraphTraits;
284 typedef typename GraphTraits::face_descriptor face_descriptor;
290 int current_face_id =
g.template GetProperty< AIFMeshT::face_type::ptr, int >(
291 "f:2_manifold_component_seg", current_f->GetIndex());
293 std::set<vertex_descriptor> forbidden_vertices;
294 std::set<edge_descriptor> forbidden_edges;
295 auto iter_ec = complex_edges.begin(), iter_ec_e = complex_edges.end();
296 forbidden_edges.insert(iter_ec, iter_ec_e);
300 std::set<edge_descriptor> copy_incident_edges_for_removal(src_incident_edges_range.begin(), src_incident_edges_range.end());
301 auto iter_e = copy_incident_edges_for_removal.begin();
302 auto iter_e_e = copy_incident_edges_for_removal.end();
303 for (; iter_e != iter_e_e; ++iter_e)
305 if (forbidden_edges.find(*iter_e)!= forbidden_edges.end())
329 assert(res_pair.second);
332 auto face_range_pair =
in_edges(*iter_e,
g);
333 std::set<face_descriptor> copy_incident_faces_for_removal(face_range_pair.first, face_range_pair.second);
334 auto iter_f = copy_incident_faces_for_removal.begin(), iter_f_e = copy_incident_faces_for_removal.end();
335 for (; iter_f != iter_f_e; ++iter_f)
337 if (
g.template GetProperty< AIFMeshT::face_type::ptr, int >(
338 "f:2_manifold_component_seg", (*iter_f)->GetIndex()) == current_face_id)
351 template<
typename MutableFaceInc
identGraph >
353 MutableFaceIncidentGraph &,
354 typename boost::graph_traits<MutableFaceIncidentGraph >::edge_descriptor e,
355 typename boost::graph_traits<MutableFaceIncidentGraph >::edge_descriptor pe,
356 typename boost::graph_traits<MutableFaceIncidentGraph >::edge_descriptor ae,
368 if (v_new_to_old.find(pe->get_first_vertex()) != v_new_to_old.end())
369 v_pe_old = v_new_to_old[pe->get_first_vertex()];
370 else if (v_new_to_old.find(pe->get_second_vertex()) != v_new_to_old.end())
371 v_pe_old = v_new_to_old[pe->get_second_vertex()];
373 else if (v_old_to_v_new.find(v_pe_old) == v_old_to_v_new.end())
375 if (v_new_to_old.find(v_pe_old) != v_new_to_old.end())
376 v_pe_old = v_new_to_old[v_pe_old];
380 std::cerr <<
"you may have a similar face with different face id" << std::endl;
385 if (v_new_to_old.find(ae->get_first_vertex()) != v_new_to_old.end())
386 v_ae_old = v_new_to_old[ae->get_first_vertex()];
387 else if (v_new_to_old.find(ae->get_second_vertex()) != v_new_to_old.end())
388 v_ae_old = v_new_to_old[ae->get_second_vertex()];
390 else if (v_old_to_v_new.find(v_ae_old) == v_old_to_v_new.end())
392 if (v_new_to_old.find(v_ae_old) != v_new_to_old.end())
393 v_ae_old = v_new_to_old[v_ae_old];
397 std::cerr <<
"you may have a similar face with different face id" << std::endl;
400 template<
typename MutableFaceInc
identGraph,
typename Po
intMap >
402 MutableFaceIncidentGraph &
g,
404 typename boost::graph_traits<MutableFaceIncidentGraph >::face_descriptor f,
405 typename boost::graph_traits<MutableFaceIncidentGraph >::edge_descriptor e,
406 typename boost::graph_traits<MutableFaceIncidentGraph >::edge_descriptor replace,
413 typedef boost::graph_traits< MutableFaceIncidentGraph > GraphTraits;
424 int current_face_id =
g.template GetProperty< AIFMeshT::face_type::ptr, int >(
425 "f:2_manifold_component_seg", f->GetIndex());
445 auto p =
get(pm, v_pe_old);
447 p =
get(pm, v_ae_old);
462 v_old_to_v_new[v_pe_old] =
source(replace,
g);
463 v_old_to_v_new[v_ae_old] =
target(replace,
g);
464 v_new_to_old[
source(replace,
g)] = v_pe_old;
465 v_new_to_old[
target(replace,
g)] = v_ae_old;
486 template<
typename MutableFaceInc
identGraph,
typename Po
intIndexMap >
488 typename boost::graph_traits<MutableFaceIncidentGraph >::face_descriptor f)
492 auto iter_v = vertex_range.begin();
493 std::map<vertex_descriptor, int> v_to_index;
494 for (; iter_v != vertex_range.end(); ++iter_v)
496 v_to_index[*iter_v] =
get(idm, *iter_v);
499 return (
degree(f,
g) == v_to_index.size()) ;
503 const std::string& colorize_mesh,
504 const std::string& remove_isolated_elements,
505 const std::string& resolve_vertices_with_similar_incident_edges,
506 const std::string& make_2_mani_not_2_mani)
510 typedef boost::graph_traits< reader_type::output_type > GraphTraits;
513 typedef typename GraphTraits::vertex_iterator vertex_iterator;
515 typedef typename GraphTraits::edge_iterator edge_iterator;
517 typedef typename GraphTraits::face_iterator face_iterator;
518 typedef typename GraphTraits::face_descriptor face_descriptor;
524 ptr_mesh = my_reader.
read(input_file_path);
526 catch (
const std::invalid_argument &e)
528 std::cerr <<
"Invalid Argument Exception catch while reading "
529 << input_file_path <<
" :" << std::endl
530 << e.what() << std::endl;
533 catch (
const std::ios_base::failure &e)
535 std::cerr <<
"IOS Failure Exception catch while reading " << input_file_path
537 << e.what() << std::endl;
540 catch (
const std::length_error &le)
542 std::cerr <<
"[AIF] Exception caught while reading input file "
543 << input_file_path <<
": " << le.what() << std::endl;
544 BOOST_ASSERT_MSG(
false,
"[AIF] Exception caught while reading input file.");
547 GeometryTraits gt(*ptr_mesh);
548 auto pos_pm =
get(boost::vertex_point, *ptr_mesh);
549 auto vertex_idm =
get(boost::vertex_index, *ptr_mesh);
550 auto edge_idm =
get(boost::edge_index, *ptr_mesh);
556 if (colorize_mesh ==
"y")
562 throw std::runtime_error(
"Failed to create vertex-color property map.");
568 throw std::runtime_error(
"Failed to create edge-color property map.");
574 throw std::runtime_error(
"Failed to create face-color property map.");
577 if (make_2_mani_not_2_mani ==
"y")
583 throw std::runtime_error(
"Failed to create face 2-manifold components property map.");
586 std::set<face_descriptor> to_process,
587 all_faces(
faces(*ptr_mesh).first,
faces(*ptr_mesh).second);
588 bool first_phase =
true
589 , second_phase_first_subphase=
true;
590 int current_id = 0, nb_used_id = 0;
592 if (iter_f_first == all_faces.end())
595 iter_f_first = all_faces.begin();
597 to_process.insert(*iter_f_first);
598 all_faces.erase(iter_f_first);
600 while (!to_process.empty())
602 face_descriptor current_f = *to_process.begin();
604 "f:2_manifold_component_seg", current_f->GetIndex(), current_id);
606 to_process.erase(to_process.begin());
609 auto iter_f = vector_faces.begin(), iter_f_end = vector_faces.end();
610 for (; iter_f != iter_f_end; ++iter_f)
612 assert(*iter_f != current_f);
613 if ((all_faces.find(*iter_f) != all_faces.end())
627 to_process.insert(*iter_f);
628 all_faces.erase(*iter_f);
634 if (second_phase_first_subphase)
636 if ((to_process.size() > 1))
638 std::set<face_descriptor> new_face_set;
640 auto iter_f = to_process.begin(), iter_f_end = to_process.end();
644 double best_val = -1.1, val_f1 = -1.1, val_f2 = -1.1;
648 size_t cpt_neigh = 0;
649 for (; iter_f != iter_f_end; ++iter_f)
651 if (*iter_f == current_f)
656 double tmp = gt.dot_product(current_n, neighbor_n);
659 best_val = val_f1 = tmp;
683 double tmp = gt.dot_product(current_n, neighbor_n);
685 new_face_set.insert(best_f);
686 else if(val_f1 > val_f2)
687 new_face_set.insert(other_f2);
689 new_face_set.insert(other_f1);
692 new_face_set.insert(best_f);
694 to_process.swap(new_face_set);
697 second_phase_first_subphase =
false;
698 if (to_process.size() > 0)
701 current_id = nb_used_id;
706 std::set<face_descriptor> new_face_set;
707 to_process.swap(new_face_set);
710 if (to_process.empty() && !all_faces.empty())
712 iter_f_first = std::find_if(
716 if (iter_f_first == all_faces.end())
719 iter_f_first = all_faces.begin();
721 auto iter_f = vector_faces.begin(), iter_f_end = vector_faces.end();
723 int id_best_match = -1;
725 double best_val = -1.1;
726 for (; iter_f != iter_f_end; ++iter_f)
728 if ((all_faces.find(*iter_f) == all_faces.end())
733 int current_f_id = ptr_mesh->template GetProperty< AIFMeshT::face_type::ptr, int >(
734 "f:2_manifold_component_seg", (*iter_f)->GetIndex());
737 double tmp = gt.dot_product(current_n, neighbor_n);
738 if (id_best_match == -1)
740 id_best_match = current_f_id;
744 || (std::abs(tmp+1.)<1e-5)
747 id_best_match = current_f_id;
756 id_best_match = current_f_id;
761 if (id_best_match == -1)
764 current_id = nb_used_id ;
768 current_id = id_best_match;
771 second_phase_first_subphase =
true;
778 to_process.insert(*iter_f_first);
779 all_faces.erase(iter_f_first);
783 std::cout <<
"segmented into " << (nb_used_id + 1) <<
" 2-manifold components." << std::endl;
789 auto iterator_pair_v =
vertices(*ptr_mesh);
790 vertex_iterator vi = iterator_pair_v.first;
791 vertex_iterator vi_end = iterator_pair_v.second;
792 int nb_isolated_vertices = 0, nb_cut_vertices = 0, nb_t_junction_vertices = 0,
793 nb_vertices_with_similar_incident_edges = 0;
794 std::vector< vertex_descriptor > v_to_remeove;
795 std::vector< vertex_descriptor > cut_vertices;
796 std::vector< vertex_descriptor > t_junction_vertices;
797 for (; vi != vi_end; ++vi)
801 ++nb_isolated_vertices;
803 if (remove_isolated_elements ==
"y")
804 v_to_remeove.push_back(*vi);
807 if (colorize_mesh ==
"y")
809 "v:color", (*vi)->GetIndex(), red);
814 ++nb_t_junction_vertices;
816 if (make_2_mani_not_2_mani ==
"y")
817 t_junction_vertices.push_back(*vi);
819 if (colorize_mesh ==
"y")
821 "v:color", (*vi)->GetIndex(), blue);
829 if (make_2_mani_not_2_mani ==
"y")
830 cut_vertices.push_back(*vi);
832 if (colorize_mesh ==
"y")
834 "v:color", (*vi)->GetIndex(), blue);
839 ++nb_vertices_with_similar_incident_edges;
841 if (resolve_vertices_with_similar_incident_edges ==
"y")
844 if (colorize_mesh ==
"y")
846 "v:color", (*vi)->GetIndex(), blue);
850 if (colorize_mesh ==
"y")
852 "v:color", (*vi)->GetIndex(), green);
857 auto iterator_pair_e =
edges(*ptr_mesh);
858 edge_iterator ei = iterator_pair_e.first;
859 edge_iterator ei_end = iterator_pair_e.second;
860 int nb_isolated_edges = 0,
861 nb_dangling_edges = 0,
862 nb_complex_edges = 0,
863 nb_non_consitently_oriented_incident_face_edges = 0,
865 std::vector< edge_descriptor > e_to_remeove;
866 std::vector< edge_descriptor > dangling_edges,
868 non_consitently_oriented_incident_face_edges;
869 for (; ei != ei_end; ++ei)
874 if (remove_isolated_elements ==
"y")
875 e_to_remeove.push_back(*ei);
878 if (colorize_mesh ==
"y")
880 "e:color", (*ei)->GetIndex(), red);
886 if (make_2_mani_not_2_mani ==
"y")
887 dangling_edges.push_back(*ei);
890 if (colorize_mesh ==
"y")
892 "e:color", (*ei)->GetIndex(), red);
898 if (make_2_mani_not_2_mani ==
"y")
899 complex_edges.push_back(*ei);
902 if (colorize_mesh ==
"y")
910 "e:color", (*ei)->GetIndex(), blue);
919 ++nb_non_consitently_oriented_incident_face_edges;
920 if (make_2_mani_not_2_mani ==
"y")
921 non_consitently_oriented_incident_face_edges.push_back(*ei);
924 if (colorize_mesh ==
"y")
926 "e:color", (*ei)->GetIndex(), red);
932 if (colorize_mesh ==
"y")
934 "e:color", (*ei)->GetIndex(), white);
938 if (colorize_mesh ==
"y")
940 "e:color", (*ei)->GetIndex(), green);
945 auto iterator_pair_f =
faces(*ptr_mesh);
946 face_iterator fi = iterator_pair_f.first;
947 face_iterator fi_end = iterator_pair_f.second;
948 int nb_isolated_faces = 0, nb_degenerated_faces = 0;
949 std::vector< face_descriptor > f_to_remeove;
950 for (; fi != fi_end; ++fi)
962 if (colorize_mesh ==
"y")
964 "f:color", (*fi)->GetIndex(), red);
969 if (colorize_mesh ==
"y")
971 "f:color", (*fi)->GetIndex(), green);
975 ++nb_degenerated_faces;
979 std::string suffix =
"";
980 if (remove_isolated_elements ==
"y")
982 if (nb_isolated_vertices != 0
983 || nb_isolated_edges != 0
988 f_to_remeove.begin(), f_to_remeove.end(), ptr_mesh);
990 e_to_remeove.begin(), e_to_remeove.end(), ptr_mesh);
992 v_to_remeove.begin(), v_to_remeove.end(), ptr_mesh);
993 suffix =
"_without_isolated_elmt";
994 if (resolve_vertices_with_similar_incident_edges ==
"y")
995 suffix +=
"_and_similar_incident_edges";
997 else if (resolve_vertices_with_similar_incident_edges ==
"y")
998 suffix =
"_without_similar_incident_edges";
1000 if (make_2_mani_not_2_mani ==
"y")
1001 suffix +=
"_without_non_manifold_elm";
1003 else if (resolve_vertices_with_similar_incident_edges ==
"y")
1005 suffix =
"_without_similar_incident_edges";
1006 if (make_2_mani_not_2_mani ==
"y")
1007 suffix +=
"_without_non_manifold_elm";
1009 else if (make_2_mani_not_2_mani ==
"y")
1010 suffix =
"_without_non_manifold_elm";
1015 auto iter_e = dangling_edges.begin(), iter_e_end = dangling_edges.end();
1016 while (iter_e != iter_e_end)
1018 if (
degree(
source(*iter_e, *ptr_mesh), *ptr_mesh) == 1)
1020 auto v_tmp =
target(*iter_e, *ptr_mesh);
1025 if (make_2_mani_not_2_mani ==
"y")
1026 cut_vertices.push_back(v_tmp);
1028 if (colorize_mesh ==
"y")
1030 "v:color", v_tmp->GetIndex(), blue);
1035 auto v_tmp =
source(*iter_e, *ptr_mesh);
1040 if (make_2_mani_not_2_mani ==
"y")
1041 cut_vertices.push_back(v_tmp);
1043 if (colorize_mesh ==
"y")
1045 "v:color", v_tmp->GetIndex(), blue);
1052 std::vector< edge_descriptor > selected_complex_edges(complex_edges.begin(), complex_edges.end()),
1053 remaining_complex_edges;
1056 while (!selected_complex_edges.empty())
1058 std::cout <<
"New decomplexification step for an independent set of complex edges" << std::endl;
1059 iter_e = selected_complex_edges.begin(), iter_e_end = selected_complex_edges.end();
1061 while (iter_e != iter_e_end)
1079 std::cout <<
"Information of current complex edge (" << i <<
"/" << selected_complex_edges.size() <<
"): " << std::endl;
1080 std::cout <<
"\tedge id: " <<
get(edge_idm, *iter_e) << std::endl;
1081 std::cout <<
"\tsource vertex: " <<
get(vertex_idm,
source(*iter_e, *ptr_mesh)) << std::endl;
1082 std::cout <<
"\ttarget vertex: " <<
get(vertex_idm,
target(*iter_e, *ptr_mesh)) << std::endl;
1083 std::cout <<
"\tdegree: " <<
degree(*iter_e, *ptr_mesh) << std::endl;
1087 auto faces_range_pair =
in_edges(*iter_e, *ptr_mesh);
1088 std::set<face_descriptor> current_faces(faces_range_pair.first, faces_range_pair.second),
1090 std::map<int, edge_descriptor> face_id_to_edge;
1091 std::map<vertex_descriptor, vertex_descriptor> v_old_to_v_new, v_new_to_old;
1093 while (!current_faces.empty())
1095 face_descriptor current_f = *current_faces.begin();
1096 int current_id = ptr_mesh->template GetProperty< AIFMeshT::face_type::ptr, int >(
1097 "f:2_manifold_component_seg", current_f->GetIndex());
1100 face_id_to_edge.insert(std::make_pair(current_id, *iter_e));
1102 else if (face_id_to_edge.find(current_id) == face_id_to_edge.end())
1104 std::cout <<
"create a new edge" << std::endl;
1106 face_id_to_edge.insert(std::make_pair(current_id, e_tmp));
1109 auto iter_f = current_faces.begin(), iter_f_end = current_faces.end();
1110 for (; iter_f != iter_f_end; ++iter_f)
1112 if (ptr_mesh->template GetProperty< AIFMeshT::face_type::ptr, int >(
1113 "f:2_manifold_component_seg", (*iter_f)->GetIndex()) != current_id)
1114 next_faces.insert(*iter_f);
1130 face_id_to_edge[current_id],
1134 std::cout <<
"\torientation: " <<
get(vertex_idm, v_pe_old) <<
" -> " <<
get(vertex_idm, v_ae_old);
1135 std::cout <<
"\treplaced by: " <<
get(vertex_idm, v_old_to_v_new[v_pe_old]) <<
" -> " <<
get(vertex_idm, v_old_to_v_new[v_ae_old]) <<
" with edge id: " <<
get(edge_idm, face_id_to_edge[current_id]);
1136 std::cout << std::endl;
1140 bool is_the_last =
true;
1141 auto iter_f2 = iter_f;
1143 for (; iter_f2 != iter_f_end; ++iter_f2)
1144 if (ptr_mesh->template GetProperty< AIFMeshT::face_type::ptr, int >(
1145 "f:2_manifold_component_seg", (*iter_f2)->GetIndex()) == current_id)
1147 is_the_last =
false;
1163 current_faces.swap(next_faces);
1168 auto iter_map = face_id_to_edge.begin(), iter_map_e = face_id_to_edge.end();
1169 for (; iter_map != iter_map_e; ++iter_map)
1171 auto v_tmp =
source(iter_map->second, *ptr_mesh);
1175 if (make_2_mani_not_2_mani ==
"y")
1176 cut_vertices.push_back(v_tmp);
1178 if (colorize_mesh ==
"y")
1180 "v:color", v_tmp->GetIndex(), blue);
1182 v_tmp =
target(iter_map->second, *ptr_mesh);
1186 if (make_2_mani_not_2_mani ==
"y")
1187 cut_vertices.push_back(v_tmp);
1189 if (colorize_mesh ==
"y")
1191 "v:color", v_tmp->GetIndex(), blue);
1198 selected_complex_edges = remaining_complex_edges;
1201 if (!non_consitently_oriented_incident_face_edges.empty())
1203 std::cout <<
"New decomplexification step for an independent set of edges incident to 2 non-consitently oriented faces" << std::endl;
1204 selected_complex_edges = non_consitently_oriented_incident_face_edges;
1205 non_consitently_oriented_incident_face_edges.clear();
1206 goto decomplexification;
1209 auto iter_v = cut_vertices.begin(), iter_v_end = cut_vertices.end();
1210 while (iter_v != iter_v_end)
1229 std::cout <<
"degree of current cut vertex: " <<
degree(*iter_v, *ptr_mesh) << std::endl;
1232 std::cout <<
"current vertex is not more a cut vertex!" << std::endl;
1240 std::set<face_descriptor> current_faces(face_range.begin(), face_range.end()),
1242 std::map<int, vertex_descriptor> face_id_to_vertex;
1244 while (!current_faces.empty())
1246 face_descriptor current_f = *current_faces.begin();
1247 int current_id = ptr_mesh->template GetProperty< AIFMeshT::face_type::ptr, int >(
1248 "f:2_manifold_component_seg", current_f->GetIndex());
1252 face_id_to_vertex.insert(std::make_pair(current_id, *iter_v));
1258 face_descriptor current_f_tmp = current_f;
1259 while ((
degree(e1, *ptr_mesh) == 2) &&
1260 (current_faces.find(current_f_tmp) != current_faces.end()))
1263 auto it_f2 = face_range2.begin();
1264 for (; it_f2 != face_range2.end(); ++it_f2)
1266 if (*it_f2 != current_f_tmp)
1268 current_faces.erase(current_f_tmp);
1269 current_f_tmp = *it_f2;
1275 if (current_f_tmp != current_f)
1276 current_faces.erase(current_f_tmp);
1277 if (
degree(e2, *ptr_mesh) == 2)
1278 current_faces.insert(current_f);
1279 while ((
degree(e2, *ptr_mesh) == 2) &&
1280 (current_faces.find(current_f) != current_faces.end()))
1283 auto it_f2 = face_range2.begin();
1284 for (; it_f2 != face_range2.end(); ++it_f2)
1286 if (*it_f2 != current_f)
1288 current_faces.erase(current_f);
1299 std::cout <<
"create a new vertex" << std::endl;
1301 auto p =
get(pos_pm, *iter_v);
1302 put(pos_pm, v_tmp, p);
1304 face_id_to_vertex.insert(std::make_pair(current_id, v_tmp));
1307 auto iter_f = current_faces.begin(), iter_f_end = current_faces.end();
1308 std::map<face_descriptor, bool> face_to_next;
1309 for (; iter_f != iter_f_end; ++iter_f)
1310 if (current_f == *iter_f)
1311 face_to_next[*iter_f] =
false;
1313 face_to_next[*iter_f] =
false;
1315 face_to_next[*iter_f] =
true;
1316 iter_f = current_faces.begin();
1317 for (; iter_f != iter_f_end; ++iter_f)
1319 if (face_to_next[*iter_f])
1320 next_faces.insert(*iter_f);
1329 auto it_e = edge_range.begin();
1330 for (; it_e != edge_range.end(); ++it_e)
1343 current_faces.swap(next_faces);
1349 std::cout <<
"failed to correct current vertex!" << std::endl;
1356 my_writer.
write(res_mesh,
1361 std::cout <<
"writing failed";
1376 my_writer.
write(ptr_mesh,
1380 my_writer.
write(ptr_mesh,
1386 std::cout <<
"writing failed";
1390 std::cout <<
"The mesh file named "
1393 if (nb_isolated_vertices > 0 || nb_t_junction_vertices > 0 || nb_cut_vertices > 0 || nb_isolated_edges > 0 ||
1394 nb_dangling_edges > 0 || nb_complex_edges > 0 || nb_non_consitently_oriented_incident_face_edges > 0 )
1395 std::cout <<
" is not 2-manifold " << std::endl;
1397 std::cout <<
" is 2-manifold" << std::endl;
1399 std::string prefix =
1400 (remove_isolated_elements ==
"y")
1401 ?
"Number of removed isolated"
1402 :
"Number of isolated";
1403 std::cout << prefix <<
" vertices: " << nb_isolated_vertices << std::endl;
1404 std::cout << prefix <<
" edges: " << nb_isolated_edges << std::endl;
1405 std::cout << prefix <<
" faces (not removed yet): " << nb_isolated_faces << std::endl;
1407 prefix = (resolve_vertices_with_similar_incident_edges ==
"y")
1408 ?
"Number of resolved vertices with similar incident edges: "
1409 :
"Number of vertices with similar incident edges: ";
1410 std::cout << prefix << nb_vertices_with_similar_incident_edges << std::endl;
1412 std::cout <<
"Number of T-junction vertices: " << nb_t_junction_vertices << std::endl;
1413 std::cout <<
"Number of cut vertices: " << nb_cut_vertices << std::endl;
1414 std::cout <<
"Number of dangling edges: " << nb_dangling_edges << std::endl;
1415 std::cout <<
"Number of complex edges: " << nb_complex_edges;
1416 if(remaining_complex_edges.empty())
1417 std::cout << std::endl;
1419 std::cout <<
" (" << remaining_complex_edges.size() <<
" not resolved due to local dependency). " << std::endl;
1420 std::cout <<
"Number of edges incident to 2 faces with inconsistent orientation: " << nb_non_consitently_oriented_incident_face_edges << std::endl;
1421 std::cout <<
"Number of surface border edges: " << nb_border_edges << std::endl;
1422 std::cout <<
"Number of degenerated faces: " << nb_degenerated_faces << std::endl;
1424 return EXIT_SUCCESS;
1430 if(narg < 3 || narg > 6)
1432 std::cerr <<
"Cannot proceed arguments. Please use " << argv[0]
1433 <<
" meshfilename_or_meshfolder colorize_mesh [remove_isolated_elements "
1434 "[resolve_vertices_with_similar_incident_edges [make_2_mani_not_2_mani]]]"
1436 return EXIT_FAILURE;
1438 std::string input_path(argv[1]);
1439 if (!boost::filesystem::exists(input_path) && !boost::filesystem::is_directory(input_path))
1441 std::cerr << input_path <<
" does not exist. Exit. " << std::endl;
1442 return EXIT_FAILURE;
1444 std::string colorize_mesh = (argv[2]);
1446 return EXIT_FAILURE;
1447 std::string remove_isolated_elements(((narg > 3) ? argv[3] :
"n"));
1448 if (!
argument_analysis(remove_isolated_elements,
"removing of isolated elements",
true))
1449 return EXIT_FAILURE;
1450 std::string resolve_vertices_with_similar_incident_edges(
1451 ((narg > 4) ? argv[4] :
"n"));
1452 if (!
argument_analysis(resolve_vertices_with_similar_incident_edges,
"resolving similar/duplicate incident edges",
true))
1453 return EXIT_FAILURE;
1454 std::string make_2_mani_not_2_mani(((narg > 5) ? argv[5] :
"n"));
1455 if (!
argument_analysis(make_2_mani_not_2_mani,
"resolving not 2-manifold elements",
true))
1456 return EXIT_FAILURE;
1458 if(!boost::filesystem::is_directory(input_path))
1461 remove_isolated_elements,
1462 resolve_vertices_with_similar_incident_edges,
1463 make_2_mani_not_2_mani);
1467 boost::filesystem::directory_iterator end_iter;
1468 for (boost::filesystem::directory_iterator dir_itr(input_path);
1469 dir_itr != end_iter;
1474 if (boost::filesystem::is_directory(dir_itr->status()))
1476 std::string dir_name_without_base = dir_itr->path().string();
1478 std::string command =
"\"";
1479 for (
int i = 0; i < narg; ++i)
1485 std::string cmd_tmp = argv[i];
1487 command +=
"\"" + cmd_tmp +
"\"";
1492 command +=
"\"" + dir_name_without_base +
"\"";
1495 command += std::string(argv[i]);
1499 command += std::string(
" ");
1502 int r = system(command.c_str());
1505 std::cerr <<
" the following command is run: " << command <<
" failed (child process generation issue)." << std::endl;
1510 else if (!boost::filesystem::is_regular_file(dir_itr->status()))
1516 catch (
const std::exception & ex)
1518 std::cout << dir_itr->path().filename() <<
" " << ex.what() << std::endl;
1521 if (dir_itr->path().extension().string() ==
".msh" || dir_itr->path().extension().string() ==
".off" || dir_itr->path().extension().string() ==
".obj"
1523 || dir_itr->path().extension().string() ==
".vtk" || dir_itr->path().extension().string() ==
".vtp" || dir_itr->path().extension().string() ==
".vtu"
1529 remove_isolated_elements,
1530 resolve_vertices_with_similar_incident_edges,
1531 make_2_mani_not_2_mani);
1537 return EXIT_SUCCESS;