diff --git a/.gitattributes b/.gitattributes index 0d53124ca05..b9bec66f61a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3716,6 +3716,8 @@ Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/fig/general_ Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/fig/general_collapse.pdf -text svneol=unset#application/pdf Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/fig/general_collapse.png -text svneol=unset#image/png Surface_mesh_simplification/examples/Surface_mesh_simplification/cube.off -text svneol=unset#application/octet-stream +Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_constrained_polyhedron.cmd -text +Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_constrained_polyhedron.cpp -text Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_enriched_polyhedron.cmd eol=lf Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_polyhedron.cmd eol=lf Surface_mesh_simplification/test/Surface_mesh_simplification/data/MODELS -text diff --git a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification/Surface_mesh_simplification.tex b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification/Surface_mesh_simplification.tex index e6bfb403c3f..1597360a2b8 100644 --- a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification/Surface_mesh_simplification.tex +++ b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification/Surface_mesh_simplification.tex @@ -311,6 +311,13 @@ and how to use a visitor policy to track the simplification process. \ccIncludeExampleCode{Surface_mesh_simplification/edge_collapse_enriched_polyhedron.cpp} +\subsubsection{Example with edges marked as non-removable} + +The following example shows how to use the optional named parameter \ccc{edge_is_border_map} to prevent +edges from being removed even if they are not really borders. + +\ccIncludeExampleCode{Surface_mesh_simplification/edge_collapse_constrained_polyhedron.cpp} + % +------------------------------------------------------------------------+ %%RefPage: end of main body, begin of sfsooter % EOF diff --git a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/EdgeCollapseSimplificationVisitor.tex b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/EdgeCollapseSimplificationVisitor.tex index ce9bd3bcd11..cf43694f3f3 100644 --- a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/EdgeCollapseSimplificationVisitor.tex +++ b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/EdgeCollapseSimplificationVisitor.tex @@ -31,11 +31,11 @@ The several callbacks given as member functions in the visitor are called from c \ccGlue \ccNestedType{FT}{A field type representing the collapse cost}{} \ccGlue - \ccTypedef{typename boost::graph_traits::edge_descriptor edge_descriptor;} - {A {\sc Bgl} edge descriptor representing an undirected edge of the surface.} + \ccNestedType{Profile} + {The type of the edge profile cache. Must be a model of the \ccc{EdgeProfile} concept.}{} \ccGlue \ccTypedef{typename CGAL::halfedge_graph_traits::Point Point;} - {The point type of the vertex. Must be a model of \ccc{Point_3}.} + {The point type for the surface vertex. Must be a model of \ccc{Point_3}.} \ccGlue \ccNestedType{size_type}{An integer type representing the number of edges}{} @@ -58,27 +58,24 @@ The several callbacks given as member functions in the visitor are called from c } \ccMethod - {void OnCollected( edge_descriptor const& edge - , ECM& surface - ); + {void OnCollected( Profile const& profile, boost::optional cost ); } {Called during the {\em collecting phase} (when a cost is assigned to the edges), - for each \ccc{edge} collected. + for each edge collected. } \ccMethod - {void OnSelected(edge_descriptor const& edge - ,ECM& surface - ,boost::optional cost - ,size_type initial_count - ,size_type current_count + {void OnSelected( Profile const& profile + , boost::optional cost + , size_type initial_count + , size_type current_count ); } {Called during the {\em processing phase} (when edges are collapsed), - for each \ccc{edge} that is selected.\\ + for each edge that is selected.\\ This method is called before the algorithm checks if the edge is collapsable.\\ - \ccc{cost} indicates the current collapse cost for the \ccc{edge}. + \ccc{cost} indicates the current collapse cost for the edge. If absent (meaning that it could not be computed) the edge will not be collapsed.\\ \ccc{initial_count} and \ccc{current_count} refer to @@ -86,23 +83,20 @@ The several callbacks given as member functions in the visitor are called from c } \ccMethod - {void OnCollapsing( edge_descriptor const& edge - , ECM& surface + {void OnCollapsing( Profile const& profile , boost::optional placement ); } - {Called when \ccc{edge} is about to be collapsed and replaced by a vertex + {Called when an edge is about to be collapsed and replaced by a vertex whose position is \ccc{*placement}.\\ If \ccc{placement} is absent (meaning that it could not be computed) the edge will not be collapsed. } \ccMethod - {void OnNonCollapsable( edge_descriptor const& edge - , ECM& surface - ); + {void OnNonCollapsable( Profile const& profile ); } - {Called for each selected \ccc{edge} which cannot be + {Called for each selected edge which cannot be collapsed because doing so would change the topological type of the surface (turn it into a non-manifold for instance). diff --git a/Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_constrained_polyhedron.cmd b/Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_constrained_polyhedron.cmd new file mode 100644 index 00000000000..5cea844d830 --- /dev/null +++ b/Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_constrained_polyhedron.cmd @@ -0,0 +1 @@ +cube.off diff --git a/Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_constrained_polyhedron.cpp b/Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_constrained_polyhedron.cpp new file mode 100644 index 00000000000..f0d957ea907 --- /dev/null +++ b/Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_constrained_polyhedron.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include + +// Adaptor for Polyhedron_3 +#include + +// Simplification function +#include + +// Stop-condition policy +#include + +// Map used to mark edges as fixed +#include + +typedef CGAL::Simple_cartesian Kernel; +typedef CGAL::Polyhedron_3 Surface; + +namespace SMS = CGAL::Surface_mesh_simplification ; + +// +// BGL property map which indicates whether an edge is border OR is marked as non-removable +// +class Constrains_map : public boost::put_get_helper +{ +public: + + typedef boost::readable_property_map_tag category; + typedef bool value_type; + typedef bool reference; + typedef typename boost::graph_traits::edge_descriptor key_type; + + Constrains_map() : mConstrains(false) {} + + reference operator[](key_type const& e) const { return e->is_border() || is_constrained(e) ; } + + void set_is_constrained ( key_type const& e, bool is ) { mConstrains[e]=is; } + + bool is_constrained( key_type const& e ) const { return mConstrains.is_defined(e) ? mConstrains[e] : false ; } + +private: + + typedef CGAL::Unique_hash_map mConstrains ; + +}; + +int main( int argc, char** argv ) +{ + Surface surface; + + std::ifstream is(argv[1]) ; is >> surface ; + + // This is a stop predicate (defines when the algorithm terminates). + // In this example, the simplification stops when the number of undirected edges + // left in the surface drops below the specified number (1000) + SMS::Count_stop_predicate stop(10); + + Constrains_map constrains_map ; + + + // This example marks ALL edges as non-removable, but a real world application would mark only selected ones. + for( Surface::Halfedge_iterator eb = surface.halfedges_begin(), ee = surface.halfedges_end() ; eb != ee ; ++ eb ) + constrains_map.set_is_constrained(eb,true); + + // This the actual call to the simplification algorithm. + // The surface and stop conditions are mandatory arguments. + // The index maps are needed because the vertices and edges + // of this surface lack an "id()" field. + int r = SMS::edge_collapse + (surface + ,stop + ,CGAL::vertex_index_map(boost::get(CGAL::vertex_external_index,surface)) + .edge_index_map (boost::get(CGAL::edge_external_index ,surface)) + .edge_is_border_map(constrains_map) + ); + + std::cout << "\nFinished...\n" << r << " edges removed.\n" + << (surface.size_of_halfedges()/2) << " final edges.\n" ; + + std::ofstream os( argc > 2 ? argv[2] : "out.off" ) ; os << surface ; + + return 0 ; +} + +// EOF //