From 9bcf8b040ee0fa50d451862f429a51055ec06848 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 22 Mar 2017 09:12:30 +0100 Subject: [PATCH] move corefinement specific code from PMP to Operations_on_polyhedra --- .../corefinement/Polyhedra_output_builder.h | 1 + .../corefinement/connected_components.h | 343 ++++++++++++++++++ .../connected_components.h | 307 +--------------- .../test_corefinement_bool_op.cpp | 1 - 4 files changed, 347 insertions(+), 305 deletions(-) create mode 100644 Operations_on_polyhedra/include/CGAL/internal/corefinement/connected_components.h diff --git a/Operations_on_polyhedra/include/CGAL/internal/corefinement/Polyhedra_output_builder.h b/Operations_on_polyhedra/include/CGAL/internal/corefinement/Polyhedra_output_builder.h index 808d9644a71..ac98a06a7ab 100644 --- a/Operations_on_polyhedra/include/CGAL/internal/corefinement/Polyhedra_output_builder.h +++ b/Operations_on_polyhedra/include/CGAL/internal/corefinement/Polyhedra_output_builder.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff --git a/Operations_on_polyhedra/include/CGAL/internal/corefinement/connected_components.h b/Operations_on_polyhedra/include/CGAL/internal/corefinement/connected_components.h new file mode 100644 index 00000000000..6356c6f5899 --- /dev/null +++ b/Operations_on_polyhedra/include/CGAL/internal/corefinement/connected_components.h @@ -0,0 +1,343 @@ +// Copyright (c) 2011, 2015 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Sebastien Loriot and Andreas Fabri + +#ifndef CGAL_INTERNAL_POLYHEDRON_SUBSET_EXTRACTION_H +#define CGAL_INTERNAL_POLYHEDRON_SUBSET_EXTRACTION_H + +#include + + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace CGAL { + namespace internal{ + namespace corefinement{ + +template +struct Compare_handle_ptr{ + typedef typename Polyhedron::Facet_const_handle Facet_const_handle; + typedef typename Polyhedron::Vertex_const_handle Vertex_const_handle; + + bool operator()(Facet_const_handle f1,Facet_const_handle f2) const { + return &(*f1) < &(*f2); + } + + bool operator()(Vertex_const_handle v1,Vertex_const_handle v2) const { + return &(*v1) < &(*v2); + } +}; + +struct Dummy_true{ + template + bool operator()(T) const {return true;} +}; + +template +class Build_polyhedron_subset : public ::CGAL::Modifier_base { + typedef typename Polyhedron::Facet_const_handle Facet_const_handle; + typedef typename Polyhedron::Vertex_const_handle Vertex_const_handle; + typedef typename Polyhedron::Halfedge_const_handle Halfedge_const_handle; + + typedef typename HDS::Vertex::Point Point; + std::list points; + std::list< std::vector > facets; + + template + typename Polyhedron::Halfedge_const_handle get_facet_halfedge(Facet_iterator facet_it) const + { + return (*facet_it)->halfedge(); + } + + typename Polyhedron::Halfedge_const_handle get_facet_halfedge(typename Polyhedron::Facet_const_handle facet) const + { + return facet->halfedge(); + } + +public: + template + Build_polyhedron_subset(const Polyhedron&,Facets_const_iterator begin,Facets_const_iterator end) + { + typedef std::map > Vertices; + Vertices vertices; + unsigned int index=0; + //get vertices and get face description relatively to the restricted set of vertices + for (Facets_const_iterator it=begin;it!=end;++it) + { + Halfedge_const_handle start=get_facet_halfedge(it); + Halfedge_const_handle curr=start; + facets.push_back(std::vector()); + std::vector& indices = facets.back(); + do{ + bool is_new_vertex; + typename Vertices::iterator it_vertex; + ::CGAL::cpp11::tie(it_vertex,is_new_vertex)=vertices.insert(std::make_pair(curr->vertex(),index)); + if (is_new_vertex) { + ++index; + points.push_back(curr->vertex()); + } + indices.push_back(it_vertex->second); + curr=curr->next(); + }while(curr!=start); + } + } + + void operator()( HDS& hds) { + ::CGAL::Polyhedron_incremental_builder_3 B( hds, true); + B.begin_surface( points.size(), facets.size() ); + for (typename std::list::iterator it=points.begin();it!=points.end();++it) + B.add_vertex((*it)->point()); + for (typename std::list< std::vector >::iterator + it=facets.begin();it!=facets.end();++it) + { + B.begin_facet(); + for (std::vector::iterator it_i=it->begin();it_i!=it->end();++it_i) + B.add_vertex_to_facet(*it_i); + B.end_facet(); + } + B.end_surface(); + } +}; + + + +template +void extract_connected_components( + Polyhedron& P, + const Adjacency_criterium& adjacent, + CGAL::Union_find::Facet_handle>& uf, + Face_to_UF_handle_map& map_f2h, + Result& result + ) +{ + typedef typename internal_IOP::Polyhedron_types_with_mpl::Facet_handle Facet_handle; + typedef typename internal_IOP::Polyhedron_types_with_mpl::Facet_iterator Facet_iterator; + typedef typename internal_IOP::Polyhedron_types_with_mpl::Halfedge_handle Halfedge_handle; + typedef ::CGAL::Union_find UF; + typedef typename UF::handle UF_handle; + typedef typename UF::iterator UF_iterator; + +//init union-find: each facet is in its own set + for (Facet_iterator it=P.facets_begin();it!=P.facets_end();++it){ + map_f2h.insert(std::make_pair(it,uf.make_set(it))); + } +//merge 2 facets if they share a common edge + for (Facet_iterator it=P.facets_begin();it!=P.facets_end();++it){ + Facet_handle facet=it; + + UF_handle current=map_f2h.find(it)->second; + std::vector neighbors; + Halfedge_handle hedge=facet->halfedge(); + do + { + neighbors.push_back( hedge->opposite() ); + hedge=hedge->next(); + } + while(hedge!=facet->halfedge()); + + std::size_t nb_edges=neighbors.size(); + for (std::size_t i=0;iis_border() ) continue; + UF_handle neigh=map_f2h.find(neighbors[i]->facet())->second; + if ( adjacent(neighbors[i]) && !uf.same_set(current,neigh) ){ + uf.unify_sets(current,neigh); + } + } + } + +//recover merged sets + for (UF_iterator it=uf.begin();it!=uf.end();++it){ + UF_handle master=uf.find(it); + result[*master].push_back(*it); + } +} + +template +void extract_connected_components(const Polyhedron& P,const Adjacency_criterium& adjacent,Output_iterator out) +{ + typedef typename Polyhedron::Facet_const_handle Facet_const_handle; + typedef ::CGAL::Union_find UF; + typedef typename UF::handle UF_handle; + typedef std::map,Compare_handle_ptr > Result; + typedef std::map > Facet_to_handle_map; + + UF uf; + Facet_to_handle_map map_f2h; + Result result; + + extract_connected_components(P,adjacent,uf,map_f2h,result); + + for (typename Result::iterator it=result.begin();it!=result.end();++it) + { + typedef std::list Facets; + const Facets& facets=it->second; + Polyhedron new_poly; + Build_polyhedron_subset modifier(new_poly,facets.begin(),facets.end()); + new_poly.delegate(modifier); + *out++=new_poly; + } +} + +template +void mark_connected_components(Polyhedron& P, const Adjacency_criterium& adjacent, Face_marker& face_marker) +{ + typedef typename Polyhedron::Facet_handle Facet_handle; + typedef ::CGAL::Union_find UF; + typedef typename UF::handle UF_handle; + typedef std::map,Compare_handle_ptr > Result; + typedef std::map > Facet_to_handle_map; + + UF uf; + Facet_to_handle_map map_f2h; + Result result; + + extract_connected_components(P,adjacent,uf,map_f2h,result); + + for (typename Result::iterator it=result.begin();it!=result.end();++it) + { + face_marker.start_new_connected_component(); + typedef std::list Facets; + const Facets& facets=it->second; + face_marker.mark(facets.begin(),facets.end()); + } +} + +template +OutputIterator +mark_connected_components(Polyhedron& P, const Adjacency_criterium& adjacent, Face_marker& face_marker, OutputIterator out) +{ + typedef typename Polyhedron::Facet_handle Facet_handle; + typedef ::CGAL::Union_find UF; + typedef typename UF::handle UF_handle; + typedef std::map,Compare_handle_ptr > Result; + typedef std::map > Facet_to_handle_map; + + UF uf; + Facet_to_handle_map map_f2h; + Result result; + + extract_connected_components(P,adjacent,uf,map_f2h,result); + + for (typename Result::iterator it=result.begin();it!=result.end();++it) + { + face_marker.start_new_connected_component(); + typedef std::list Facets; + const Facets& facets=it->second; + face_marker.mark(facets.begin(),facets.end()); + *out++=*facets.begin(); + } + return out; +} + +template +void extract_connected_components(const Polyhedron& P,Output_iterator out) +{ + extract_connected_components(P,Dummy_true(),out); +} + +template +std::size_t +init_facet_indices( + const Polyhedron& P, + Polyhedron_facet_index_map facet_index_map) +{ + //init facet indices + std::size_t index=0; + for (typename Polyhedron::Facet_const_iterator fit=P.facets_begin(), + fit_end=P.facets_end(); + fit!=fit_end; ++fit) + { + put(facet_index_map, fit, index++); + } + return index; +} + +// alternative method by propagation +template +std::size_t +mark_connected_components_v2( + const Polyhedron& P, + const Adjacency_criterium& adjacent, + Polyhedron_facet_index_map facet_index_map, + std::vector& patch_ids, + std::vector& patch_sizes) +{ + typedef typename Polyhedron::Halfedge_const_handle Halfedge_handle; + + std::size_t max_id=(std::numeric_limits::max)(); + patch_ids.clear(); + patch_ids.resize(P.size_of_facets(), max_id); + + //traversal of the facets to discover connected components + std::size_t patch_id=0; + for (typename Polyhedron::Facet_const_iterator fit=P.facets_begin(), + fit_end=P.facets_end(); + fit!=fit_end; ++fit) + { + std::size_t index=get(facet_index_map, fit); + if ( patch_ids[index]==max_id ) + { + patch_sizes.push_back(0); + patch_ids[index]=patch_id;// set patch id + ++(patch_sizes.back()); + std::vector queue; + if ( adjacent(fit->halfedge()) ) + queue.push_back( fit->halfedge()->opposite() ); + if ( adjacent(fit->halfedge()->next()) ) + queue.push_back( fit->halfedge()->next()->opposite() ); + if ( adjacent(fit->halfedge()->next()->next()) ) + queue.push_back( fit->halfedge()->next()->next()->opposite() ); + while (!queue.empty()) + { + Halfedge_handle h=queue.back(); + queue.pop_back(); + index=get(facet_index_map, h->facet()); + if ( patch_ids[index]!=max_id ) continue; + patch_ids[index]=patch_id; + ++(patch_sizes.back()); + if ( adjacent(h->next()) ) + queue.push_back( h->next()->opposite() ); + if ( adjacent(h->next()->next()) ) + queue.push_back( h->next()->next()->opposite() ); + } + ++patch_id; + } + } + + return patch_id; +} + +} } // end of namespace internal::corefinement + + +} // namespace CGAL + +#endif //CGAL_INTERNAL_POLYHEDRON_SUBSET_EXTRACTION_H diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h index a5ef2f5b2ac..17d09b180c7 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h @@ -18,8 +18,8 @@ // // Author(s) : Sebastien Loriot and Andreas Fabri -#ifndef CGAL_INTERNAL_POLYHEDRON_SUBSET_EXTRACTION_H -#define CGAL_INTERNAL_POLYHEDRON_SUBSET_EXTRACTION_H +#ifndef CGAL_POLYGON_MESH_PROCESSING_CONNECTED_COMPONENTS_H +#define CGAL_POLYGON_MESH_PROCESSING_CONNECTED_COMPONENTS_H #include @@ -39,13 +39,9 @@ #include #include -#include -#include -#include #include #include #include -#include #include #include @@ -58,303 +54,6 @@ namespace CGAL { - namespace internal{ - namespace corefinement{ - -template -struct Compare_handle_ptr{ - typedef typename Polyhedron::Facet_const_handle Facet_const_handle; - typedef typename Polyhedron::Vertex_const_handle Vertex_const_handle; - - bool operator()(Facet_const_handle f1,Facet_const_handle f2) const { - return &(*f1) < &(*f2); - } - - bool operator()(Vertex_const_handle v1,Vertex_const_handle v2) const { - return &(*v1) < &(*v2); - } -}; - -struct Dummy_true{ - template - bool operator()(T) const {return true;} -}; - -template -class Build_polyhedron_subset : public ::CGAL::Modifier_base { - typedef typename Polyhedron::Facet_const_handle Facet_const_handle; - typedef typename Polyhedron::Vertex_const_handle Vertex_const_handle; - typedef typename Polyhedron::Halfedge_const_handle Halfedge_const_handle; - - typedef typename HDS::Vertex::Point Point; - std::list points; - std::list< std::vector > facets; - - template - typename Polyhedron::Halfedge_const_handle get_facet_halfedge(Facet_iterator facet_it) const - { - return (*facet_it)->halfedge(); - } - - typename Polyhedron::Halfedge_const_handle get_facet_halfedge(typename Polyhedron::Facet_const_handle facet) const - { - return facet->halfedge(); - } - -public: - template - Build_polyhedron_subset(const Polyhedron&,Facets_const_iterator begin,Facets_const_iterator end) - { - typedef std::map > Vertices; - Vertices vertices; - unsigned int index=0; - //get vertices and get face description relatively to the restricted set of vertices - for (Facets_const_iterator it=begin;it!=end;++it) - { - Halfedge_const_handle start=get_facet_halfedge(it); - Halfedge_const_handle curr=start; - facets.push_back(std::vector()); - std::vector& indices = facets.back(); - do{ - bool is_new_vertex; - typename Vertices::iterator it_vertex; - ::CGAL::cpp11::tie(it_vertex,is_new_vertex)=vertices.insert(std::make_pair(curr->vertex(),index)); - if (is_new_vertex) { - ++index; - points.push_back(curr->vertex()); - } - indices.push_back(it_vertex->second); - curr=curr->next(); - }while(curr!=start); - } - } - - void operator()( HDS& hds) { - ::CGAL::Polyhedron_incremental_builder_3 B( hds, true); - B.begin_surface( points.size(), facets.size() ); - for (typename std::list::iterator it=points.begin();it!=points.end();++it) - B.add_vertex((*it)->point()); - for (typename std::list< std::vector >::iterator - it=facets.begin();it!=facets.end();++it) - { - B.begin_facet(); - for (std::vector::iterator it_i=it->begin();it_i!=it->end();++it_i) - B.add_vertex_to_facet(*it_i); - B.end_facet(); - } - B.end_surface(); - } -}; - - - -template -void extract_connected_components( - Polyhedron& P, - const Adjacency_criterium& adjacent, - CGAL::Union_find::Facet_handle>& uf, - Face_to_UF_handle_map& map_f2h, - Result& result - ) -{ - typedef typename internal_IOP::Polyhedron_types_with_mpl::Facet_handle Facet_handle; - typedef typename internal_IOP::Polyhedron_types_with_mpl::Facet_iterator Facet_iterator; - typedef typename internal_IOP::Polyhedron_types_with_mpl::Halfedge_handle Halfedge_handle; - typedef ::CGAL::Union_find UF; - typedef typename UF::handle UF_handle; - typedef typename UF::iterator UF_iterator; - -//init union-find: each facet is in its own set - for (Facet_iterator it=P.facets_begin();it!=P.facets_end();++it){ - map_f2h.insert(std::make_pair(it,uf.make_set(it))); - } -//merge 2 facets if they share a common edge - for (Facet_iterator it=P.facets_begin();it!=P.facets_end();++it){ - Facet_handle facet=it; - - UF_handle current=map_f2h.find(it)->second; - std::vector neighbors; - Halfedge_handle hedge=facet->halfedge(); - do - { - neighbors.push_back( hedge->opposite() ); - hedge=hedge->next(); - } - while(hedge!=facet->halfedge()); - - std::size_t nb_edges=neighbors.size(); - for (std::size_t i=0;iis_border() ) continue; - UF_handle neigh=map_f2h.find(neighbors[i]->facet())->second; - if ( adjacent(neighbors[i]) && !uf.same_set(current,neigh) ){ - uf.unify_sets(current,neigh); - } - } - } - -//recover merged sets - for (UF_iterator it=uf.begin();it!=uf.end();++it){ - UF_handle master=uf.find(it); - result[*master].push_back(*it); - } -} - -template -void extract_connected_components(const Polyhedron& P,const Adjacency_criterium& adjacent,Output_iterator out) -{ - typedef typename Polyhedron::Facet_const_handle Facet_const_handle; - typedef ::CGAL::Union_find UF; - typedef typename UF::handle UF_handle; - typedef std::map,Compare_handle_ptr > Result; - typedef std::map > Facet_to_handle_map; - - UF uf; - Facet_to_handle_map map_f2h; - Result result; - - extract_connected_components(P,adjacent,uf,map_f2h,result); - - for (typename Result::iterator it=result.begin();it!=result.end();++it) - { - typedef std::list Facets; - const Facets& facets=it->second; - Polyhedron new_poly; - Build_polyhedron_subset modifier(new_poly,facets.begin(),facets.end()); - new_poly.delegate(modifier); - *out++=new_poly; - } -} - -template -void mark_connected_components(Polyhedron& P, const Adjacency_criterium& adjacent, Face_marker& face_marker) -{ - typedef typename Polyhedron::Facet_handle Facet_handle; - typedef ::CGAL::Union_find UF; - typedef typename UF::handle UF_handle; - typedef std::map,Compare_handle_ptr > Result; - typedef std::map > Facet_to_handle_map; - - UF uf; - Facet_to_handle_map map_f2h; - Result result; - - extract_connected_components(P,adjacent,uf,map_f2h,result); - - for (typename Result::iterator it=result.begin();it!=result.end();++it) - { - face_marker.start_new_connected_component(); - typedef std::list Facets; - const Facets& facets=it->second; - face_marker.mark(facets.begin(),facets.end()); - } -} - -template -OutputIterator -mark_connected_components(Polyhedron& P, const Adjacency_criterium& adjacent, Face_marker& face_marker, OutputIterator out) -{ - typedef typename Polyhedron::Facet_handle Facet_handle; - typedef ::CGAL::Union_find UF; - typedef typename UF::handle UF_handle; - typedef std::map,Compare_handle_ptr > Result; - typedef std::map > Facet_to_handle_map; - - UF uf; - Facet_to_handle_map map_f2h; - Result result; - - extract_connected_components(P,adjacent,uf,map_f2h,result); - - for (typename Result::iterator it=result.begin();it!=result.end();++it) - { - face_marker.start_new_connected_component(); - typedef std::list Facets; - const Facets& facets=it->second; - face_marker.mark(facets.begin(),facets.end()); - *out++=*facets.begin(); - } - return out; -} - -template -void extract_connected_components(const Polyhedron& P,Output_iterator out) -{ - extract_connected_components(P,Dummy_true(),out); -} - -template -std::size_t -init_facet_indices( - const Polyhedron& P, - Polyhedron_facet_index_map facet_index_map) -{ - //init facet indices - std::size_t index=0; - for (typename Polyhedron::Facet_const_iterator fit=P.facets_begin(), - fit_end=P.facets_end(); - fit!=fit_end; ++fit) - { - put(facet_index_map, fit, index++); - } - return index; -} - -// alternative method by propagation -template -std::size_t -mark_connected_components_v2( - const Polyhedron& P, - const Adjacency_criterium& adjacent, - Polyhedron_facet_index_map facet_index_map, - std::vector& patch_ids, - std::vector& patch_sizes) -{ - typedef typename Polyhedron::Halfedge_const_handle Halfedge_handle; - - std::size_t max_id=(std::numeric_limits::max)(); - patch_ids.clear(); - patch_ids.resize(P.size_of_facets(), max_id); - - //traversal of the facets to discover connected components - std::size_t patch_id=0; - for (typename Polyhedron::Facet_const_iterator fit=P.facets_begin(), - fit_end=P.facets_end(); - fit!=fit_end; ++fit) - { - std::size_t index=get(facet_index_map, fit); - if ( patch_ids[index]==max_id ) - { - patch_sizes.push_back(0); - patch_ids[index]=patch_id;// set patch id - ++(patch_sizes.back()); - std::vector queue; - if ( adjacent(fit->halfedge()) ) - queue.push_back( fit->halfedge()->opposite() ); - if ( adjacent(fit->halfedge()->next()) ) - queue.push_back( fit->halfedge()->next()->opposite() ); - if ( adjacent(fit->halfedge()->next()->next()) ) - queue.push_back( fit->halfedge()->next()->next()->opposite() ); - while (!queue.empty()) - { - Halfedge_handle h=queue.back(); - queue.pop_back(); - index=get(facet_index_map, h->facet()); - if ( patch_ids[index]!=max_id ) continue; - patch_ids[index]=patch_id; - ++(patch_sizes.back()); - if ( adjacent(h->next()) ) - queue.push_back( h->next()->opposite() ); - if ( adjacent(h->next()->next()) ) - queue.push_back( h->next()->next()->opposite() ); - } - ++patch_id; - } - } - - return patch_id; -} - -} } // end of namespace internal::corefinement namespace Polygon_mesh_processing{ @@ -1104,4 +803,4 @@ void keep_connected_components(PolygonMesh& pmesh } // namespace CGAL -#endif //CGAL_INTERNAL_POLYHEDRON_SUBSET_EXTRACTION_H +#endif //CGAL_POLYGON_MESH_PROCESSING_CONNECTED_COMPONENTS_H diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_corefinement_bool_op.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_corefinement_bool_op.cpp index ec68cef857e..6b1d61c739d 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_corefinement_bool_op.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_corefinement_bool_op.cpp @@ -17,7 +17,6 @@ // includes for Operations on polyhedra #include #include -#include #include #include