From d3da0be12069ef1fc54b1147d31fda719f5ba7bc Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 4 Jan 2017 15:49:41 +0100 Subject: [PATCH] Fix detect_features() --- .../Polyhedral_mesh_domain_with_features_3.h | 138 ++++++++++++++---- 1 file changed, 109 insertions(+), 29 deletions(-) diff --git a/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h b/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h index 39490d4a06f..f70959fb004 100644 --- a/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h +++ b/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include #include @@ -74,9 +76,9 @@ struct Angle_tester vertex_descriptor v2 = target(*out_edge_it++, g); CGAL_assertion(out_edge_it == out_edges_end); - const typename Kernel::Point_3& p = v->point(); - const typename Kernel::Point_3& p1 = v1->point(); - const typename Kernel::Point_3& p2 = v2->point(); + const typename Kernel::Point_3& p = g[v]; + const typename Kernel::Point_3& p1 = g[v1]; + const typename Kernel::Point_3& p2 = g[v2]; return (CGAL::angle(p1, p, p2) == CGAL::ACUTE); } @@ -106,17 +108,21 @@ struct Is_border_edge { } }; // end Is_featured_edge -template +template struct Extract_polyline_with_context_visitor { typedef typename Polyhedral_mesh_domain::Polyhedron Polyhedron; std::vector& polylines; const Polyhedron& polyhedron; + const Graph& graph; Extract_polyline_with_context_visitor (const Polyhedron& polyhedron, + const Graph& graph, typename std::vector& polylines) - : polylines(polylines), polyhedron(polyhedron) + : polylines(polylines), polyhedron(polyhedron), graph(graph) {} void start_new_polyline() @@ -124,33 +130,30 @@ struct Extract_polyline_with_context_visitor polylines.push_back(Polyline_with_context()); } - void add_node(typename Polyhedron::Vertex_handle vd) + void add_node(typename boost::graph_traits::vertex_descriptor vd) { if(polylines.back().polyline_content.empty()) { - polylines.back().polyline_content.push_back(vd->point()); + polylines.back().polyline_content.push_back(graph[vd]); } } - void add_edge(typename boost::graph_traits::edge_descriptor ed) + void add_edge(typename boost::graph_traits::edge_descriptor ed) { + typename boost::graph_traits::vertex_descriptor + s = source(ed, graph), + t = target(ed, graph); Polyline_with_context& polyline = polylines.back(); - typename Polyhedron::Halfedge_handle he = halfedge(ed, polyhedron); CGAL_assertion(!polyline.polyline_content.empty()); - if(polyline.polyline_content.back() != he->vertex()->point()) { - polyline.polyline_content.push_back(he->vertex()->point()); - } else if(polyline.polyline_content.back() != - he->opposite()->vertex()->point()) - { // if the edge is zero-length, it is ignored - polyline.polyline_content.push_back(he->opposite()->vertex()->point()); - } - typename Polyhedral_mesh_domain::Surface_patch_index_generator generator; - if(!is_border(he, polyhedron)) { - polyline.context.adjacent_patches_ids.insert(generator(he->face())); - } - he = he->opposite(); - if(!is_border(he, polyhedron)) { - polyline.context.adjacent_patches_ids.insert(generator(he->face())); + if(polyline.polyline_content.back() != graph[s]) { + polyline.polyline_content.push_back(graph[s]); + } else if(polyline.polyline_content.back() != graph[t]) { + // if the edge is zero-length, it is ignored + polyline.polyline_content.push_back(graph[t]); } + const typename boost::edge_bundle_type::type & + set_of_indices = graph[ed]; + polyline.context.adjacent_patches_ids.insert(set_of_indices.begin(), + set_of_indices.end()); } void end_polyline() @@ -197,6 +200,13 @@ class Polyhedral_mesh_domain_with_features_3 Polyhedron_, IGT_, TriangleAccessor, Use_patch_id_tag, Use_exact_intersection_construction_tag > > Base; + typedef boost::adjacency_list< + boost::setS, // this avoids parallel edges + boost::vecS, + boost::undirectedS, + typename Polyhedron_::Point, + typename Polyhedron_::Vertex::Set_of_indices> Featured_edges_copy; + public: typedef Polyhedron_ Polyhedron; @@ -375,7 +385,7 @@ void dump_graph_edges(std::ostream& out, const Graph& g) { vertex_descriptor s = source(e, g); vertex_descriptor t = target(e, g); - out << "2 " << s->point() << " " << t->point() << "\n"; + out << "2 " << g[s] << " " << g[t] << "\n"; } } @@ -396,12 +406,15 @@ detect_features(FT angle_in_degree, std::vector& poly) if (borders_detected_) return;//prevent from not-terminating + CGAL::Mesh_3::Detect_features_in_polyhedra detect_features; BOOST_FOREACH(Polyhedron& p, poly) { initialize_ts(p); // Get sharp features - Mesh_3::detect_features(p,angle_in_degree); + detect_features.detect_sharp_edges(p, angle_in_degree); + detect_features.detect_surface_patches(p); + detect_features.detect_vertices_incident_patches(p); internal::Mesh_3::Is_featured_edge is_featured_edge(p); @@ -420,20 +433,87 @@ add_features_from_split_graph_into_polylines(const Polyhedron& p, { typedef boost::filtered_graph Featured_edges_graph; - Featured_edges_graph graph(p, pred); + Featured_edges_graph orig_graph(p, pred); + + typedef Featured_edges_graph Graph; + typedef typename boost::graph_traits::vertex_descriptor Graph_vertex_descriptor; + typedef typename boost::graph_traits::edge_descriptor Graph_edge_descriptor; + typedef Featured_edges_copy G_copy; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + + G_copy g_copy; + { + const Featured_edges_graph& graph = orig_graph; + + typedef std::map P2vmap; + // TODO: replace this map by and unordered_map + P2vmap p2vmap; + + BOOST_FOREACH(Graph_vertex_descriptor v, vertices(graph)){ + vertex_descriptor vc; + typename P2vmap::iterator it = p2vmap.find(v->point()); + if(it == p2vmap.end()) { + vc = add_vertex(g_copy); + g_copy[vc] = v->point(); + p2vmap[v->point()] = vc; + } + } + + BOOST_FOREACH(Graph_edge_descriptor e, edges(graph)){ + vertex_descriptor vs = p2vmap[source(e,graph)->point()]; + vertex_descriptor vt = p2vmap[target(e,graph)->point()]; + if(vs == vt){ + std::cerr << "ignore self loop\n"; + }else{ + const std::pair pair = add_edge(vs,vt,g_copy); + typename Polyhedron::Halfedge_handle he = halfedge(e, p); + if(!is_border(he, p)) { + g_copy[pair.first].insert(he->face()->patch_id());; + } + he = he->opposite(); + if(!is_border(he, p)) { + g_copy[pair.first].insert(he->face()->patch_id());; + } + } + } + } + +#if CGAL_MESH_3_PROTECTION_DEBUG > 1 + {// DEBUG + dump_graph_edges("edges-graph.polylines.txt", g_copy); + } +#endif std::vector polylines; internal::Mesh_3::Extract_polyline_with_context_visitor< Polyhedral_mesh_domain_with_features_3, - Polyline_with_context - > visitor(p, polylines); + Polyline_with_context, + Featured_edges_copy + > visitor(p, g_copy, polylines); internal::Mesh_3::Angle_tester angle_tester; - split_graph_into_polylines(graph, visitor, angle_tester); + split_graph_into_polylines(g_copy, visitor, angle_tester); this->add_features_with_context(polylines.begin(), polylines.end()); +#if CGAL_MESH_3_PROTECTION_DEBUG > 1 + {//DEBUG + std::ofstream og("polylines_graph.polylines.txt"); + og.precision(17); + BOOST_FOREACH(const Polyline_with_context& poly, polylines) + { + og << poly.polyline_content.size() << " "; + BOOST_FOREACH(const Point_3& p, poly.polyline_content) + og << p << " "; + og << std::endl; + } + og.close(); + } +#endif // CGAL_MESH_3_PROTECTION_DEBUG > 1 + }