diff --git a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Count_ratio_stop_predicate.tex b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Count_ratio_stop_predicate.tex index be688d53008..f010a2061e5 100644 --- a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Count_ratio_stop_predicate.tex +++ b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Count_ratio_stop_predicate.tex @@ -43,10 +43,10 @@ of edges drops below a certain ratio. \ccOperations \ccMethod - {bool operator()( FT const& current_cost - , edge_descriptor const& edge - , size_type initial_count - , size_type current_count + {bool operator()( FT const& current_cost + , Profile const& edge_profile + , size_type initial_count + , size_type current_count ) const ; } {Returns ( \ccc{((double)current_count/ (double)initial_count) < ratio}. All other parameters are ignored.} diff --git a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Count_stop_predicate.tex b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Count_stop_predicate.tex index 1553ca4296b..b636e0b1cf7 100644 --- a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Count_stop_predicate.tex +++ b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Count_stop_predicate.tex @@ -42,10 +42,10 @@ It returns \ccc{true} when the number of current edges drops below a certain thr \ccOperations \ccMethod - {bool operator()( FT const& current_cost - , edge_descriptor const& edge - , size_type initial_count - , size_type current_count + {bool operator()( FT const& current_cost + , Profile const& edge_profile + , size_type initial_count + , size_type current_count ) const ; } {Returns \ccc{current_count < threshold}. All other parameters are ignored.} 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 5213c2b8a5d..dd2447ed248 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 @@ -60,14 +60,11 @@ The several callbacks given as member functions in the visitor are called from c \ccMethod {void OnCollected( edge_descriptor const& edge - , bool is_fixed , ECM& surface ); } {Called during the {\em collecting phase} (when a cost is assigned to the edges), - for each \ccc{edge} collected.\\ - \ccc{is_fixed} indicates whether \ccc{edge} is fixed or not. - If it is fixed it will not be collapsed. + for each \ccc{edge} collected. } \ccMethod diff --git a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Edge_length_cost.tex b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Edge_length_cost.tex index a600ce9e45b..bdb6a54354a 100644 --- a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Edge_length_cost.tex +++ b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Edge_length_cost.tex @@ -39,16 +39,10 @@ It computes the collapse cost as the squared length of the edge. \ccConstructor{Edge_length_cost();}{Default constructor} \ccHeading{Methods} - \ccMethod{template - result_type operator()( edge_descriptor const& edge - , ECM& surface - , Cache const& cache - , Params const* params - ) const; - } + \ccMethod{result_type operator()( Profile const& profile, optional const& placement ) const; } {Returns the {\em collapse cost} as the squared distance between the points - of the source and target vertices of \ccc{edge}. All arguments - except \ccc{edge} and \ccc{surface} are ignored. + of the source and target vertices (that is, \ccc{profile.p0()} and \ccc{profile.p1()}.\ + The \ccc{placement} argument is ignored. } \end{ccRefClass} diff --git a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/GetCost.tex b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/GetCost.tex index 35c0a6601b9..e7fdf62c0e0 100644 --- a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/GetCost.tex +++ b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/GetCost.tex @@ -22,27 +22,25 @@ \ccCreationVariable{gc} %% choose variable name \ccDefinition -The concept \ccRefName\ describes the requirements for the {\em policy function object} which gets the {\em collapse cost} of an edge. +The concept \ccRefName\ describes the requirements for the {\em policy function object} +which gets the {\em collapse cost} of an edge. -The cost returned is a \ccc{boost::optional} value (i.e. it can be absent). An {\em absent} cost could be the result of a computational limitation (such as overflow), or can be intentionally returned to prevent the edge from being collapsed. - -A model of this concept can simply return the cost stored in the -passed cache object, if any, or perform the actual computation. +The cost returned is a \ccc{boost::optional} value (i.e. it can be absent). +An {\em absent} cost indicates that the edge should not be collapsed. +This could be the result of a computational limitation (such as overflow), +or can be intentionally returned to prevent the edge from being collapsed. \ccRefines \ccc{DefaultConstructible}\\ \ccc{CopyConstructible} \ccTypes - \ccNestedType{ECM}{The type of the surface to simplify. - Must be a model of the \ccc{EdgeCollapsableMesh} concept.}{} -\ccGlue - \ccNestedType{Params}{The type of the model-specific parameters needed. Can be \ccc{void}.}{} + \ccNestedType{Profile} + {The type of the edge profile cache. Must be a model of the \ccc{EdgeProfile} concept.}{} \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 edge of the surface.} + \ccTypedef{typename CGAL::halfedge_graph_traits::Point Point;}{The point type for the surface vertex.} \ccGlue \ccTypedef{boost::optional result_type;}{The type of the result (an optional cost value).} @@ -53,23 +51,12 @@ passed cache object, if any, or perform the actual computation. \ccOperations - \ccMethod{template - result_type operator()( edge_descriptor const& edge - , ECM& surface - , Cache const& cache - , Params const* params - ) const; - } - {Computes and returns the cost of collapsing \ccc{edge} using the model-specific \ccc{params}.\\ - \ccc{edge} is required to be in the \ccc{surface}.\\ - If \ccc{Cache} is a model of \ccc{CostCache} or \ccc{CostAndPlacementCache}, - which means that \ccc{cache} stores the cost, a model of this \ccc{GetCost} concept - can simply return the cached cost (but is not required to do so).\\ - \ccc{params} can be a \ccStyle{NULL} pointer. + \ccMethod{result_type operator()( Profile const& edge_profile, optional const& placement ) const;} + {Computes and returns the cost of collapsing the edge (represented by its profile), + using the calculated placement.\\ } \ccHasModels -\ccRefIdfierPage{CGAL::Surface_mesh_simplification::Cached_cost}. \ccRefIdfierPage{CGAL::Surface_mesh_simplification::Edge_length_cost}. \ccRefIdfierPage{CGAL::Surface_mesh_simplification::LindstromTurk_cost}. diff --git a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/GetPlacement.tex b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/GetPlacement.tex index cfc10f473bd..44ef70a20bc 100644 --- a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/GetPlacement.tex +++ b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/GetPlacement.tex @@ -24,31 +24,22 @@ The concept \ccRefName\ describes the requirements for the {\em policy function object} which gets the {\em collapse placement} of an edge, -that is, the position of the vertex that replaces the edge after the -collapse. +that is, the new position of the vertex that remains after a +halfedge-collapse. The placement returned is a \ccc{boost::optional} value (i.e., it can -be absent). An absent placement could be the result of a -computational limitation (such as overflow), or can be intentionally -returned to prevent the edge from being collapsed. - -A model of this concept can simply return the placement stored in the -passed cache object, if any, or perform the actual computation. +be absent). An absent result indicates that the remainin vertex +must be kept in place, not moved to a new position. \ccRefines \ccc{DefaultConstructible}\\ \ccc{CopyConstructible} \ccTypes - \ccNestedType{ECM}{The type of the surface to simplify. - Must be a model of the \ccc{EdgeCollapsableMesh} concept.}{} -\ccGlue - \ccNestedType{Params}{The type of the model-specific parameters needed. Can be \ccc{void}.}{} + \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 for the surface vertex.} -\ccGlue - \ccTypedef{typename boost::graph_traits::edge_descriptor edge_descriptor;} - {A {\sc Bgl} edge descriptor representing an edge of the surface.} \ccGlue \ccTypedef{boost::optional result_type;}{The type of the result (an optional point).} @@ -59,26 +50,13 @@ passed cache object, if any, or perform the actual computation. \ccOperations - \ccMethod{template - result_type operator()( edge_descriptor const& edge - , ECM& surface - , Cache const& cache - , Params const* params - ) const; - } + \ccMethod{ result_type operator()( Profile const& edge_profile ) const; } {Computes and returns the placement, that is, the position of the vertex - which replaces the collapsing \ccc{edge}, using the model-specific \ccc{params}.\\ - \ccc{edge} is required to be in the \ccc{surface}.\\ - If \ccc{Cache} is a model of \ccc{CostAndPlacementCache}, which means that - \ccc{cache} stores the placement, a model can simply return that - (but is not required to do so).\\ - \ccc{params} can be a \ccc{NULL} pointer. - } + which replaces the collapsing edge (represented by its profile). } \ccHasModels -\ccRefIdfierPage{CGAL::Surface_mesh_simplification::Cached_cost}. -\ccRefIdfierPage{CGAL::Surface_mesh_simplification::Edge_length_cost}. -\ccRefIdfierPage{CGAL::Surface_mesh_simplification::LindstromTurk_cost}. +\ccRefIdfierPage{CGAL::Surface_mesh_simplification::Edge_length_placement}. +\ccRefIdfierPage{CGAL::Surface_mesh_simplification::LindstromTurk_placement}. \end{ccRefConcept} diff --git a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/LindstromTurk_cost.tex b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/LindstromTurk_cost.tex index 79e14afb303..b0e45263025 100644 --- a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/LindstromTurk_cost.tex +++ b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/LindstromTurk_cost.tex @@ -37,21 +37,15 @@ It must be a model of the \ccc{EdgeCollapsableMesh} concept. \ccCreation \ccCreationVariable{gc} %% choose variable name -\ccConstructor{LindstromTurk_cost();}{Default constructor} +\ccConstructor{LindstromTurk_cost( LindstromTurk_params const& aParams );} +{Initializes the policy with the given parameters} \ccHeading{Methods} - \ccMethod{template - result_type operator()( edge_descriptor const& edge - , ECM& surface - , Cache const& cache - , LindstromTurk_Params const* params - ) const; - } - {Returns the cost of collapsing \ccc{edge}.} + \ccMethod{result_type operator()( Profile const& profile, optional const& placement ) const;} + {Returns the cost of collapsing the edge (represented by its profile) considering + the new \ccc{placement} computed for it.} \ccSeeAlso -\ccc{CGAL::Surface_mesh_simplification::LindstromTurk_set_cost_cache}\\ -\ccc{CGAL::Surface_mesh_simplification::LindstromTurk_set_cost_and_placement_cache}\\ \ccc{CGAL::Surface_mesh_simplification::LindstromTurk_placement}\\ \ccc{CGAL::Surface_mesh_simplification::LindstromTurk_params} diff --git a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/LindstromTurk_params.tex b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/LindstromTurk_params.tex index 0408966fbd6..4efb3eb5927 100644 --- a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/LindstromTurk_params.tex +++ b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/LindstromTurk_params.tex @@ -36,8 +36,6 @@ cost strategy (Section~\ref{SurfaceMeshSimplification:LindstromTurkStrategy}) {Initializes an instance which stores the given weights.} \ccSeeAlso -\ccc{CGAL::Surface_mesh_simplification::LindstromTurk_set_cost_cache}\\ -\ccc{CGAL::Surface_mesh_simplification::LindstromTurk_set_cost_and_placement_cache}\\ \ccc{CGAL::Surface_mesh_simplification::LindstromTurk_cost}\\ \ccc{CGAL::Surface_mesh_simplification::LindstromTurk_placement} diff --git a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/LindstromTurk_placement.tex b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/LindstromTurk_placement.tex index 04700fb4c75..217cdc67eea 100644 --- a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/LindstromTurk_placement.tex +++ b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/LindstromTurk_placement.tex @@ -24,7 +24,8 @@ \ccDefinition The class \ccRefName\ provides a model for the \ccc{GetPlacement} concept. -It computes the collapse cost following the Lindstrom-Turk strategy +It computes the placement, that is, the new position for the remaining vertex after +a halfedge-collapse, following the Lindstrom-Turk strategy (Section~\ref{SurfaceMeshSimplification:LindstromTurkStrategy}). The class \ccRefName\ has one template argument: the type of surface being simplified. @@ -37,20 +38,15 @@ It must be a model of the \ccc{EdgeCollapsableMesh} concept. \ccCreation \ccCreationVariable{gp} %% choose variable name -\ccConstructor{LindstromTurk_placement();}{Default constructor} +\ccConstructor{LindstromTurk_placement( LindstromTurk_params const& aParams );} +{Initializes the policy with the given parameters} \ccHeading{Methods} - \ccMethod{template - result_type operator()( edge_descriptor const& edge - , ECM& surface - , Cache const& cache - , LindstromTurk_params const* params - ) const; - } - {Returns the position of the vertex that replaces the collapsed \ccc{edge}.} + \ccMethod{result_type operator()( Profile const& edge_profile ) const;} + {Returns the new position for the remaining vertex after collapsing the edge + (represented by its profile).} -\ccc{CGAL::Surface_mesh_simplification::LindstromTurk_set_cost_cache}\\ -\ccc{CGAL::Surface_mesh_simplification::LindstromTurk_set_cost_and_placement_cache}\\ +\ccSeeAlso \ccc{CGAL::Surface_mesh_simplification::LindstromTurk_cost}\\ \ccc{CGAL::Surface_mesh_simplification::LindstromTurk_params}\\ \end{ccRefClass} diff --git a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Midpoint_placement.tex b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Midpoint_placement.tex index 9c55e0d3855..a1e8f171f4f 100644 --- a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Midpoint_placement.tex +++ b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/Midpoint_placement.tex @@ -40,17 +40,11 @@ It be a model of the \ccc{EdgeCollapsableMesh} concept. \ccConstructor{Midpoint_placement();}{Default constructor} \ccHeading{Methods} - \ccMethod{template - result_type operator()( edge_descriptor const& edge - , ECM& surface - , Cache const& cache - , Params const* params - ) const; + \ccMethod{result_type operator()( Profile const& edge_profile ) const; } {Returns the {\em placement} (vertex position) as the midpoint between - the points of the source and target vertices of \ccc{edge}. All arguments - except \ccc{edge} and \ccc{surface} are ignored. - } + the points of the source and target vertices + (that is, \ccc{profile.p0()} and \ccc{profile.p1()})} \end{ccRefClass} diff --git a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/StopPredicate.tex b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/StopPredicate.tex index e4c93139f06..b1f05d10f0d 100644 --- a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/StopPredicate.tex +++ b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/StopPredicate.tex @@ -31,8 +31,8 @@ The concept \ccRefName\ describes the requirements for the predicate which indic \ccGlue \ccNestedType{size_type}{An integer type representing the number of edges}{} \ccGlue - \ccTypedef{typename boost::graph_traits::edge_descriptor edge_descriptor;} - {A {\sc Bgl} edge descriptor representing an edge of the surface.} + \ccNestedType{Profile} + {The type of the edge profile cache. Must be a model of the \ccc{EdgeProfile} concept.}{} \ccCreation \ccCreationVariable{should_stop} %% choose variable name @@ -40,19 +40,19 @@ The concept \ccRefName\ describes the requirements for the predicate which indic \ccOperations \ccMethod - {bool operator()( FT current_cost - , edge_descriptor edge - , size_type initial_count - , size_type current_count - ) const ; + {bool operator()( FT const& current_cost + , Profile const& profile + , size_type initial_count + , size_type current_count + ) const ; } { - This predicate is called each time an \ccc{edge} is selected for processing, - before it is collapsed.\\ + This predicate is called each time an edge is selected for processing, + before it is collapsed.\\ \ccc{current_cost} is the cost of the selected edge.\\ \ccc{initial_count} and \ccc{current_count} is the number of initial and current edges.\\ \\ - If the return value is \ccc{true} the simplification terminates before processing \ccc{edge}, + If the return value is \ccc{true} the simplification terminates before processing the edge, otherwise it continues normally. } diff --git a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/edge_collapse.tex b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/edge_collapse.tex index be4b93dc527..e3ae9cfddcd 100644 --- a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/edge_collapse.tex +++ b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/edge_collapse.tex @@ -64,43 +64,43 @@ All named parameters have default values and the order of the named parameters is irrelevant so you only need to compose those for which the default is inappropriate. -\subsubsection*{vertex\_point\_map(VertexPointMap vpm)} +\subsubsection*{vertex\_index\_map(VertexIndexMap vpm)} -Provides lvalue access to the point of a vertex of the surface. -\ccc{VertexPointMap} must be an -\ccAnchor{http://www.boost.org/libs/property_map/LvaluePropertyMap.html}{LValuePropertyMap} +Maps each vertex in the surface into an unsigned integer number +in the range \ccc{[0,num_vertices(surface))}. + +\ccc{VertexIndexMap} must be a +\ccAnchor{http://www.boost.org/libs/property_map/ReadablePropertyMap.html}{ReadablePropertyMap} whose \ccc{key_type} is -\ccc{boost::graph_traits::vertex_descriptor} +\ccc{boost::graph_traits::vertex_descriptor} and whose \ccc{value_type} is -\ccc{boost::halfedge_graph_traits::Point} - -\textbf{Default}: the property map obtained by calling \ccc{get(vertex_point,surface)}. - +\ccc{boost::graph_traits::size_type}, +\textbf{Default}: the property map obtained by calling \ccc{get(vertex_index,surface)}, +which requires the surface vertices to have an \ccc{id()} member properly initialized to the +required value.\\ +If the verices don't have such id(), you must pass a map explicitely, such as +the property map obtained by calling \ccc{get(vertex_external_index,surface)}, +which constructs an internal map which non-intrusively associates a proper id with each vertex. \subsubsection*{edge\_index\_map(EdgeIndexMap eim)} -Maps each {\em directed} edge in the surface into an integer number +Maps each {\em directed} edge in the surface into an unsigned integer number in the range \ccc{[0,num_edges(surface))}. -\ccc{EdgeIndexMap} must be a either a +\ccc{EdgeIndexMap} must be a \ccAnchor{http://www.boost.org/libs/property_map/ReadablePropertyMap.html}{ReadablePropertyMap} whose \ccc{key_type} is \ccc{boost::graph_traits::edge_descriptor} and whose \ccc{value_type} is -\ccc{boost::graph_traits::size_type}, -or the same as \ccc{EdgeCollapsableMesh}, in which case -\ccc{eim} is in fact the surface to be simplified. +\ccc{boost::graph_traits::size_type} -If \ccc{eim} is a valid property map, it is -passed as the argument, but if it is the surface, a -temporary property map is passed instead. -Such temporary map externally relates each edge -in the surface (\ccc{eim}) to its index, -without requiring any user intervention or any special -provision in the surface edge. - -\textbf{Default}: the property map obtained by calling \ccc{get(edge_index,surface)}. +\textbf{Default}: the property map obtained by calling \ccc{get(edge_index,surface)}, +which requires the surface edges to have an \ccc{id()} member properly initialized to the +require value.\\ +If the edges don't have such id(), you must pass a map explicitely, such as +the property map obtained by calling \ccc{get(edge_external_index,surface)}, +which constructs an internal map which non-intrusively associates a proper id with each edge. \subsubsection*{edge\_is\_border\_map(EdgeIsBorderMap ebm)} @@ -115,49 +115,13 @@ and whose \ccc{value_type} is \ccc{bool}. \textbf{Default}: the property map obtained by calling \ccc{get(edge_is_border,surface)}. - -\subsubsection*{vertex\_is\_fixed\_map(VertexIsFixedMap vfm)} - - -Maps each vertex in the surface into a boolean value -which indicates if the vertex is fixed and cannot be modified -by the \ccc{edge_collapse} function.\\ -\ccc{VertexIsFixedMap} must be a -\ccAnchor{http://www.boost.org/libs/property_map/ReadablePropertyMap.html}{ReadablePropertyMap} -whose \ccc{key_type} is -\ccc{boost::graph_traits::vertex_descriptor} -and whose \ccc{value_type} is \ccc{bool}. - -\textbf{Default}: -\ccc{Vertex_is_fixed_property_map_always_false()}. - - -\subsubsection*{set\_cache(SetCache sc)} - -The policy which indicates the caching level used -by the \ccc{edge_collapse} function.\\ -The type of \ccc{sc} must be a model of the \ccc{SetCache} concept. - -\textbf{Default}: -\ccc{CGAL::Surface_mesh_simplification::LindstromTurk_set_cost_cache()} - - \subsubsection*{get\_cost(GetCost gc)} - The policy which returns the collapse cost for an edge.\\ The type of \ccc{gc} must be a model of the \ccc{GetCost} concept. \textbf{Default}: -\ccc{CGAL::Surface_mesh_simplification::Cached_cost}. - - -\subsubsection*{get\_cost\_params(GetCost::Params const* gp)} - -The model-specific parameters to \ccc{get_cost}. - -\textbf{Default}: \ccc{NULL}. - +\ccc{CGAL::Surface_mesh_simplification::LindstromTurk_cost}. \subsubsection*{get\_placement(GetPlacement gp)} @@ -168,16 +132,6 @@ The type of \ccc{gp} must be a model of the \ccc{GetPlacement} concept. \textbf{Default}: \ccc{CGAL::Surface_mesh_simplification::LindstromTurk_placement} - - -\subsubsection*{get\_placement\_params(GetPlacement::Params const* gpp)} - -The model-specific parameters to \ccc{get_placement}. - -\textbf{Default}: A pointer to a local default constructed instance of \ccc{CGAL::LindstromTurk_params}. - - - \subsubsection*{visitor(EdgeCollapseSimplificationVisitor const* v)} The visitor that is called by the \ccc{edge_collapse} function @@ -197,16 +151,9 @@ examples in the user manual. The simplification process continues until the \ccc{should_stop} policy returns \ccc{true} or the surface cannot be simplified any further due to topological constraints. -\ccc{vertex_is_fixed_map} is used to indicate that some edges should not be -collapsed: edges incident upon fixed vertices are not collapsed. - -\ccc{set_cache}, along with \ccc{get_cost} and \ccc{get_placement}, -are the policies which control the {\em cost-strategy}, that is, -the order in which edges are collapsed and the replacement vertex is positioned.\\ -\ccc{get_cost_params} and \ccc{get_placement_params} are the runtime -parameters used by the these policies. They can be null pointers -if the policies do not need them. This strategy is the driving factor that determines the accuracy of the -simplified surface with respect to the original. +\ccc{get_cost} and \ccc{get_placement} are the policies which control +the {\em cost-strategy}, that is, the order in which edges are collapsed +and the remaining vertex is re-positioned. \ccc{visitor} is an optional object (can be null) which can be used to keep track of the simplification process. diff --git a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/intro.tex b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/intro.tex index 621d6bebe35..ed1e87acb97 100644 --- a/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/intro.tex +++ b/Surface_mesh_simplification/doc_tex/Surface_mesh_simplification_ref/intro.tex @@ -26,42 +26,26 @@ by iterative edge-collapsing. \ccHeading{Concepts} \ccRefConceptPage{EdgeCollapsableMesh} \\ +\ccRefConceptPage{EdgeProfile} \\ \ccRefConceptPage{StopPredicate} \\ -\ccRefConceptPage{NoCache} \\ -\ccRefConceptPage{CostCache} \\ -\ccRefConceptPage{CostAndPlacementCache} \\ -\ccRefConceptPage{SetCache} \\ \ccRefConceptPage{GetCost} \\ \ccRefConceptPage{GetPlacement} \\ \ccRefConceptPage{EdgeCollapseSimplificationVisitor} - \ccHeading{Functions} \ccRefIdfierPage{CGAL::Surface_mesh_simplification::edge_collapse}\\ - \ccHeading{Classes} +\ccRefIdfierPage{CGAL::Surface_mesh_simplification::Edge_profile}\\ \ccRefIdfierPage{CGAL::Surface_mesh_simplification::Count_stop_predicate}\\ \ccRefIdfierPage{CGAL::Surface_mesh_simplification::Count_ratio_stop_predicate}\\ -\ccRefIdfierPage{CGAL::Surface_mesh_simplification::No_cache}\\ -\ccRefIdfierPage{CGAL::Surface_mesh_simplification::Cost_cache}\\ -\ccRefIdfierPage{CGAL::Surface_mesh_simplification::Cost_and_placement_cache}\\ -\ccRefIdfierPage{CGAL::Surface_mesh_simplification::Set_no_cache}\\ -\ccRefIdfierPage{CGAL::Surface_mesh_simplification::Set_cost_cache}\\ -\ccRefIdfierPage{CGAL::Surface_mesh_simplification::Set_cost_and_placement_cache}\\ -\ccRefIdfierPage{CGAL::Surface_mesh_simplification::Cached_cost}\\ -\ccRefIdfierPage{CGAL::Surface_mesh_simplification::Cached_placement}\\ \ccRefIdfierPage{CGAL::Surface_mesh_simplification::Edge_length_cost}\\ \ccRefIdfierPage{CGAL::Surface_mesh_simplification::Midpoint_placement}\\ -\ccRefIdfierPage{CGAL::Surface_mesh_simplification::LindstromTurk_set_cost_cache}\\ -\ccRefIdfierPage{CGAL::Surface_mesh_simplification::LindstromTurk_set_cost_and_placement_cache}\\ \ccRefIdfierPage{CGAL::Surface_mesh_simplification::LindstromTurk_cost}\\ \ccRefIdfierPage{CGAL::Surface_mesh_simplification::LindstromTurk_placement}\\ \ccRefIdfierPage{CGAL::Surface_mesh_simplification::LindstromTurk_params}\\ -\ccRefIdfierPage{CGAL::Vertex_is_fixed_property_map_always_false}\\ -\ccRefIdfierPage{CGAL::Vertex_is_fixed_property_map_stored}\\ % +------------------------------------------------------------------------+ %%RefPage: end of main body, begin of footer diff --git a/Surface_mesh_simplification/examples/Surface_mesh_simplification/LT_edge_collapse_polyhedron.cpp b/Surface_mesh_simplification/examples/Surface_mesh_simplification/LT_edge_collapse_polyhedron.cpp index f357e3f57e0..a1cfb6fc212 100644 --- a/Surface_mesh_simplification/examples/Surface_mesh_simplification/LT_edge_collapse_polyhedron.cpp +++ b/Surface_mesh_simplification/examples/Surface_mesh_simplification/LT_edge_collapse_polyhedron.cpp @@ -35,9 +35,13 @@ int main( int argc, char** argv ) // This the actual call to the simplification algorithm. // The surface and stop conditions are mandatory arguments. - // The third argument is needed because the edges on this - // surface lack an "id()" field. - int r = SMS::edge_collapse(surface, stop, CGAL::edge_index_map(boost::get(CGAL::edge_external_index,surface)) ); + // 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)) + ,CGAL::edge_index_map (boost::get(CGAL::edge_external_index ,surface)) + ); // === CONCRETE USAGE EXAMPLE ENDS HERE === diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Detail/Common.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Detail/Common.h index 330c82178c1..1b7e6e8be41 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Detail/Common.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Detail/Common.h @@ -58,7 +58,6 @@ using boost::addressof ; using namespace boost::tuples ; - template inline bool handle_assigned( Handle h ) { Handle null ; return h != null ; } @@ -74,31 +73,6 @@ bool handle_exists ( Iterator begin, Iterator end, Handle h ) return false ; } - -template struct ChooseNotVoidType ; -template struct ChooseNotVoidType { typedef T type ; } ; -template struct ChooseNotVoidType { typedef U type ; } ; -template<> struct ChooseNotVoidType { typedef void type ; } ; - -template -struct ExtractCostParamsType -{ - typedef typename ChooseNotVoidType< typename GetCost ::Params - , typename SetCache::CostParams - > - ::type type ; -} ; - -template -struct ExtractPlacementParamsType -{ - typedef typename ChooseNotVoidType< typename GetPlacement::Params - , typename SetCache ::PlacementParams - > - ::type type ; -} ; - - } // namespace Surface_mesh_simplification template diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Detail/Edge_collapse.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Detail/Edge_collapse.h index 9bc04d594dd..575cf847fb8 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Detail/Edge_collapse.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Detail/Edge_collapse.h @@ -28,6 +28,7 @@ #include #include +#include CGAL_BEGIN_NAMESPACE @@ -39,13 +40,11 @@ namespace Surface_mesh_simplification // template class EdgeCollapse @@ -54,17 +53,17 @@ public: typedef ECM_ ECM ; typedef ShouldStop_ ShouldStop ; - typedef VertexPointMap_ VertexPointMap ; + typedef VertexIndexMap_ VertexIndexMap ; typedef EdgeIndexMap_ EdgeIndexMap ; typedef EdgeIsBorderMap_ EdgeIsBorderMap ; typedef GetCost_ GetCost ; typedef GetPlacement_ GetPlacement ; - typedef CostParams_ CostParams ; - typedef PlacementParams_ PlacementParams ; typedef VisitorT_ VisitorT ; typedef EdgeCollapse Self ; + typedef Edge_profile Profile ; + typedef boost::graph_traits GraphTraits ; typedef boost::graph_traits ConstGraphTraits ; typedef halfedge_graph_traits HalfedgeGraphTraits ; @@ -117,7 +116,7 @@ public: // NOTE: A cost is an optional<> value. // Absent optionals are ordered first; that is, "none < T" and "T > none" for any defined T != none. // In consequence, edges with undefined costs will be promoted to the top of the priority queue and poped out first. - return mAlgorithm->get_cost(a) < mAlgorithm->get_cost(b); + return mAlgorithm->get_data(a).cost() < mAlgorithm->get_data(b).cost(); } Self const* mAlgorithm ; @@ -176,13 +175,11 @@ public: EdgeCollapse( ECM& aSurface , ShouldStop const& aShouldStop - , VertexPointMap const& aVertex_point_map + , VertexIndexMap const& aVertex_index_map , EdgeIndexMap const& aEdge_index_map , EdgeIsBorderMap const& aEdge_is_border_map , GetCost const& aGetCost , GetPlacement const& aGetPlacement - , CostParams const* aCostParams // Can be NULL - , PlacementParams const* aPlacementParams // Can be NULL , VisitorT* aVisitor // Can be NULL ) ; @@ -192,12 +189,17 @@ private: void Collect(); void Loop(); - bool Is_collapsable( edge_descriptor const& aEdge ) ; + bool Is_collapsable( Profile const& aProfile ) ; bool Is_tetrahedron( edge_descriptor const& h1 ) ; bool Is_open_triangle( edge_descriptor const& h1 ) ; - void Collapse( edge_descriptor const& aEdge ) ; + void Collapse( Profile const& aProfile ) ; void Update_neighbors( vertex_descriptor const& aKeptV ) ; + Profile create_profile ( edge_descriptor const& aEdge ) + { + return Profile(aEdge,mSurface,Vertex_index_map,Edge_index_map,Edge_is_border_map); + } + size_type get_directed_edge_id ( const_edge_descriptor const& aEdge ) const { return Edge_index_map[aEdge]; } size_type get_undirected_edge_id ( const_edge_descriptor const& aEdge ) const { return get_directed_edge_id(aEdge) / 2 ; } @@ -223,7 +225,10 @@ private: return mEdgeDataArray[get_undirected_edge_id(aEdge)]; } - Point get_point ( const_vertex_descriptor const aV ) const { return get(Vertex_point_map,aV); } + Point const& get_point ( const_vertex_descriptor const& aV ) const + { + return get(vertex_point,mSurface,aV); + } tuple get_vertices( const_edge_descriptor const& aEdge ) const { @@ -253,14 +258,14 @@ private: return boost::str( boost::format("{E%1% %2%->%3%}") % aEdge->ID % vertex_to_string(p) % vertex_to_string(q) ) ; } - Cost_type get_cost ( edge_descriptor const& aEdge ) const + Cost_type get_cost ( Profile const& aProfile ) const { - return Get_cost(aEdge,mSurface,mCostParams, get_placement(aEdge) ); + return Get_cost(aProfile, get_placement(aProfile) ); } - Placement_type get_placement( edge_descriptor const& aEdge ) const + Placement_type get_placement( Profile const& aProfile ) const { - return Get_placement(aEdge,mSurface,mPlacementParams); + return Get_placement(aProfile); } void insert_in_PQ( edge_descriptor const& aEdge, Edge_data& aData ) @@ -299,13 +304,11 @@ private: ECM& mSurface ; ShouldStop const& Should_stop ; - VertexPointMap const& Vertex_point_map ; + VertexIndexMap const& Vertex_index_map ; EdgeIndexMap const& Edge_index_map ; EdgeIsBorderMap const& Edge_is_border_map ; GetCost const& Get_cost ; GetPlacement const& Get_placement ; - CostParams const* mCostParams ; // Can be NULL - PlacementParams const* mPlacementParams ; // Can be NULL VisitorT* Visitor ; // Can be NULL private: diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Detail/Edge_collapse_impl.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Detail/Edge_collapse_impl.h index 9ea80cb3c19..62875465f5f 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Detail/Edge_collapse_impl.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Detail/Edge_collapse_impl.h @@ -23,28 +23,24 @@ CGAL_BEGIN_NAMESPACE namespace Surface_mesh_simplification { -template -EdgeCollapse::EdgeCollapse( ECM& aSurface - , ShouldStop const& aShould_stop - , VertexPointMap const& aVertex_point_map - , EdgeIndexMap const& aEdge_index_map - , EdgeIsBorderMap const& aEdge_is_border_map - , GetCost const& aGet_cost - , GetPlacement const& aGet_placement - , CostParams const* aCostParams - , PlacementParams const* aPlacementParams - , VisitorT* aVisitor - ) +template +EdgeCollapse::EdgeCollapse( ECM& aSurface + , ShouldStop const& aShould_stop + , VertexIndexMap const& aVertex_index_map + , EdgeIndexMap const& aEdge_index_map + , EdgeIsBorderMap const& aEdge_is_border_map + , GetCost const& aGet_cost + , GetPlacement const& aGet_placement + , VisitorT* aVisitor + ) : mSurface (aSurface) ,Should_stop (aShould_stop) - ,Vertex_point_map (aVertex_point_map) + ,Vertex_index_map (aVertex_index_map) ,Edge_index_map (aEdge_index_map) ,Edge_is_border_map (aEdge_is_border_map) ,Get_cost (aGet_cost) ,Get_placement (aGet_placement) - ,mCostParams (aCostParams) - ,mPlacementParams (aPlacementParams) ,Visitor (aVisitor) { @@ -63,8 +59,8 @@ EdgeCollapse::EdgeCollapse( ECM& #endif } -template -int EdgeCollapse::run() +template +int EdgeCollapse::run() { if ( Visitor ) Visitor->OnStarted(mSurface); @@ -85,8 +81,8 @@ int EdgeCollapse::run() return r ; } -template -void EdgeCollapse::Collect() +template +void EdgeCollapse::Collect() { CGAL_ECMS_TRACE(0,"Collecting edges..."); @@ -113,16 +109,13 @@ void EdgeCollapse::Collect() CGAL_assertion( get_directed_edge_id(lEdge) == id ) ; CGAL_assertion( get_directed_edge_id(opposite_edge(lEdge,mSurface)) == id+1 ) ; - - vertex_descriptor p,q ; - tie(p,q) = get_vertices(lEdge); - - CGAL_assertion(p!=q); - - if ( !equal_points( get_point(p), get_point(q) ) ) + + Profile const& lProfile = create_profile(lEdge); + + if ( !equal_points(lProfile.p0(),lProfile.p1()) ) { Edge_data& lData = get_data(lEdge); - lData.cost() = get_cost(lEdge) ; + lData.cost() = get_cost(lProfile) ; insert_in_PQ(lEdge,lData); } @@ -137,8 +130,8 @@ void EdgeCollapse::Collect() CGAL_ECMS_TRACE(0,"Initial edge count: " << mInitialEdgeCount ) ; } -template -void EdgeCollapse::Loop() +template +void EdgeCollapse::Loop() { CGAL_ECMS_TRACE(0,"Collapsing edges...") ; @@ -157,7 +150,9 @@ void EdgeCollapse::Loop() if ( lCost ) { - if ( Should_stop(*lCost,*lEdge,mInitialEdgeCount,mCurrentEdgeCount) ) + Profile const& lProfile = create_profile(*lEdge); + + if ( Should_stop(*lCost,lProfile,mInitialEdgeCount,mCurrentEdgeCount) ) { if ( Visitor ) Visitor->OnStopConditionReached(mSurface); @@ -169,9 +164,9 @@ void EdgeCollapse::Loop() break ; } - if ( Is_collapsable(*lEdge) ) + if ( Is_collapsable(lProfile) ) { - Collapse(*lEdge); + Collapse(lProfile); } else { @@ -189,8 +184,8 @@ void EdgeCollapse::Loop() } } -template -bool EdgeCollapse::is_border( const_vertex_descriptor const& aV ) const +template +bool EdgeCollapse::is_border( const_vertex_descriptor const& aV ) const { bool rR = false ; @@ -216,41 +211,34 @@ bool EdgeCollapse::is_border( const_vertex_descr // // The link conidition is as follows: for every vertex 'k' adjacent to both 'p and 'q', "p,k,q" is a facet of the mesh. // -template -bool EdgeCollapse::Is_collapsable( edge_descriptor const& aEdgePQ ) +template +bool EdgeCollapse::Is_collapsable( Profile const& aProfile ) { bool rR = true ; - vertex_descriptor p,q ; tie(p,q) = get_vertices(aEdgePQ); - - CGAL_ECMS_TRACE(3,"Testing collapsabilty of p_q=V" << p->ID << "(%" << p->vertex_degree() << ")" - << "->V" << q->ID << "(%" << q->vertex_degree() << ")" + CGAL_ECMS_TRACE(3,"Testing collapsabilty of p_q=V" << aProfile.v0()->id() << "(%" << aProfile.v0()->vertex_degree() << ")" + << "->V" << aProfile.v1()->id() << "(%" << aProfile.v1()->vertex_degree() << ")" ); - CGAL_ECMS_TRACE(4, "is p_q border:" << is_border(aEdgePQ) ); - CGAL_ECMS_TRACE(4, "is q_q border:" << is_border(opposite_edge(aEdgePQ,mSurface)) ) ; + CGAL_ECMS_TRACE(4, "is p_q border:" << aProfile.is_v0v1_a_border() ); + CGAL_ECMS_TRACE(4, "is q_q border:" << aProfile.is_v1v0_a_border() ); - bool lIsBoundary = is_undirected_edge_a_border(aEdgePQ) ; + bool lIsBoundary = aProfile.is_v0v1_a_border() || aProfile.is_v1v0_a_border() ; out_edge_iterator eb1, ee1 ; out_edge_iterator eb2, ee2 ; - edge_descriptor lEdgeQP = opposite_edge(aEdgePQ,mSurface); - - vertex_descriptor t = target(next_edge(aEdgePQ,mSurface),mSurface); - vertex_descriptor b = target(next_edge(lEdgeQP,mSurface),mSurface); + CGAL_ECMS_TRACE(4," t=V" << aProfile.vt()->ID << "(%" << aProfile.vt()->vertex_degree() << ")" ); + CGAL_ECMS_TRACE(4," b=V" << aProfile.vb()->ID << "(%" << aProfile.vb()->vertex_degree() << ")" ); - CGAL_ECMS_TRACE(4," t=V" << t->ID << "(%" << t->vertex_degree() << ")" ); - CGAL_ECMS_TRACE(4," b=V" << b->ID << "(%" << b->vertex_degree() << ")" ); - - // The following loop checks the link condition for aEdgePQ. + // The following loop checks the link condition for aProfile.v0v1(). // Specifically, that every vertex 'k' adjacent to both 'p and 'q' is a face of the mesh. // - for ( tie(eb1,ee1) = out_edges(p,mSurface) ; rR && eb1 != ee1 ; ++ eb1 ) + for ( tie(eb1,ee1) = out_edges(aProfile.v0(),mSurface) ; rR && eb1 != ee1 ; ++ eb1 ) { edge_descriptor p_k = *eb1 ; - if ( p_k != aEdgePQ ) + if ( p_k != aProfile.v0v1() ) { vertex_descriptor k = target(p_k,mSurface); @@ -258,7 +246,7 @@ bool EdgeCollapse::Is_collapsable( edge_descript { edge_descriptor k_l = *eb2 ; - if ( target(k_l,mSurface) == q ) + if ( target(k_l,mSurface) == aProfile.v1() ) { // At this point we know p-q-k are connected and we need to determine if this triangle is a face of the mesh. // @@ -271,18 +259,18 @@ bool EdgeCollapse::Is_collapsable( edge_descript // or k==b but q->b is a border (because in that case even though there exists triangles p->q->t (or q->p->b) // they are holes, not faces) // - bool lIsFace = ( t == k && !is_border(aEdgePQ) ) - || ( b == k && !is_border(lEdgeQP) ) ; + bool lIsFace = ( aProfile.vl() == k && aProfile.left_face_exists () ) + || ( aProfile.vr() == k && aProfile.right_face_exists() ) ; if ( !lIsFace ) { - CGAL_ECMS_TRACE(3," k=V" << k->ID << " IS NOT in a face with p-q. NON-COLLAPSABLE edge." ) ; + CGAL_ECMS_TRACE(3," k=V" << k->id() << " IS NOT in a face with p-q. NON-COLLAPSABLE edge." ) ; rR = false ; break ; } else { - CGAL_ECMS_TRACE(4," k=V" << k->ID << " is in a face with p-q") ; + CGAL_ECMS_TRACE(4," k=V" << k->id() << " is in a face with p-q") ; } } } @@ -293,7 +281,7 @@ bool EdgeCollapse::Is_collapsable( edge_descript { if ( lIsBoundary ) { - if ( Is_open_triangle(aEdgePQ) ) + if ( Is_open_triangle(aProfile.v0v1()) ) { rR = false ; CGAL_ECMS_TRACE(3," p-q belongs to an open triangle. NON-COLLAPSABLE edge." ) ; @@ -301,12 +289,12 @@ bool EdgeCollapse::Is_collapsable( edge_descript } else { - if ( is_border(p) && is_border(q) ) + if ( is_border(aProfile.v0()) && is_border(aProfile.v1()) ) { rR = false ; CGAL_ECMS_TRACE(3," both p and q are boundary vertices but p-q is not. NON-COLLAPSABLE edge." ) ; } - else if ( Is_tetrahedron(aEdgePQ) ) + else if ( Is_tetrahedron(aProfile.v0v1()) ) { rR = false ; CGAL_ECMS_TRACE(3," p-q belongs to a tetrahedron. NON-COLLAPSABLE edge." ) ; @@ -317,8 +305,8 @@ bool EdgeCollapse::Is_collapsable( edge_descript return rR ; } -template -bool EdgeCollapse::Is_tetrahedron( edge_descriptor const& h1 ) +template +bool EdgeCollapse::Is_tetrahedron( edge_descriptor const& h1 ) { // // Code copied from Polyhedron_3::is_tetrahedron() @@ -369,8 +357,8 @@ bool EdgeCollapse::Is_tetrahedron( edge_descript return true; } -template -bool EdgeCollapse::Is_open_triangle( edge_descriptor const& h1 ) +template +bool EdgeCollapse::Is_open_triangle( edge_descriptor const& h1 ) { edge_descriptor h2 = next_edge(h1,mSurface); edge_descriptor h3 = next_edge(h2,mSurface); @@ -379,87 +367,60 @@ bool EdgeCollapse::Is_open_triangle( edge_descri } -template -void EdgeCollapse::Collapse( edge_descriptor const& aEdgePQ ) +template +void EdgeCollapse::Collapse( Profile const& aProfile ) { - CGAL_ECMS_TRACE(1,"S" << mStep << ". Collapsig " << edge_to_string(aEdgePQ) ) ; + CGAL_ECMS_TRACE(1,"S" << mStep << ". Collapsig " << edge_to_string(aProfile.v0v1()) ) ; - vertex_descriptor lP, lQ ; tie(lP,lQ) = get_vertices(aEdgePQ); - - CGAL_assertion( lP != lQ ); - vertex_descriptor rResult ; // The external function Get_new_vertex_point() is allowed to return an absent point if there is no way to place the vertex // satisfying its constrians. In that case the vertex-pair is simply not removed. - Placement_type lPlacement = get_placement(aEdgePQ); + Placement_type lPlacement = get_placement(aProfile); if ( Visitor ) - Visitor->OnCollapsing(aEdgePQ,mSurface,lPlacement); - - CGAL_ECMS_TRACE(2,"New vertex point: " << xyz_to_string(*lPlacement) ) ; + Visitor->OnCollapsing(aProfile.v0v1(),mSurface,lPlacement); -- mCurrentEdgeCount ; - edge_descriptor lEdgeQP = opposite_edge(aEdgePQ,mSurface); - - // The collapse of P-Q removes the top and bottom facets, if any. - // Edges P-T and P-Q, which are in the top and bottom facets (if they exist), are used by the collapse operator to remove them. - - // Edges P-T and P-Q are defined only if the top/bottom facets exists - - edge_descriptor lEdgePT, lEdgeQB ; - - if ( !is_border(aEdgePQ) ) // Exists top facet - lEdgePT = primary_edge(opposite_edge(prev_edge(aEdgePQ,mSurface),mSurface)); - - if ( !is_border(lEdgeQP) ) // Exists bottom facet - lEdgeQB = primary_edge(opposite_edge(prev_edge(lEdgeQP,mSurface),mSurface)); - - CGAL_ECMS_TRACE(3,"EdgePQ E" << aEdgePQ->ID - << "(V" << aEdgePQ->vertex()->ID << "->V" << aEdgePQ->opposite()->vertex()->ID - << ") EdgeQP E" << aEdgePQ->opposite()->ID - ) ; - - - // If the top/bottom facets exists, they are removed and the edges P-T and Q-B along with them. + // If the top/bottom facets exists, they are removed and the edges v0vt and Q-B along with them. // In that case their corresponding pairs must be pop off the queue - if ( handle_assigned(lEdgePT) ) + if ( aProfile.left_face_exists() ) { - CGAL_ECMS_TRACE(3,"EdgePT E" << lEdgePT->ID - << "(V" << lEdgePT->vertex()->ID << "->V" << lEdgePT->opposite()->vertex()->ID - << ") EdgeTP E" << lEdgePT->opposite()->ID + edge_descriptor lV0VL = primary_edge(aProfile.vlv0()); + + CGAL_ECMS_TRACE(3,"V0VL E" << lV0VL->id() + << "(V" << lV0VL->vertex()->id() << "->V" << lV0VL->opposite()->vertex()->id() << ") ) ; - Edge_data& lDataPT = get_data(lEdgePT) ; - if ( lDataPT.is_in_PQ() ) + Edge_data& lData = get_data(lV0VL) ; + if ( lData.is_in_PQ() ) { - CGAL_ECMS_TRACE(2,"Removing E" << lEdgePT->ID << " from PQ" ) ; - remove_from_PQ(lEdgePT,lDataPT) ; + CGAL_ECMS_TRACE(2,"Removing E" << lV0VL->id() << " from PQ" ) ; + remove_from_PQ(lV0VL,lData) ; -- mCurrentEdgeCount ; } } - if ( handle_assigned(lEdgeQB) ) + if ( aProfile.right_face_exists() ) { - CGAL_ECMS_TRACE(3,"EdgeQB E" << lEdgeQB->ID - << "(V" << lEdgeQB->vertex()->ID << "->V" << lEdgeQB->opposite()->vertex()->ID - << ") EdgeBQ E" << lEdgeQB->opposite()->ID + edge_descriptor lVRV1 = primary_edge(aProfile.vrv1()); + + CGAL_ECMS_TRACE(3,"V1VRE" << lVRV1->id() + << "(V" << lVRV1->vertex()->id() << "->V" << lVRV1->opposite()->vertex()->id() << ")" ) ; - Edge_data& lDataQB = get_data(lEdgeQB) ; - if ( lDataQB.is_in_PQ() ) + Edge_data& lData = get_data(lVRV1) ; + if ( lData.is_in_PQ() ) { - CGAL_ECMS_TRACE(2,"Removing E" << lEdgeQB->ID << " from PQ") ; - remove_from_PQ(lEdgeQB,lDataQB) ; + CGAL_ECMS_TRACE(2,"Removing E" << lVRV1->ID << " from PQ") ; + remove_from_PQ(lVRV1,lData) ; -- mCurrentEdgeCount ; } } - CGAL_ECMS_TRACE(1,"Removing:\n P-Q: E" << aEdgePQ->ID << "(V" << lP->ID << "->V" << lQ->ID << ")" ); - CGAL_ECMS_TRACE_IF(handle_assigned(lEdgePT),1," P-T: E" << lEdgePT->ID << "(V" << lP->ID << "->V" << target(lEdgePT,mSurface)->ID << ")" ) ; - CGAL_ECMS_TRACE_IF(handle_assigned(lEdgeQB),1," Q-B: E" << lEdgeQB->ID << "(V" << lQ->ID << "->V" << target(lEdgeQB,mSurface)->ID << ")" ) ; + CGAL_ECMS_TRACE(1,"Removing:\n v0v1: E" << aProfile.v0v1()->ID << "(V" << lP->ID << "->V" << lQ->ID << ")" ); // Perform the actuall collapse. @@ -467,7 +428,7 @@ void EdgeCollapse::Collapse( edge_descriptor con // It's REQUIRED to remove ONLY 1 vertex (P or Q) and edges PQ,PT and QB (PT and QB are removed if they are not null). // All other edges must be kept. // All directed edges incident to vertex removed are relink to the vertex kept. - rResult = collapse_triangulation_edge(aEdgePQ,mSurface); + rResult = collapse_triangulation_edge(aProfile.v0v1(),mSurface); CGAL_ECMS_TRACE(1,"V" << rResult->ID << " kept." ) ; @@ -478,15 +439,18 @@ void EdgeCollapse::Collapse( edge_descriptor con #endif if ( lPlacement ) + { + CGAL_ECMS_TRACE(2,"New vertex point: " << xyz_to_string(*lPlacement) ) ; put(vertex_point,mSurface,rResult,*lPlacement) ; + } Update_neighbors(rResult) ; CGAL_ECMS_DEBUG_CODE ( ++mStep ; ) } -template -void EdgeCollapse::Update_neighbors( vertex_descriptor const& aKeptV ) +template +void EdgeCollapse::Update_neighbors( vertex_descriptor const& aKeptV ) { CGAL_ECMS_TRACE(3,"Updating cost of neighboring edges..." ) ; @@ -531,7 +495,9 @@ void EdgeCollapse::Update_neighbors( vertex_desc Edge_data& lData = get_data(lEdge); - lData.cost() = get_cost(lEdge) ; + Profile const& lProfile = create_profile(lEdge); + + lData.cost() = get_cost(lProfile) ; CGAL_ECMS_TRACE(3, edge_to_string(lEdge) << " updated in the PQ") ; diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_ratio_stop_predicate.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_ratio_stop_predicate.h index acf0564f62a..5b611865218 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_ratio_stop_predicate.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_ratio_stop_predicate.h @@ -19,6 +19,7 @@ #define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_COUNT_RATIO_STOP_PREDICATE_H 1 #include +#include CGAL_BEGIN_NAMESPACE @@ -43,6 +44,8 @@ public: typedef ECM_ ECM ; + typedef Edge_profile Profile ; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor ; typedef typename boost::graph_traits::edges_size_type size_type ; @@ -54,10 +57,10 @@ public : Count_ratio_stop_predicate( double aRatio ) : mRatio(aRatio) {} - bool operator()( FT const& // aCurrentCost - , edge_descriptor const& //aEdge - , size_type aInitialCount - , size_type aCurrentCount + bool operator()( FT const& // aCurrentCost + , Profile const& //aEdgeProfile + , size_type aInitialCount + , size_type aCurrentCount ) const { return ( static_cast(aCurrentCount) / static_cast(aInitialCount) ) < mRatio ; diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_stop_predicate.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_stop_predicate.h index 46e10c3f4b5..475cb769f96 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_stop_predicate.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_stop_predicate.h @@ -19,6 +19,7 @@ #define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_COUNT_STOP_PREDICATE_H 1 #include +#include CGAL_BEGIN_NAMESPACE @@ -43,6 +44,8 @@ public: typedef ECM_ ECM ; + typedef Edge_profile Profile ; + private : typedef typename halfedge_graph_traits::Point Point ; @@ -59,10 +62,10 @@ public : Count_stop_predicate( size_type aThres ) : mThres(aThres) {} - bool operator()( FT const& // aCurrentCost - , edge_descriptor const& //aEdge - , size_type aInitialCount - , size_type aCurrentCount + bool operator()( FT const& // aCurrentCost + , Profile const& //aEdgeProfile + , size_type aInitialCount + , size_type aCurrentCount ) const { return aCurrentCount < mThres ; diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Detail/Lindstrom_Turk_core.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Detail/Lindstrom_Turk_core.h index b1144500e12..85d963b97da 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Detail/Lindstrom_Turk_core.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Detail/Lindstrom_Turk_core.h @@ -21,6 +21,7 @@ #include #include +#include #include CGAL_BEGIN_NAMESPACE @@ -44,6 +45,8 @@ public: typedef ECM_ ECM ; + typedef Edge_profile Profile ; + typedef boost::graph_traits GraphTraits ; typedef typename GraphTraits::vertex_descriptor vertex_descriptor ; @@ -65,40 +68,37 @@ public: typedef MatrixC33 Matrix ; + typedef typename Profile::Triangle Triangle ; + typedef typename Profile::vertex_descriptor_vector vertex_descriptor_vector ; + + typedef typename Profile::Triangle_vector ::const_iterator const_triangle_iterator ; + typedef typename Profile::edge_descriptor_vector::const_iterator const_border_edge_iterator ; + public: - LindstromTurkCore( Params const& aParams - , edge_descriptor const& aP_Q - , ECM& aSurface - ) ; + LindstromTurkCore( Params const& aParams, Profile const& aProfile ) ; Optional_point compute_placement() ; Optional_FT compute_cost( Optional_point const& p ) ; private : - struct Triangle + struct Triangle_data { - Triangle() {} - - Triangle( Vector const& aNormalV, FT const& aNormalL ) : NormalV(aNormalV), NormalL(aNormalL) {} + Triangle_data( Vector const& aNormalV, FT const& aNormalL ) : NormalV(aNormalV), NormalL(aNormalL) {} Vector NormalV ; FT NormalL ; } ; - - typedef std::vector Triangles ; - typedef std::vector Link ; - typedef std::vector edge_descriptor_vector ; - - struct BoundaryEdge + struct Boundary_data { - BoundaryEdge ( Point s_, Point t_, Vector const& v_, Vector const& n_ ) : s(s_), t(t_), v(v_), n(n_) {} + Boundary_data ( Point s_, Point t_, Vector const& v_, Vector const& n_ ) : s(s_), t(t_), v(v_), n(n_) {} Point s, t ; Vector v, n ; } ; - typedef std::vector BoundaryEdges ; + typedef std::vector Triangle_data_vector ; + typedef std::vector Boundary_data_vector ; class Constrians { @@ -123,27 +123,21 @@ private : private : - void Add_boundary_preservation_constrians( BoundaryEdges const& aBdry ) ; - void Add_volume_preservation_constrians( Triangles const& aTriangles ); - void Add_boundary_and_volume_optimization_constrians( BoundaryEdges const& aBdry, Triangles const& aTriangles ) ; - void Add_shape_optimization_constrians( Link const& aLink ) ; + void Extract_triangle_data(); + void Extract_boundary_data() ; + + void Add_boundary_preservation_constrians( Boundary_data_vector const& aBdry ) ; + void Add_volume_preservation_constrians( Triangle_data_vector const& aTriangles ); + void Add_boundary_and_volume_optimization_constrians( Boundary_data_vector const& aBdry, Triangle_data_vector const& aTriangles ) ; + void Add_shape_optimization_constrians( vertex_descriptor_vector const& aLink ) ; - FT Compute_boundary_cost( Vector const& v, BoundaryEdges const& aBdry ) ; - FT Compute_volume_cost ( Vector const& v, Triangles const& aTriangles ) ; - FT Compute_shape_cost ( Point const& p, Link const& aLink ) ; - - bool is_border ( edge_descriptor const& edge ) const - { - return get(edge_is_border,mSurface,edge) ; - } - bool is_undirected_edge_a_border ( edge_descriptor const& edge ) const - { - return is_border(edge) || is_border(opposite_edge(edge,mSurface)) ; - } + FT Compute_boundary_cost( Vector const& v, Boundary_data_vector const& aBdry ) ; + FT Compute_volume_cost ( Vector const& v, Triangle_data_vector const& aTriangles ) ; + FT Compute_shape_cost ( Point const& p, vertex_descriptor_vector const& aLink ) ; Point const& get_point ( vertex_descriptor const& v ) const { - return get(vertex_point,mSurface,v); + return get(vertex_point,surface(),v); } static Vector Point_cross_product ( Point const& a, Point const& b ) @@ -172,39 +166,19 @@ private : ); } - Triangle Get_triangle ( vertex_descriptor const& v0 - , vertex_descriptor const& v1 - , vertex_descriptor const& v2 - ) ; - - void Extract_triangle( vertex_descriptor const& v0 - , vertex_descriptor const& v1 - , vertex_descriptor const& v2 - , edge_descriptor const& e02 - ) ; - - void Extract_triangles_and_link(); - - void Extract_boundary_edge ( edge_descriptor edge) ; - void Extract_boundary_edges( vertex_descriptor const& v, edge_descriptor_vector& rCollected ) ; - void Extract_boundary_edges() ; + ECM& surface() const { return mProfile.surface() ; } private: - Params const& mParams ; - edge_descriptor const& mP_Q ; - ECM& mSurface ; - - vertex_descriptor mP ; - vertex_descriptor mQ ; - edge_descriptor mQ_P ; + Params const& mParams ; + Profile const& mProfile ; private: - Triangles mTriangles; - Link mLink; - BoundaryEdges mBdry ; - Constrians mConstrians ; + Triangle_data_vector mTriangle_data ; + Boundary_data_vector mBdry_data ; + + Constrians mConstrians ; }; } // namespace Surface_mesh_simplification diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Detail/Lindstrom_Turk_core_impl.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Detail/Lindstrom_Turk_core_impl.h index 9eb079d2cfd..908a4639be9 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Detail/Lindstrom_Turk_core_impl.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Detail/Lindstrom_Turk_core_impl.h @@ -31,38 +31,65 @@ namespace Surface_mesh_simplification { template -LindstromTurkCore::LindstromTurkCore( Params const& aParams - , edge_descriptor const& aP_Q - , ECM& aSurface - ) +LindstromTurkCore::LindstromTurkCore( Params const& aParams, Profile const& aProfile ) : mParams(aParams) - ,mP_Q(aP_Q) - ,mSurface(aSurface) - - ,mP ( source (aP_Q,aSurface) ) - ,mQ ( target (aP_Q,aSurface) ) - ,mQ_P( opposite_edge(aP_Q,aSurface) ) + ,mProfile(aProfile) { + Extract_triangle_data(); + Extract_boundary_data(); +} - mTriangles.clear(); - mLink .clear(); - mTriangles.reserve(16); - mLink .reserve(16); +template +void LindstromTurkCore::Extract_boundary_data() +{ + for ( const_border_edge_iterator it = mProfile.border_edges().begin(), eit = mProfile.border_edges().end() ; it != eit ; ++ it ) + { + edge_descriptor border_edge = *it ; + + edge_descriptor face_edge = opposite_edge(border_edge,surface()) ; + + vertex_descriptor sv = source(face_edge,surface()); + vertex_descriptor tv = target(face_edge,surface()); + + Point const& sp = get_point(sv); + Point const& tp = get_point(tv); + + Vector v = tp - sp ; + Vector n = Point_cross_product(tp,sp) ; + + CGAL_ECMS_LT_TRACE(3,"Boundary edge. S:" << xyz_to_string(sp) << " T:" << xyz_to_string(tp) + << " V:" << xyz_to_string(v) << " N:" << xyz_to_string(n) + ) ; + + mBdry_data.push_back( Boundary_data(sp,tp,v,n) ) ; + } +} - // Volume preservation and optimization constrians are based on the normals to the triangles in the star of the collapsing egde - // Triangle shape optimization constrians are based on the link of the collapsing edge (the cycle of vertices around the edge) - Extract_triangles_and_link(); - -#ifdef CGAL_SURFACE_SIMPLIFICATION_ENABLE_LT_TRACE - std::ostringstream ss ; - for( typename Link::const_iterator it = mLink.begin(), eit = mLink.end() ; it != eit ; ++it ) - ss << "v" << (*it)->ID << " " ; - std::string s = ss.str(); - CGAL_ECMS_LT_TRACE(3,"Link: " << s ); -#endif - - Extract_boundary_edges(); +template +void LindstromTurkCore::Extract_triangle_data() +{ + for ( const_triangle_iterator it = mProfile.triangles().begin(), eit = mProfile.triangles().end() ; it != eit ; ++ it ) + { + Triangle const& tri = *it ; + + Point const& p0 = get_point(tri.v0); + Point const& p1 = get_point(tri.v1); + Point const& p2 = get_point(tri.v2); + + Vector v01 = p1 - p0 ; + Vector v02 = p2 - p0 ; + + Vector lNormalV = cross_product(v01,v02); + + FT lNormalL = Point_cross_product(p0,p1) * (p2-ORIGIN); + + CGAL_ECMS_LT_TRACE(3,"Extracting triangle v" << lTri.v0->id() << "->v" << lTri.v1->id() << "->v" << lTri.v2->id() + << " N:" << xyz_to_string(lNormalV) << " L:" << lNormalL + ); + + mTriangle_data.push_back(Triangle_data(lNormalV,lNormalL)); + } } template @@ -71,7 +98,7 @@ typename LindstromTurkCore::Optional_point LindstromTurkCore::compute_ Optional_point rPlacementP ; Optional_vector lPlacementV ; - CGAL_ECMS_LT_TRACE(2,"Computing LT data for E" << mP_Q->ID << " (V" << mP->ID << "->V" << mQ->ID << ")" ); + CGAL_ECMS_LT_TRACE(2,"Computing LT data for E" << mProfile.v0v1()->id() << " (V" << mProfile.v0()->id() << "->V" << mProfile.v1()->id() << ")" ); // // Each vertex constrian is an equation of the form: Ai * v = bi @@ -96,17 +123,17 @@ typename LindstromTurkCore::Optional_point LindstromTurkCore::compute_ // // A constrian (Ai,bi) must be alpha-compatible with the previously added constrians (see Paper); if it's not, is discarded. // - if ( mBdry.size() > 0 ) - Add_boundary_preservation_constrians(mBdry); + if ( mBdry_data.size() > 0 ) + Add_boundary_preservation_constrians(mBdry_data); if ( mConstrians.n < 3 ) - Add_volume_preservation_constrians(mTriangles); + Add_volume_preservation_constrians(mTriangle_data); if ( mConstrians.n < 3 ) - Add_boundary_and_volume_optimization_constrians(mBdry,mTriangles); + Add_boundary_and_volume_optimization_constrians(mBdry_data,mTriangle_data); if ( mConstrians.n < 3 ) - Add_shape_optimization_constrians(mLink); + Add_shape_optimization_constrians(mProfile.link()); // It might happen that there were not enough alpha-compatible constrians. // In that case there is simply no good vertex placement @@ -141,18 +168,15 @@ typename LindstromTurkCore::Optional_FT LindstromTurkCore::compute_cos if ( aP ) { - Point const& lP = get_point(mP) ; - Point const& lQ = get_point(mQ) ; - Vector lV = (*aP) - ORIGIN ; - FT lSquaredLength = squared_distance(lP,lQ); + FT lSquaredLength = squared_distance(mProfile.p0(),mProfile.p1()); CGAL_ECMS_LT_TRACE(1,"Squared edge length: " << lSquaredLength ) ; - FT lBdryCost = Compute_boundary_cost(lV ,mBdry); - FT lVolumeCost = Compute_volume_cost (lV ,mTriangles); - FT lShapeCost = Compute_shape_cost (*aP,mLink); + FT lBdryCost = Compute_boundary_cost(lV ,mBdry_data); + FT lVolumeCost = Compute_volume_cost (lV ,mTriangle_data); + FT lShapeCost = Compute_shape_cost (*aP,mProfile.link()); FT lTotalCost = FT(mParams.VolumeWeight) * lVolumeCost + FT(mParams.BoundaryWeight) * lBdryCost * lSquaredLength @@ -172,194 +196,16 @@ typename LindstromTurkCore::Optional_FT LindstromTurkCore::compute_cos } -// -// Caches the "local boundary", that is, the sequence of 3 border edges: o->p, p->q, q->e -// template -void LindstromTurkCore::Extract_boundary_edge( edge_descriptor edge ) +void LindstromTurkCore::Add_boundary_preservation_constrians( Boundary_data_vector const& aBdry ) { - edge_descriptor face_edge = is_border(edge) ? opposite_edge(edge,mSurface) : edge ; - - vertex_descriptor sv = source(face_edge,mSurface); - vertex_descriptor tv = target(face_edge,mSurface); - - Point const& sp = get_point(sv); - Point const& tp = get_point(tv); - - Vector v = tp - sp ; - Vector n = Point_cross_product(tp,sp) ; - - CGAL_ECMS_LT_TRACE(3,"Boundary edge. S:" << xyz_to_string(sp) << " T:" << xyz_to_string(tp) - << " V:" << xyz_to_string(v) << " N:" << xyz_to_string(n) - ) ; - - mBdry.push_back( BoundaryEdge(sp,tp,v,n) ) ; -} - -template -void LindstromTurkCore::Extract_boundary_edges( vertex_descriptor const& v - , edge_descriptor_vector& rCollected - ) -{ - in_edge_iterator eb, ee ; - for ( tie(eb,ee) = in_edges(v,mSurface) ; eb != ee ; ++ eb ) - { - edge_descriptor edge = *eb ; - - if ( is_undirected_edge_a_border(edge) && std::find(rCollected.begin(),rCollected.end(),edge) == rCollected.end() ) - { - Extract_boundary_edge(edge); - rCollected.push_back(edge); - rCollected.push_back(opposite_edge(edge,mSurface)); - } - } -} - -template -void LindstromTurkCore::Extract_boundary_edges() -{ - edge_descriptor_vector lCollected ; - Extract_boundary_edges(mP,lCollected); - Extract_boundary_edges(mQ,lCollected); -} - -// -// Calculates the normal of the triangle (v0,v1,v2) (both vector and its length as (v0xv1).v2) -// -template -typename LindstromTurkCore::Triangle LindstromTurkCore::Get_triangle( vertex_descriptor const& v0 - , vertex_descriptor const& v1 - , vertex_descriptor const& v2 - ) -{ - Point const& p0 = get_point(v0); - Point const& p1 = get_point(v1); - Point const& p2 = get_point(v2); - - Vector v01 = p1 - p0 ; - Vector v02 = p2 - p0 ; - - Vector lNormalV = cross_product(v01,v02); - - FT lNormalL = Point_cross_product(p0,p1) * (p2-ORIGIN); - - CGAL_ECMS_LT_TRACE(3,"Extracting triangle v" << v0->ID << "->v" << v1->ID << "->v" << v2->ID - << " N:" << xyz_to_string(lNormalV) << " L:" << lNormalL - ); - - return Triangle(lNormalV,lNormalL); -} - -// -// If (v0,v1,v2) is a finite triangular facet of the mesh, that is, NONE of these vertices are boundary vertices, -// the triangle (properly oriented) is added to rTriangles. -// The triangle is encoded as its normal, calculated using the actual facet orientation [(v0,v1,v2) or (v0,v2,v1)] -// -template -void LindstromTurkCore::Extract_triangle( vertex_descriptor const& v0 - , vertex_descriptor const& v1 - , vertex_descriptor const& v2 - , edge_descriptor const& e02 - ) -{ - // The 3 vertices are obtained by circulating ccw around v0, that is, e02 = next_ccw(e01). - // Since these vertices are NOT obtained by circulating the face, the actual triangle orientation is unspecified. - - // The triangle is oriented v0->v2->v1 if the next edge that follows e02 (which is the edge v0->v2) is v2->v1. - if ( target(next_edge(e02,mSurface),mSurface) == v1 ) - { - // The triangle is oriented v0->v2->v1. - // In this case e02 is an edge of the facet. - // If this facet edge is a border edge then this triangle is not in the mesh . - if ( !is_border(e02) ) - mTriangles.push_back(Get_triangle(v0,v2,v1) ) ; - } - else - { - // The triangle is oriented v0->v1->v2. - // In this case, e20 and not e02, is an edge of the facet. - // If this facet edge is a border edge then this triangle is not in the mesh . - if ( !is_border(opposite_edge(e02,mSurface)) ) - mTriangles.push_back(Get_triangle(v0,v1,v2) ) ; - } -} - -// -// Extract all triangles (its normals) and vertices (the link) around the collpasing edge p_q -// -template -void LindstromTurkCore::Extract_triangles_and_link() -{ - // - // Extract around mP, CCW - // - vertex_descriptor v0 = mP; - vertex_descriptor v1 = mQ; - - edge_descriptor e02 = mP_Q; - - do - { - e02 = next_edge_ccw(e02,mSurface); - - vertex_descriptor v2 = target(e02,mSurface); - - if ( v2 != mQ ) - { - CGAL_expensive_assertion ( std::find(mLink.begin(),mLink.end(),v2) == mLink.end() ) ; - mLink.push_back(v2) ; - } - - Extract_triangle(v0,v1,v2,e02); - - v1 = v2 ; - } - while ( e02 != mP_Q ) ; - - // - // Extract around mQ, CCW - // - - v0 = mQ; - - e02 = next_edge_ccw(mQ_P,mSurface); - - v1 = target(e02,mSurface); - - // This could have been added to the link while circulating around mP - if ( v1 != mP && std::find(mLink.begin(),mLink.end(),v1) == mLink.end() ) - mLink.push_back(v1) ; - - e02 = next_edge_ccw(e02,mSurface); - - do - { - vertex_descriptor v2 = target(e02,mSurface); - - // Any of the vertices found around mP can be reached again around mQ, but we can't duplicate them here. - if ( v2 != mP && std::find(mLink.begin(),mLink.end(),v2) == mLink.end() ) - mLink.push_back(v2) ; - - Extract_triangle(v0,v1,v2,e02); - - v1 = v2 ; - - e02 = next_edge_ccw(e02,mSurface); - - } - while ( e02 != mQ_P ) ; -} - -template -void LindstromTurkCore::Add_boundary_preservation_constrians( BoundaryEdges const& aBdry ) -{ - + if ( aBdry.size() > 0 ) { Vector e1 = NULL_VECTOR ; Vector e2 = NULL_VECTOR ; - for ( typename BoundaryEdges::const_iterator it = aBdry.begin() ; it != aBdry.end() ; ++ it ) + for ( typename Boundary_data_vector::const_iterator it = aBdry.begin() ; it != aBdry.end() ; ++ it ) { e1 = e1 + it->v ; e2 = e2 + it->n ; @@ -376,14 +222,14 @@ void LindstromTurkCore::Add_boundary_preservation_constrians( BoundaryEdges } template -void LindstromTurkCore::Add_volume_preservation_constrians( Triangles const& aTriangles ) +void LindstromTurkCore::Add_volume_preservation_constrians( Triangle_data_vector const& aTriangles ) { CGAL_ECMS_LT_TRACE(2,"Adding volume preservation constrians. " << aTriangles.size() << " triangles."); Vector lSumV = NULL_VECTOR ; FT lSumL(0) ; - for( typename Triangles::const_iterator it = aTriangles.begin(), eit = aTriangles.end() ; it != eit ; ++it ) + for( typename Triangle_data_vector::const_iterator it = aTriangles.begin(), eit = aTriangles.end() ; it != eit ; ++it ) { lSumV = lSumV + it->NormalV ; lSumL = lSumL + it->NormalL ; @@ -394,7 +240,9 @@ void LindstromTurkCore::Add_volume_preservation_constrians( Triangles const } template -void LindstromTurkCore::Add_boundary_and_volume_optimization_constrians( BoundaryEdges const& aBdry, Triangles const& aTriangles ) +void LindstromTurkCore::Add_boundary_and_volume_optimization_constrians( Boundary_data_vector const& aBdry + , Triangle_data_vector const& aTriangles + ) { CGAL_ECMS_LT_TRACE(2,"Adding boundary and volume optimization constrians. "); @@ -404,9 +252,9 @@ void LindstromTurkCore::Add_boundary_and_volume_optimization_constrians( Bo // // Volume optimization // - for( typename Triangles::const_iterator it = aTriangles.begin(), eit = aTriangles.end() ; it != eit ; ++it ) + for( typename Triangle_data_vector::const_iterator it = aTriangles.begin(), eit = aTriangles.end() ; it != eit ; ++it ) { - Triangle const& lTri = *it ; + Triangle_data const& lTri = *it ; H += direct_product(lTri.NormalV,lTri.NormalV) ; @@ -424,7 +272,7 @@ void LindstromTurkCore::Add_boundary_and_volume_optimization_constrians( Bo Matrix Hb = NULL_MATRIX ; Vector cb = NULL_VECTOR ; - for ( typename BoundaryEdges::const_iterator it = aBdry.begin() ; it != aBdry.end() ; ++ it ) + for ( typename Boundary_data_vector::const_iterator it = aBdry.begin() ; it != aBdry.end() ; ++ it ) { Matrix H = LT_product(it->v); Vector c = cross_product(it->v,it->n); @@ -438,7 +286,7 @@ void LindstromTurkCore::Add_boundary_and_volume_optimization_constrians( Bo // // Weighted average // - FT lScaledBoundaryWeight = FT(9) * mParams.BoundaryWeight * squared_distance ( get_point(mP), get_point(mQ) ) ; + FT lScaledBoundaryWeight = FT(9) * mParams.BoundaryWeight * squared_distance(mProfile.p0(),mProfile.p1()) ; H *= mParams.VolumeWeight ; c = c * mParams.VolumeWeight ; @@ -454,7 +302,7 @@ void LindstromTurkCore::Add_boundary_and_volume_optimization_constrians( Bo } template -void LindstromTurkCore::Add_shape_optimization_constrians( Link const& aLink ) +void LindstromTurkCore::Add_shape_optimization_constrians( vertex_descriptor_vector const& aLink ) { FT s(aLink.size()); @@ -465,7 +313,7 @@ void LindstromTurkCore::Add_shape_optimization_constrians( Link const& aLin Vector c = NULL_VECTOR ; - for( typename Link::const_iterator it = aLink.begin(), eit = aLink.end() ; it != eit ; ++it ) + for( typename vertex_descriptor_vector::const_iterator it = aLink.begin(), eit = aLink.end() ; it != eit ; ++it ) c = c + (ORIGIN - get_point(*it)) ; CGAL_ECMS_LT_TRACE(2,"Adding shape optimization constrians: Shape vector: " << xyz_to_string(c) ); @@ -475,10 +323,10 @@ void LindstromTurkCore::Add_shape_optimization_constrians( Link const& aLin template typename LindstromTurkCore::FT -LindstromTurkCore::Compute_boundary_cost( Vector const& v, BoundaryEdges const& aBdry ) +LindstromTurkCore::Compute_boundary_cost( Vector const& v, Boundary_data_vector const& aBdry ) { FT rCost(0); - for ( typename BoundaryEdges::const_iterator it = aBdry.begin() ; it != aBdry.end() ; ++ it ) + for ( typename Boundary_data_vector::const_iterator it = aBdry.begin() ; it != aBdry.end() ; ++ it ) { Vector u = (it->t - ORIGIN ) - v ; Vector c = cross_product(it->v,u); @@ -489,13 +337,13 @@ LindstromTurkCore::Compute_boundary_cost( Vector const& v, BoundaryEdges co template typename LindstromTurkCore::FT -LindstromTurkCore::Compute_volume_cost( Vector const& v, Triangles const& aTriangles ) +LindstromTurkCore::Compute_volume_cost( Vector const& v, Triangle_data_vector const& aTriangles ) { FT rCost(0); - for( typename Triangles::const_iterator it = aTriangles.begin(), eit = aTriangles.end() ; it != eit ; ++it ) + for( typename Triangle_data_vector::const_iterator it = aTriangles.begin(), eit = aTriangles.end() ; it != eit ; ++it ) { - Triangle const& lTri = *it ; + Triangle_data const& lTri = *it ; FT lF = lTri.NormalV * v - lTri.NormalL ; @@ -508,11 +356,11 @@ LindstromTurkCore::Compute_volume_cost( Vector const& v, Triangles const& a template typename LindstromTurkCore::FT -LindstromTurkCore::Compute_shape_cost( Point const& p, Link const& aLink ) +LindstromTurkCore::Compute_shape_cost( Point const& p, vertex_descriptor_vector const& aLink ) { FT rCost(0); - for( typename Link::const_iterator it = aLink.begin(), eit = aLink.end() ; it != eit ; ++it ) + for( typename vertex_descriptor_vector::const_iterator it = aLink.begin(), eit = aLink.end() ; it != eit ; ++it ) rCost += squared_distance(p,get_point(*it)) ; return rCost ; diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Edge_length_cost.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Edge_length_cost.h index 2c287643cdb..c84e9aaf5e1 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Edge_length_cost.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Edge_length_cost.h @@ -19,6 +19,7 @@ #define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_EDGE_LENGHT_COST_H #include +#include CGAL_BEGIN_NAMESPACE @@ -36,52 +37,25 @@ public: typedef ECM_ ECM ; -private : - - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor ; + typedef Edge_profile Profile ; typedef typename halfedge_graph_traits::Point Point ; typedef typename Kernel_traits::Kernel Kernel ; -public: - - typedef typename boost::graph_traits::edge_descriptor edge_descriptor ; - typedef typename Kernel::FT FT ; typedef optional result_type ; - typedef void Params ; - - public: Edge_length_cost() {} - result_type operator()( edge_descriptor const& aEdge - , ECM& aSurface - , Params const* //aParams - , optional const& //aPlacement - ) const + result_type operator()( Profile const& aProfile, optional const& /*aPlacement*/ ) const { - vertex_descriptor vs,vt ; tie(vs,vt) = get_vertices(aEdge,aSurface); - - Point const& ps = get(vertex_point,aSurface,vs); - Point const& pt = get(vertex_point,aSurface,vt); - - return result_type(squared_distance(ps,pt)); + return result_type(squared_distance(aProfile.p0(),aProfile.p1())); } -private: - - tuple get_vertices ( edge_descriptor const& aEdge, ECM& aSurface ) const - { - vertex_descriptor p = source(aEdge,aSurface); - vertex_descriptor q = target(aEdge,aSurface); - return make_tuple(p,q); - } - }; diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/LindstromTurk_cost.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/LindstromTurk_cost.h index 62103aaf978..0b36b655a7a 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/LindstromTurk_cost.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/LindstromTurk_cost.h @@ -32,34 +32,27 @@ class LindstromTurk_cost public: typedef ECM_ ECM ; - - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor ; - typedef typename boost::graph_traits::edge_descriptor edge_descriptor ; - + + typedef Edge_profile Profile ; + typedef typename halfedge_graph_traits::Point Point ; typedef typename Kernel_traits::Kernel Kernel ; typedef typename Kernel::FT FT ; typedef optional result_type ; - typedef LindstromTurk_params Params ; - public: - LindstromTurk_cost() {} + LindstromTurk_cost( LindstromTurk_params const& aParams = LindstromTurk_params() ) : mParams(aParams) {} - result_type operator()( edge_descriptor const& aEdge - , ECM& aSurface - , Params const* aParams - , optional const& aPlacement - ) const + result_type operator()( Profile const& aProfile, optional const& aPlacement ) const { - CGAL_assertion(aParams); - CGAL_assertion( handle_assigned(aEdge) ); - - return LindstromTurkCore(*aParams,aEdge,aSurface).compute_cost(aPlacement) ; + return LindstromTurkCore(mParams,aProfile).compute_cost(aPlacement) ; } - + +private: + + LindstromTurk_params mParams ; }; } // namespace Surface_mesh_simplification diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/LindstromTurk_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/LindstromTurk_placement.h index b90480eae9f..34428d49ce3 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/LindstromTurk_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/LindstromTurk_placement.h @@ -33,26 +33,25 @@ public: typedef ECM_ ECM ; - typedef typename boost::graph_traits::edge_descriptor edge_descriptor ; - + typedef Edge_profile Profile ; + typedef typename halfedge_graph_traits::Point Point ; typedef optional result_type ; - typedef LindstromTurk_params Params ; - public: - result_type operator()( edge_descriptor const& aEdge - , ECM& aSurface - , Params const* aParams - ) const + LindstromTurk_placement( LindstromTurk_params const& aParams = LindstromTurk_params() ) : mParams(aParams) {} + + result_type operator()( Profile const& aProfile) const { - CGAL_assertion(aParams); - CGAL_assertion( handle_assigned(aEdge) ); - - return LindstromTurkCore(*aParams,aEdge,aSurface).compute_placement() ; + return LindstromTurkCore(mParams,aProfile).compute_placement() ; } + +private: + + LindstromTurk_params mParams ; + }; diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Midpoint_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Midpoint_placement.h index e94b7685a5c..84fe11deb75 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Midpoint_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Midpoint_placement.h @@ -19,6 +19,7 @@ #define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_MIDPOINT_PLACEMENT_H 1 #include +#include CGAL_BEGIN_NAMESPACE @@ -32,42 +33,21 @@ public: typedef ECM_ ECM ; - typedef typename boost::graph_traits::edge_descriptor edge_descriptor ; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor ; + typedef Edge_profile Profile ; typedef typename halfedge_graph_traits::Point Point ; - typedef typename Kernel_traits::Kernel Kernel ; - typedef typename Kernel::FT FT ; typedef optional result_type ; - typedef void Params ; - public: Midpoint_placement() {} - result_type operator()( edge_descriptor const& aEdge - , ECM& aSurface - , Params const* //aParams - ) const + result_type operator()( Profile const& aProfile ) const { - vertex_descriptor vs,vt ; tie(vs,vt) = get_vertices(aEdge,aSurface); - - Point const& ps = get(vertex_point,aSurface,vs); - Point const& pt = get(vertex_point,aSurface,vt); - - return result_type(midpoint(ps,pt)); + return result_type(midpoint(aProfile.p0(),aProfile.p1())); } - -private: - tuple get_vertices ( edge_descriptor const& aEdge, ECM& aSurface ) const - { - vertex_descriptor p = source(aEdge,aSurface); - vertex_descriptor q = target(aEdge,aSurface); - return make_tuple(p,q); - } }; } // namespace Surface_mesh_simplification diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/edge_collapse.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/edge_collapse.h index eb81c7c6947..5c4e12c9d6a 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/edge_collapse.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/edge_collapse.h @@ -29,76 +29,37 @@ CGAL_BEGIN_NAMESPACE namespace Surface_mesh_simplification { - -// -// Edge-collapse method: -// -// Simplifies a triangulated surface mesh by iteratively selecting and collapsing edges. -// -// Not all edges are selected for removal; those which cannot be removed are labled "fixed" -// and there are two kinds of fixed pairs: Intrisically fixed and explicitely fixed. -// Intrinsically fixed edges are those which, if removed, would result in a topologically incosistent mesh. -// (the algorithm automatically detects intrinsically fixed edges). -// Explicitely fixed edges appear when the two vertices incident on the edge have been marked by the user as fixed, -// via the "VertexIsFixedMap" property map. -// -// For each non-fixed edge in the mesh, a "collapse data" record is constructed by calling the user-supplied function -// "SetCollapseData". -// The edge is then associated with its collapse data via the "EdgeExtraPtrMap" property map. -// -// The user-supplied function "GetCost" is called, for each non-fixed edge. -// This function returns a value which defines the collapsing cost of the edge. Edges with a lower cost are collapsed first. -// -// When a non-fixed edge is selected for removal, a user-supplied function "GetNewVertexPoint" is called. -// This function returns a Point_3 which defines the coordinates of the single vertex that replaces the collapsed edge. -// -// The simplification continues until there are no more non-fixed edges to collapse or the user-defined function "ShouldStop" -// returns true. -// -// NOTE: The functions GetCost and GetNewVertexPoint return 'optional values'. This is to allow the function to reject an -// edge becasue it's cost is too high or uncomputable or the new vertex point cannot be placed in any way that -// satisfies the constriants required by method used in these functions. -// Consequently, not all non-fixed edges are neccessarily removed. -// -// This global function returns the number of edges collapsed. -// template int edge_collapse ( ECM& aSurface , ShouldStop const& aShould_stop // optional mesh information policies - , VertexPointMap const& aVertex_point_map // defaults to get(Vertex_point,aSurface) - , EdgeIndexMap const& aEdge_index_map // defaults to get(Edge_index,aSurface) - , EdgeIsBorderMap const& aEdge_is_border_map // defaults to get(Edge_is_border,aSurface) + , VertexIndexMap const& aVertex_index_map // defaults to get(vertex_index,aSurface) + , EdgeIndexMap const& aEdge_index_map // defaults to get(edge_index,aSurface) + , EdgeIsBorderMap const& aEdge_is_border_map // defaults to get(edge_is_border,aSurface) // optional strategy policies - defaults to LindstomTurk , GetCost const& aGet_cost , GetPlacement const& aGet_placement - , CostParams const* aCostParams // Can be NULL - , PlacementParams const* aPlacementParams // Can be NULL , Visitor* aVisitor // Can be NULL ) { typedef EdgeCollapse< ECM , ShouldStop - , VertexPointMap + , VertexIndexMap , EdgeIndexMap , EdgeIsBorderMap , GetCost , GetPlacement - , CostParams - , PlacementParams , Visitor > Algorithm @@ -106,13 +67,11 @@ int edge_collapse ( ECM& aSurface Algorithm algorithm( aSurface , aShould_stop - , aVertex_point_map + , aVertex_index_map , aEdge_index_map , aEdge_is_border_map , aGet_cost , aGet_placement - , aCostParams - , aPlacementParams , aVisitor ) ; @@ -160,13 +119,11 @@ int edge_collapse ( ECM& aSurface return edge_collapse(aSurface ,aShould_stop - ,choose_const_pmap(get_param(aParams,vertex_point),aSurface,vertex_point) + ,choose_const_pmap(get_param(aParams,boost::vertex_index),aSurface,boost::vertex_index) ,choose_const_pmap(get_param(aParams,boost::edge_index),aSurface,boost::edge_index) ,choose_const_pmap(get_param(aParams,edge_is_border),aSurface,edge_is_border) ,choose_param (get_param(aParams,get_cost_policy), LindstromTurk_cost()) ,choose_param (get_param(aParams,get_placement_policy), LindstromTurk_placement()) - ,choose_param (get_param(aParams,get_cost_policy_params), &lPolicyParams) - ,choose_param (get_param(aParams,get_placement_policy_params), &lPolicyParams) ,choose_param (get_param(aParams,vis), ((Dummy_visitor*)0)) ) ;