Added constrained example and updated visitor reference

This commit is contained in:
Fernando Cacciola 2009-04-29 20:47:50 +00:00
parent d2c99fc698
commit b7409a797d
5 changed files with 114 additions and 21 deletions

2
.gitattributes vendored
View File

@ -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.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/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/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_enriched_polyhedron.cmd eol=lf
Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_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 Surface_mesh_simplification/test/Surface_mesh_simplification/data/MODELS -text

View File

@ -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} \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 %%RefPage: end of main body, begin of sfsooter
% EOF % EOF

View File

@ -31,11 +31,11 @@ The several callbacks given as member functions in the visitor are called from c
\ccGlue \ccGlue
\ccNestedType{FT}{A field type representing the collapse cost}{} \ccNestedType{FT}{A field type representing the collapse cost}{}
\ccGlue \ccGlue
\ccTypedef{typename boost::graph_traits<ECM>::edge_descriptor edge_descriptor;} \ccNestedType{Profile}
{A {\sc Bgl} edge descriptor representing an undirected edge of the surface.} {The type of the edge profile cache. Must be a model of the \ccc{EdgeProfile} concept.}{}
\ccGlue \ccGlue
\ccTypedef{typename CGAL::halfedge_graph_traits<ECM>::Point Point;} \ccTypedef{typename CGAL::halfedge_graph_traits<ECM>::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 \ccGlue
\ccNestedType{size_type}{An integer type representing the number of edges}{} \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 \ccMethod
{void OnCollected( edge_descriptor const& edge {void OnCollected( Profile const& profile, boost::optional<FT> cost );
, ECM& surface
);
} }
{Called during the {\em collecting phase} (when a cost is assigned to the edges), {Called during the {\em collecting phase} (when a cost is assigned to the edges),
for each \ccc{edge} collected. for each edge collected.
} }
\ccMethod \ccMethod
{void OnSelected(edge_descriptor const& edge {void OnSelected( Profile const& profile
,ECM& surface , boost::optional<FT> cost
,boost::optional<double> cost , size_type initial_count
,size_type initial_count , size_type current_count
,size_type current_count
); );
} }
{Called during the {\em processing phase} (when edges are collapsed), {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 This method is called before the algorithm checks
if the edge is collapsable.\\ 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) If absent (meaning that it could not be computed)
the edge will not be collapsed.\\ the edge will not be collapsed.\\
\ccc{initial_count} and \ccc{current_count} refer to \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 \ccMethod
{void OnCollapsing( edge_descriptor const& edge {void OnCollapsing( Profile const& profile
, ECM& surface
, boost::optional<Point> placement , boost::optional<Point> 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}.\\ whose position is \ccc{*placement}.\\
If \ccc{placement} is absent (meaning that it could not be computed) If \ccc{placement} is absent (meaning that it could not be computed)
the edge will not be collapsed. the edge will not be collapsed.
} }
\ccMethod \ccMethod
{void OnNonCollapsable( edge_descriptor const& edge {void OnNonCollapsable( Profile const& profile );
, ECM& surface
);
} }
{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 collapsed because doing so would change the topological
type of the surface (turn it into a non-manifold type of the surface (turn it into a non-manifold
for instance). for instance).

View File

@ -0,0 +1,89 @@
#include <iostream>
#include <fstream>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
// Adaptor for Polyhedron_3
#include <CGAL/Surface_mesh_simplification/HalfedgeGraph_Polyhedron_3.h>
// Simplification function
#include <CGAL/Surface_mesh_simplification/edge_collapse.h>
// Stop-condition policy
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_stop_predicate.h>
// Map used to mark edges as fixed
#include <CGAL/Unique_hash_map.h>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef CGAL::Polyhedron_3<Kernel> 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<bool,Constrains_map>
{
public:
typedef boost::readable_property_map_tag category;
typedef bool value_type;
typedef bool reference;
typedef typename boost::graph_traits<Surface const>::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<key_type,bool> 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<Surface> 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 //