Clean SMS code (whitespace, indentation, variable names, clumsy for loops, etc)

This commit is contained in:
Mael Rouxel-Labbé 2019-05-09 09:31:35 +02:00
parent 4747f8ccaf
commit 6d8d0b564c
29 changed files with 579 additions and 633 deletions

View File

@ -6,42 +6,41 @@ namespace Surface_mesh_simplification {
\ingroup PkgSurfaceMeshSimplificationRef
The class `Count_ratio_stop_predicate` is a model for the `StopPredicate` concept
which returns `true` when the relation between the initial and current number of edges drops below a certain ratio.
which returns `true` when the relation between the initial and current number of edges drops below a certain ratio.
\tparam TriangleMesh is the type of surface mesh being simplified, and must be a model of the `MutableFaceGraph` and `HalfedgeListGraph` concepts.
\cgalModels `StopPredicate`
\sa `CGAL::Surface_mesh_simplification::Count_stop_predicate<TriangleMesh>`
\sa `CGAL::Surface_mesh_simplification::Count_stop_predicate<TriangleMesh>`
*/
template< typename TriangleMesh >
class Count_ratio_stop_predicate {
class Count_ratio_stop_predicate
{
public:
/// \name Creation
/// \name Creation
/// @{
/*!
Initializes the predicate establishing the `ratio`.
*/
Count_ratio_stop_predicate<TriangleMesh>(double ratio);
Initializes the predicate establishing the `ratio`.
*/
Count_ratio_stop_predicate<TriangleMesh>(double ratio);
/// @}
/// @}
/// \name Operations
/// \name Operations
/// @{
/*!
Returns ` (((double)current_count / (double)initial_count) < ratio)`.
All other parameters are ignored (but exist since this is a generic policy).
*/
bool operator()(FT const& current_cost
, const Profile& edge_profile
, size_type initial_count
, size_type current_count
) const;
Returns ` (((double)current_count / (double)initial_count) < ratio)`.
All other parameters are ignored (but exist since this is a generic policy).
*/
bool operator()(const FT& current_cost,
const Profile& edge_profile,
size_type initial_count,
size_type current_count) const;
/// @}

View File

@ -1,4 +1,3 @@
namespace CGAL {
namespace Surface_mesh_simplification {
@ -6,40 +5,39 @@ namespace Surface_mesh_simplification {
\ingroup PkgSurfaceMeshSimplificationRef
The class `Count_stop_predicate` is a model for the `StopPredicate` concept,
which returns `true` when the number of current edges drops below a certain threshold.
which returns `true` when the number of current edges drops below a certain threshold.
\tparam TriangleMesh is the type of surface mesh being simplified, and must be a model of the `MutableFaceGraph` and `HalfedgeListGraph` concepts.
\cgalModels `StopPredicate`
\sa `CGAL::Surface_mesh_simplification::Count_ratio_stop_predicate<TriangleMesh>`
\sa `CGAL::Surface_mesh_simplification::Count_ratio_stop_predicate<TriangleMesh>`
*/
template< typename TriangleMesh >
class Count_stop_predicate {
public:
/// \name Creation
/// \name Creation
/// @{
/*!
Initializes the predicate establishing the `threshold` value.
*/
Count_stop_predicate<TriangleMesh>(size_type threshold);
Initializes the predicate establishing the `threshold` value.
*/
Count_stop_predicate<TriangleMesh>(size_type threshold);
/// @}
/// @}
/// \name Operations
/// \name Operations
/// @{
/*!
Returns `(current_count < threshold)`. All other parameters are ignored (but exist since this is a generic policy).
*/
bool operator()(FT const& current_cost
, const Profile& edge_profile
, size_type initial_count
, size_type current_count
) const;
Returns `(current_count < threshold)`. All other parameters are ignored (but exist since this is a generic policy).
*/
bool operator()(const FT& current_cost,
const Profile& edge_profile,
size_type initial_count,
size_type current_count) const;
/// @}

View File

@ -1,4 +1,3 @@
namespace CGAL {
namespace Surface_mesh_simplification {
@ -6,41 +5,41 @@ namespace Surface_mesh_simplification {
\ingroup PkgSurfaceMeshSimplificationRef
The class `Edge_length_cost` is a model for the `GetCost` concept,
which computes the collapse cost as the squared length of the edge.
which computes the collapse cost as the squared length of the edge.
\tparam TriangleMesh is the type of surface mesh being simplified, and must be a model of the `MutableFaceGraph` and `HalfedgeListGraph` concepts.
\cgalModels `GetCost`
*/
template< typename TriangleMesh >
class Edge_length_cost {
class Edge_length_cost
{
public:
/// \name Creation
/// \name Creation
/// @{
/*!
Default constructor
*/
Edge_length_cost<TriangleMesh>();
Default constructor
*/
Edge_length_cost<TriangleMesh>();
/// @}
/// @}
/// \name Operations
/// \name Operations
/// @{
/*!
Returns the <I>collapse cost</I> as the squared distance between the points
of the source and target vertices (that is, `profile.p0()` and `profile.p1()`.
Returns the <I>collapse cost</I> as the squared distance between the points
of the source and target vertices (that is, `profile.p0()` and `profile.p1()`.
The `placement` argument is ignored.
The `placement` argument is ignored.
*/
template <typename Profile, typename T>
optional<typename Profile::FT> operator()(const Profile& profile
, T const& placement) const;
*/
template <typename Profile, typename T>
optional<typename Profile::FT> operator()(const Profile& profile,
const T& placement) const;
/// @}

View File

@ -15,7 +15,8 @@ This predicate is meant to be used with `Edge_length_cost`.
*/
template< typename FT >
class Edge_length_stop_predicate {
class Edge_length_stop_predicate
{
public:
/// \name Creation
@ -35,11 +36,10 @@ Edge_length_stop_predicate<TriangleMesh>(FT threshold);
Returns `(CGAL::squared_distance(edge_profile.p0(),edge_profile.p1()) > threshold*threshold)`.
All other parameters are ignored (but exist since this is a generic policy).
*/
bool operator()(FT const&
, const Profile& edge_profile
, size_type
, size_type
) const;
bool operator()(const FT&,
const Profile& edge_profile,
size_type,
size_type) const;
/// @}

View File

@ -1,46 +1,45 @@
namespace CGAL {
namespace Surface_mesh_simplification {
/*!
\ingroup PkgSurfaceMeshSimplificationRef
The class `LindstromTurk_cost` provides a model for the `GetCost` concept.
It computes the collapse cost following the Lindstrom-Turk strategy
(Section \ref SurfaceMeshSimplificationLindstromTurkStrategy)
The class `LindstromTurk_cost` provides a model for the `GetCost` concept.
It computes the collapse cost following the Lindstrom-Turk strategy
(Section \ref SurfaceMeshSimplificationLindstromTurkStrategy)
\tparam TriangleMesh is the type of surface mesh being simplified, and must be a model of the `MutableFaceGraph` and `HalfedgeListGraph` concepts.
\cgalModels `GetCost`
\sa `CGAL::Surface_mesh_simplification::LindstromTurk_placement<TriangleMesh>`
\sa `CGAL::Surface_mesh_simplification::LindstromTurk_placement<TriangleMesh>`
*/
template< typename TriangleMesh >
class LindstromTurk_cost {
public:
/// \name Creation
/// \name Creation
/// @{
/*!
Initializes the policy with the given <I>weighting unit factor</I>.
See \ref SurfaceMeshSimplificationLindstromTurkStrategy for details on the meaning of this factor.
*/
LindstromTurk_cost<TriangleMesh>(FT const& factor = FT(0.5));
Initializes the policy with the given <I>weighting unit factor</I>.
See \ref SurfaceMeshSimplificationLindstromTurkStrategy for details on the meaning of this factor.
*/
LindstromTurk_cost<TriangleMesh>(const FT& factor = FT(0.5));
/// @}
/// @}
/// \name Operations
/// \name Operations
/// @{
/*!
Returns the cost of collapsing the edge (represented by its profile) considering
the new `placement` computed for it.
*/
Returns the cost of collapsing the edge (represented by its profile) considering
the new `placement` computed for it.
*/
template <typename Profile>
optional<typename Profile::FT>
operator()(const Profile& profile
, boost::optional<typename Profile::Point> const& placement) const;
operator()(const Profile& profile,
const boost::optional<typename Profile::Point>& placement) const
/// @}

View File

@ -1,47 +1,46 @@
namespace CGAL {
namespace Surface_mesh_simplification {
/*!
\ingroup PkgSurfaceMeshSimplificationRef
The class `LindstromTurk_placement` provides a model for the `GetPlacement` concept.
It computes the placement, that is, the new position for the remaining vertex after
a halfedge-collapse, following the Lindstrom-Turk strategy
(Section \ref SurfaceMeshSimplificationLindstromTurkStrategy).
The class `LindstromTurk_placement` provides a model for the `GetPlacement` concept.
It computes the placement, that is, the new position for the remaining vertex after
a halfedge-collapse, following the Lindstrom-Turk strategy
(Section \ref SurfaceMeshSimplificationLindstromTurkStrategy).
\tparam TriangleMesh is the type of surface mesh being simplified, and must be a model of the `MutableFaceGraph` and `HalfedgeListGraph` concepts.
\cgalModels `GetPlacement`
\sa `CGAL::Surface_mesh_simplification::LindstromTurk_cost<TriangleMesh>`
\sa `CGAL::Surface_mesh_simplification::LindstromTurk_cost<TriangleMesh>`
*/
template< typename TriangleMesh >
class LindstromTurk_placement {
public:
/// \name Creation
/// \name Creation
/// @{
/*!
Initializes the policy with the given <I>weighting unit factor</I>.
See \ref SurfaceMeshSimplificationLindstromTurkStrategy for details on the meaning of this factor.
*/
LindstromTurk_placement<TriangleMesh>(FT const& factor = FT(0.5));
Initializes the policy with the given <I>weighting unit factor</I>.
See \ref SurfaceMeshSimplificationLindstromTurkStrategy for details on the meaning of this factor.
*/
LindstromTurk_placement<TriangleMesh>(const FT& factor = FT(0.5));
/// @}
/// @}
/// \name Operations
/// \name Operations
/// @{
/*!
Returns the new position for the remaining vertex after collapsing the edge
(represented by its profile).
*/
template <typename Profile>
Returns the new position for the remaining vertex after collapsing the edge
(represented by its profile).
*/
template <typename Profile>
optional<typename Profile::Point>
operator()(const Profile& profile) const;
operator()(const Profile& profile) const;
/// @}

View File

@ -1,123 +1,119 @@
/*!
\ingroup PkgSurfaceMeshSimplificationConcepts
\cgalConcept
The concept `EdgeCollapseSimplificationVisitor` describes the requirements for the <I>visitor object</I> which is used to track the edge collapse simplification algorithm.
The concept `EdgeCollapseSimplificationVisitor` describes the requirements for the <I>visitor object</I> which is used to track the edge collapse simplification algorithm.
The several callbacks given as member functions in the visitor are called from certain places in the algorithm implementation.
The several callbacks given as member functions in the visitor are called from certain places in the algorithm implementation.
*/
class EdgeCollapseSimplificationVisitor {
public:
/// \name Types
/// \name Types
/// @{
/*!
The type of the surface mesh to simplify. Must be a model of the `MutableFaceGraph` and `HalfedgeListGraph` concepts.
*/
typedef unspecified_type TriangleMesh;
*/
typedef unspecified_type TriangleMesh;
/*!
A field type representing the collapse cost
*/
typedef unspecified_type FT;
A field type representing the collapse cost
*/
typedef unspecified_type FT;
/*!
The type of the edge profile cache. Must be a model of the `EdgeProfile` concept.
*/
typedef unspecified_type Profile;
The type of the edge profile cache. Must be a model of the `EdgeProfile` concept.
*/
typedef unspecified_type Profile;
/*!
The point type for the surface mesh vertex. Must be a model of `Point_3`.
*/
typename unspecified_type Point;
The point type for the surface mesh vertex. Must be a model of `Point_3`.
*/
typename unspecified_type Point;
/*!
An integer type representing the number of edges
*/
typedef unspecified_type size_type;
An integer type representing the number of edges
*/
typedef unspecified_type size_type;
/// @}
/// @}
/// \name Operations
/// \name Operations
/// @{
/*!
Called before the algorithm starts.
*/
void OnStarted(TriangleMesh& surface_mesh);
Called before the algorithm starts.
*/
void OnStarted(TriangleMesh& surface_mesh);
/*!
Called after the algorithm finishes.
*/
void OnFinished (TriangleMesh& surface_mesh);
Called after the algorithm finishes.
*/
void OnFinished(TriangleMesh& surface_mesh);
/*!
Called when the `StopPredicate` returned `true`
(but not if the algorithm terminates because the surface mesh could not be simplified any further).
Called when the `StopPredicate` returned `true`
(but not if the algorithm terminates because the surface mesh could not be simplified any further).
*/
void OnStopConditionReached(TriangleMesh& surface_mesh);
*/
void OnStopConditionReached(TriangleMesh& surface_mesh);
/*!
Called during the <I>collecting phase</I> (when a cost is assigned to the edges),
for each edge collected.
Called during the <I>collecting phase</I> (when a cost is assigned to the edges),
for each edge collected.
*/
void OnCollected(const Profile& profile, boost::optional<FT> cost);
*/
void OnCollected(const Profile& profile,
boost::optional<FT> cost);
/*!
Called during the <I>processing phase</I> (when edges are collapsed),
for each edge that is selected.
Called during the <I>processing phase</I> (when edges are collapsed),
for each edge that is selected.
This method is called before the algorithm checks
if the edge is collapsable.
This method is called before the algorithm checks
if the edge is collapsable.
`cost` indicates the current collapse cost for the edge.
If absent (meaning that it could not be computed)
the edge will not be collapsed.
`cost` indicates the current collapse cost for the edge.
If absent (meaning that it could not be computed)
the edge will not be collapsed.
`initial_count` and `current_count` refer to
the number of edges.
`initial_count` and `current_count` refer to
the number of edges.
*/
void OnSelected(const Profile& profile
, boost::optional<FT> cost
, size_type initial_count
, size_type current_count
);
*/
void OnSelected(const Profile& profile,
boost::optional<FT> cost,
size_type initial_count,
size_type current_count);
/*!
Called when an edge is about to be collapsed and replaced by a vertex
whose position is `*placement`.
Called when an edge is about to be collapsed and replaced by a vertex
whose position is `*placement`.
If `placement` is absent (meaning that it could not be computed)
the edge will not be collapsed.
If `placement` is absent (meaning that it could not be computed)
the edge will not be collapsed.
*/
void OnCollapsing(const Profile& profile
, boost::optional<Point> placement
);
*/
void OnCollapsing(const Profile& profile,
boost::optional<Point> placement);
/*!
Called when an edge has been collapsed and replaced by the vertex `vd`
*/
void OnCollapsed(Profile const&, Profile::const vertex_descriptor vd) {}
void OnCollapsed(const Profile&,
const Profile::vertex_descriptor vd) {}
/*!
Called for each selected edge which cannot be
collapsed because doing so would change the topological
type of the surface mesh (turn it into a non-manifold
for instance).
Called for each selected edge which cannot be
collapsed because doing so would change the topological
type of the surface mesh (turn it into a non-manifold
for instance).
*/
void OnNonCollapsable(const Profile& profile);
*/
void OnNonCollapsable(const Profile& profile);
/// @}
}; /* end EdgeCollapseSimplificationVisitor */

View File

@ -1,26 +1,24 @@
/*!
\ingroup PkgSurfaceMeshSimplificationConcepts
\cgalConcept
The concept `EdgeProfile` describes the requirements for a data structure that caches the local topology and geometry in the surroundings of a halfedge.
The concept `EdgeProfile` describes the requirements for a data structure that caches the local topology and geometry in the surroundings of a halfedge.
This profile is used by the stop, cost and placement policies.
This profile is used by the stop, cost and placement policies.
\cgalHasModel `CGAL::Surface_mesh_simplification::Edge_profile<TriangleMesh>`
*/
class EdgeProfile {
public:
/// \name Types
/// \name Types
/// @{
/*!
The type of the surface mesh to simplify. Must be a model of the `MutableFaceGraph` and `HalfedgeListGraph` concepts.
*/
typedef unspecified_type TriangleMesh;
*/
typedef unspecified_type TriangleMesh;
/*!
The type of a property map that maps vertices on points.
@ -28,119 +26,119 @@ The type of a property map that maps vertices on points.
typedef unspecified_type VertexPointMap;
/*!
A <span class="textsc">Bgl</span> vertex descriptor representing a vertex of the surface mesh.
*/
typename boost::graph_traits<TriangleMesh>::vertex_descriptor vertex_descriptor;
A <span class="textsc">Bgl</span> vertex descriptor representing a vertex of the surface mesh.
*/
typename boost::graph_traits<TriangleMesh>::vertex_descriptor vertex_descriptor;
/*!
A <span class="textsc">Bgl</span> halfedge descriptor representing a haledge of the surface mesh.
*/
typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
A <span class="textsc">Bgl</span> halfedge descriptor representing a haledge of the surface mesh.
*/
typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
/*!
The point type for the surface mesh vertex. Must be a model of `Point_3`.
*/
typename boost::property_traits<VertexPointMap>::value_type Point;
The point type for the surface mesh vertex. Must be a model of `Point_3`.
*/
typename boost::property_traits<VertexPointMap>::value_type Point;
/*!
The coordinate type of points.
*/
typename CGAL::Kernel_traits<Point>::Kernel::FT FT;
/// @}
/// @}
/// \name Access Functions
/// \name Access Functions
/// @{
/*!
One of vertices of the edge to be collapsed.
*/
vertex_descriptor v0() const;
One of vertices of the edge to be collapsed.
*/
vertex_descriptor v0() const;
/*!
The other vertex of the edge to be collapsed.
*/
vertex_descriptor v1() const;
The other vertex of the edge to be collapsed.
*/
vertex_descriptor v1() const;
/*!
One of the directed edges corresponding to the
halfedge being collapsed.
*/
halfedge_descriptor v0_v1() const;
halfedge being collapsed.
*/
halfedge_descriptor v0_v1() const;
/*!
The other directed edge corresponding to the
halfedge being collapsed.
*/
halfedge_descriptor v1_v0() const;
halfedge being collapsed.
*/
halfedge_descriptor v1_v0() const;
/*!
The point of vertex ` v0`.
*/
Point const& p0() const;
The point of vertex ` v0`.
*/
const Point& p0() const;
/*!
The point of vertex ` v1`.
*/
Point const& p1() const;
The point of vertex ` v1`.
*/
const Point& p1() const;
/*!
If ` v0v1` belongs to a finite face (is not a border edge)
the third vertex of that triangular face, a <I>null descriptor</I> otherwise.
*/
vertex_descriptor vL() const;
If ` v0v1` belongs to a finite face (is not a border edge)
the third vertex of that triangular face, a <I>null descriptor</I> otherwise.
*/
vertex_descriptor vL() const;
/*!
If ` v0v1` belongs to a finite face (is not a border edge)
the directed edge from ` v1` to ` vL`, a <I>null descriptor</I> otherwise.
*/
halfedge_descriptor v1_vL() const;
If ` v0v1` belongs to a finite face (is not a border edge)
the directed edge from ` v1` to ` vL`, a <I>null descriptor</I> otherwise.
*/
halfedge_descriptor v1_vL() const;
/*!
If ` v0v1` belongs to a finite face (is not a border edge)
the directed edge from ` vL` to ` v0`, a <I>null descriptor</I> otherwise.
*/
halfedge_descriptor vL_v0() const;
If ` v0v1` belongs to a finite face (is not a border edge)
the directed edge from ` vL` to ` v0`, a <I>null descriptor</I> otherwise.
*/
halfedge_descriptor vL_v0() const;
/*!
If ` v1v0` belongs to a finite face (is not a border edge)
the third vertex of that triangular face, a <I>null descriptor</I> otherwise.
*/
vertex_descriptor vR() const;
If ` v1v0` belongs to a finite face (is not a border edge)
the third vertex of that triangular face, a <I>null descriptor</I> otherwise.
*/
vertex_descriptor vR() const;
/*!
If ` v1v0` belongs to a finite face (is not a border edge)
the directed edge from ` v0` to ` vR`, a <I>null descriptor</I> otherwise.
*/
halfedge_descriptor v0_vR() const;
If ` v1v0` belongs to a finite face (is not a border edge)
the directed edge from ` v0` to ` vR`, a <I>null descriptor</I> otherwise.
*/
halfedge_descriptor v0_vR() const;
/*!
If ` v1v0` belongs to a finite face (is not a border edge)
the directed edge from ` vR` to ` v1`, a <I>null descriptor</I> otherwise.
*/
halfedge_descriptor vR_v1() const;
If ` v1v0` belongs to a finite face (is not a border edge)
the directed edge from ` vR` to ` v1`, a <I>null descriptor</I> otherwise.
*/
halfedge_descriptor vR_v1() const;
/*!
The unique sequence of the vertices
around ` v0v1` in topological order (<I>ccw</I> or <I>cw</I> depending
on the relative ordering of `v0` and `v1` in the profile).
The unique sequence of the vertices
around ` v0v1` in topological order (<I>ccw</I> or <I>cw</I> depending
on the relative ordering of `v0` and `v1` in the profile).
The sequence may have duplicates, but when this happens the edge is not collapsible.
*/
std::vector<vertex_descriptor> link() const;
*/
std::vector<vertex_descriptor> link() const;
/*!
The unique collection of the border directed edges incident upon ` v0` and ` v1`.
*/
std::vector<halfedge_descriptor> border_edges() const;
The unique collection of the border directed edges incident upon ` v0` and ` v1`.
*/
std::vector<halfedge_descriptor> border_edges() const;
/*!
Indicates if `v0v1` belongs to a finite face of the surface mesh (i.e, `v0v1` is not a border edge).
*/
bool left_face_exists() const;
Indicates if `v0v1` belongs to a finite face of the surface mesh (i.e, `v0v1` is not a border edge).
*/
bool left_face_exists() const;
/*!
Indicates if `v0v1` belongs to a finite face of the surface mesh (i.e, `v1v0` is not a border edge).
*/
bool right_face_exists() const;
Indicates if `v0v1` belongs to a finite face of the surface mesh (i.e, `v1v0` is not a border edge).
*/
bool right_face_exists() const;
/*!
Returns the surface mesh the edge belongs to.
@ -150,7 +148,7 @@ const TriangleMesh& surface_mesh() const;
/*!
Returns the vertex point property map.
*/
VertexPointMap vertex_point_map() const;
VertexPointMap vertex_point_map() const;
/// @}

View File

@ -1,4 +1,3 @@
/*!
\ingroup PkgSurfaceMeshSimplificationConcepts
\cgalConcept
@ -18,11 +17,10 @@ or can be intentionally returned to prevent the edge from being collapsed.
\cgalHasModel `CGAL::Surface_mesh_simplification::LindstromTurk_cost<TriangleMesh>`
*/
class GetCost {
class GetCost
{
public:
/// \name Operations
/// @{
@ -32,8 +30,8 @@ using the calculated placement.
\tparam Profile must be a model of `EdgeProfile`.
*/
template <class Profile>
boost::optional<typename Profile::FT> operator()(const Profile& edge_profile
, boost::optional<typename Profile::Point> const& placement) const;
boost::optional<typename Profile::FT> operator()(const Profile& edge_profile,
const boost::optional<typename Profile::Point>& placement) const;
/// @}

View File

@ -1,67 +1,63 @@
/*!
\ingroup PkgSurfaceMeshSimplificationConcepts
\cgalConcept
The concept `StopPredicate` describes the requirements for the predicate which indicates if the simplification process must finish.
The concept `StopPredicate` describes the requirements for the predicate which indicates if the simplification process must finish.
\cgalHasModel `CGAL::Surface_mesh_simplification::Count_stop_predicate<TriangleMesh>`
\cgalHasModel `CGAL::Surface_mesh_simplification::Count_ratio_stop_predicate<TriangleMesh>`
\cgalHasModel `CGAL::Surface_mesh_simplification::Edge_length_stop_predicate<FT>`
*/
class StopPredicate {
public:
/// \name Types
/// \name Types
/// @{
/*!
The type of the surface mesh to simplify. Must be a model of the `MutableFaceGraph` and `HalfedgeListGraph` concepts.
*/
typedef unspecified_type TriangleMesh;
*/
typedef unspecified_type TriangleMesh;
/*!
A field type representing the collapse cost
*/
typedef unspecified_type FT;
A field type representing the collapse cost
*/
typedef unspecified_type FT;
/*!
An integer type representing the number of edges
*/
typedef unspecified_type size_type;
An integer type representing the number of edges
*/
typedef unspecified_type size_type;
/*!
The type of the edge profile cache. Must be a model of the `EdgeProfile` concept.
*/
typedef unspecified_type Profile;
The type of the edge profile cache. Must be a model of the `EdgeProfile` concept.
*/
typedef unspecified_type Profile;
/// @}
/// @}
/// \name Operations
/// \name Operations
/// @{
/*!
This predicate is called each time an 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.
`current_cost` is the cost of the selected edge.
`current_cost` is the cost of the selected edge.
`initial_count` and `current_count` are the number of initial and current edges.
`initial_count` and `current_count` are the number of initial and current edges.
If the return value is `true` the simplification terminates before processing the edge,
otherwise it continues normally.
If the return value is `true` the simplification terminates before processing the edge,
otherwise it continues normally.
*/
bool operator()(FT const& current_cost
, const Profile& profile
, size_type initial_count
, size_type current_count
) const;
*/
bool operator()(const FT& current_cost,
const Profile& profile,
size_type initial_count,
size_type current_count) const;
/// @}
}; /* end StopPredicate */

View File

@ -36,11 +36,9 @@ struct Constrained_edge_map
: mConstraints(aConstraints)
{}
reference operator[](key_type const& e) const { return is_constrained(e); }
reference operator[](const key_type& e) const { return is_constrained(e); }
bool is_constrained(key_type const& e) const {
return mConstraints.is_defined(e);
}
bool is_constrained(const key_type& e) const { return mConstraints.is_defined(e); }
private:
const CGAL::Unique_hash_map<key_type,bool>& mConstraints;

View File

@ -13,18 +13,17 @@
// Stop-condition policy
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_ratio_stop_predicate.h>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point_3;
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point_3;
typedef CGAL::Surface_mesh<Point_3> Surface_mesh;
typedef CGAL::Surface_mesh<Point_3> Surface_mesh;
typedef boost::graph_traits<Surface_mesh>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<Surface_mesh>::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits<Surface_mesh>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<Surface_mesh>::vertex_descriptor vertex_descriptor;
namespace SMS = CGAL::Surface_mesh_simplification;
typedef SMS::Edge_profile<Surface_mesh> Profile;
typedef SMS::Edge_profile<Surface_mesh> Profile;
// The following is a Visitor that keeps track of the simplification process.
// In this example the progress is printed real-time and a few statistics are
@ -32,86 +31,80 @@ typedef SMS::Edge_profile<Surface_mesh> Profile;
//
struct Stats
{
Stats()
: collected(0)
, processed(0)
, collapsed(0)
, non_collapsable(0)
, cost_uncomputable(0)
, placement_uncomputable(0)
{}
Stats()
: collected(0), processed(0), collapsed(0),
non_collapsable(0), cost_uncomputable(0), placement_uncomputable(0)
{}
std::size_t collected;
std::size_t processed;
std::size_t collapsed;
std::size_t non_collapsable;
std::size_t cost_uncomputable;
std::size_t placement_uncomputable;
std::size_t placement_uncomputable;
};
struct My_visitor : SMS::Edge_collapse_visitor_base<Surface_mesh>
{
My_visitor(Stats* s) : stats(s){}
My_visitor(Stats* s) : stats(s){}
// Called during the collecting phase for each edge collected.
void OnCollected(Profile const&, boost::optional<double> const&)
void OnCollected(const Profile&, const boost::optional<double>&)
{
++ stats->collected;
++(stats->collected);
std::cerr << "\rEdges collected: " << stats->collected << std::flush;
}
}
// Called during the processing phase for each edge selected.
// If cost is absent the edge won't be collapsed.
void OnSelected(const Profile&
,boost::optional<double> cost
,std::size_t initial
,std::size_t current
)
void OnSelected(const Profile&,
boost::optional<double> cost,
std::size_t initial,
std::size_t current)
{
++ stats->processed;
++(stats->processed);
if(!cost)
++ stats->cost_uncomputable;
++(stats->cost_uncomputable);
if(current == initial)
std::cerr << "\n" << std::flush;
std::cerr << "\r" << current << std::flush;
}
}
// Called during the processing phase for each edge being collapsed.
// If placement is absent the edge is left uncollapsed.
void OnCollapsing(const Profile&
,boost::optional<Point> placement
)
void OnCollapsing(const Profile&,
boost::optional<Point> placement)
{
if(!placement)
++ stats->placement_uncomputable;
}
++(stats->placement_uncomputable);
}
// Called for each edge which failed the so called link-condition,
// that is, which cannot be collapsed because doing so would
// turn the surface mesh into a non-manifold.
void OnNonCollapsable(Profile const&)
void OnNonCollapsable(const Profile&)
{
++ stats->non_collapsable;
}
++(stats->non_collapsable);
}
// Called after each edge has been collapsed
void OnCollapsed(Profile const&, vertex_descriptor)
void OnCollapsed(const Profile&, vertex_descriptor)
{
++ stats->collapsed;
}
++(stats->collapsed);
}
Stats* stats;
};
int main(int argc, char** argv)
int main(int argc, char** argv)
{
Surface_mesh surface_mesh;
Surface_mesh surface_mesh;
std::ifstream is(argv[1]);
is >> surface_mesh;
if(!CGAL::is_triangle_mesh(surface_mesh)){
if(!CGAL::is_triangle_mesh(surface_mesh))
{
std::cerr << "Input geometry is not triangulated." << std::endl;
return EXIT_FAILURE;
}
@ -119,9 +112,9 @@ int main(int argc, char** argv)
// In this example, the simplification stops when the number of undirected edges
// drops below 10% of the initial count
SMS::Count_ratio_stop_predicate<Surface_mesh> stop(0.1);
Stats stats;
My_visitor vis(&stats);
// The index maps are not explicitelty passed as in the previous
@ -129,27 +122,23 @@ int main(int argc, char** argv)
// On the other hand, we pass here explicit cost and placement
// function which differ from the default policies, ommited in
// the previous example.
int r = SMS::edge_collapse
(surface_mesh
,stop
,CGAL::parameters::visitor(vis)
);
int r = SMS::edge_collapse(surface_mesh, stop, CGAL::parameters::visitor(vis));
std::cout << "\nEdges collected: " << stats.collected
<< "\nEdges proccessed: " << stats.processed
<< "\nEdges collapsed: " << stats.collapsed
<< std::endl
<< "\nEdges not collapsed due to topological constraints: " << stats.non_collapsable
<< "\nEdge not collapsed due to cost computation constraints: " << stats.cost_uncomputable
<< "\nEdge not collapsed due to placement computation constraints: " << stats.placement_uncomputable
<< std::endl;
std::cout << "\nFinished...\n" << r << " edges removed.\n"
<< "\nEdge not collapsed due to cost computation constraints: " << stats.cost_uncomputable
<< "\nEdge not collapsed due to placement computation constraints: " << stats.placement_uncomputable
<< std::endl;
std::cout << "\nFinished...\n" << r << " edges removed.\n"
<< surface_mesh.number_of_edges() << " final edges.\n";
std::ofstream os(argc > 2 ? argv[2] : "out.off");
os.precision(17);
os << surface_mesh;
return EXIT_SUCCESS;
return EXIT_SUCCESS;
}

View File

@ -163,7 +163,7 @@ private:
template<class R>
inline
MatrixC33<R> direct_product(Vector_3<R> const& u, Vector_3<R> const& v)
MatrixC33<R> direct_product(const Vector_3<R>& u, const Vector_3<R>& v)
{
return MatrixC33<R>(v * u.x(),
v * u.y(),
@ -239,7 +239,7 @@ boost::optional< MatrixC33<R> > inverse_matrix(const MatrixC33<R>& m)
return rInverse;
}
} //namespace CGAL
} // namespace CGAL
#endif // CGAL_CARTESIAN_MATRIXC33_H //
// EOF //

View File

@ -28,6 +28,6 @@ class Null_matrix {};
static const Null_matrix NULL_MATRIX = Null_matrix();
} //namespace CGAL
} // namespace CGAL
#endif // CGAL_NULL_MATRIX_H

View File

@ -18,11 +18,10 @@
// Author(s) : Fernando Cacciola <fernando.cacciola@geometryfactory.com>
//
#ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_DETAIL_EDGE_COLLAPSE_H
#define CGAL_SURFACE_MESH_SIMPLIFICATION_DETAIL_EDGE_COLLAPSE_H 1
#define CGAL_SURFACE_MESH_SIMPLIFICATION_DETAIL_EDGE_COLLAPSE_H
#include <CGAL/license/Surface_mesh_simplification.h>
#include <CGAL/Surface_mesh_simplification/Detail/Common.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Edge_profile.h>
#include <CGAL/boost/graph/Euler_operations.h>
@ -122,7 +121,7 @@ public:
edge_id() : mAlgorithm(0) {}
edge_id(Self const* aAlgorithm) : mAlgorithm(aAlgorithm) {}
size_type operator[] (const halfedge_descriptor e) const { return mAlgorithm->get_edge_id(e); }
size_type operator[](const halfedge_descriptor e) const { return mAlgorithm->get_edge_id(e); }
Self const* mAlgorithm;
};
@ -182,15 +181,15 @@ private:
}
size_type get_halfedge_id(const halfedge_descriptor aEdge) const { return Edge_index_map[aEdge]; }
size_type get_edge_id (const halfedge_descriptor aEdge) const { return get_halfedge_id(aEdge) / 2; }
size_type get_edge_id(const halfedge_descriptor aEdge) const { return get_halfedge_id(aEdge) / 2; }
bool is_primary_edge (const halfedge_descriptor aEdge) const { return (get_halfedge_id(aEdge) % 2) == 0; }
halfedge_descriptor primary_edge (const halfedge_descriptor aEdge) {
bool is_primary_edge(const halfedge_descriptor aEdge) const { return (get_halfedge_id(aEdge) % 2) == 0; }
halfedge_descriptor primary_edge(const halfedge_descriptor aEdge) {
return is_primary_edge(aEdge) ? aEdge : opposite(aEdge, mSurface);
}
bool is_border(const vertex_descriptor aV) const;
bool is_border (const halfedge_descriptor aEdge) const {
bool is_border(const halfedge_descriptor aEdge) const {
return face(aEdge, mSurface) == boost::graph_traits<TM>::null_face();
}
@ -202,7 +201,7 @@ private:
bool is_border_or_constrained(const vertex_descriptor aV) const;
bool is_border_or_constrained(const halfedge_descriptor aEdge) const { return is_border(aEdge) || is_constrained(aEdge); }
bool is_edge_a_border (const halfedge_descriptor aEdge) const
bool is_edge_a_border(const halfedge_descriptor aEdge) const
{
return is_border(aEdge) || is_border(opposite(aEdge, mSurface));
}
@ -243,13 +242,14 @@ private:
return boost::str(boost::format("[V%1%:%2%]") % get(Vertex_index_map,v) % xyz_to_string(p));
}
std::string edge_to_string (const halfedge_descriptor aEdge) const
std::string edge_to_string(const halfedge_descriptor aEdge) const
{
vertex_descriptor p,q; boost::tie(p,q) = get_vertices(aEdge);
vertex_descriptor p, q;
boost::tie(p,q) = get_vertices(aEdge);
return boost::str(boost::format("{E%1% %2%->%3%}%4%") % get(Edge_index_map, aEdge) % vertex_to_string(p) % vertex_to_string(q) % (is_border(aEdge) ? " (BORDER)" : (is_border(opposite(aEdge, mSurface)) ? " (~BORDER)": "")));
}
Cost_type get_cost (const Profile& aProfile) const {
Cost_type get_cost(const Profile& aProfile) const {
return Get_cost(aProfile, get_placement(aProfile));
}
@ -361,7 +361,7 @@ private:
FT mcMaxDihedralAngleCos2;
CGAL_SMS_DEBUG_CODE (unsigned mStep;)
CGAL_SMS_DEBUG_CODE(unsigned mStep;)
};
template<class M, class SP, class VIM, class VPM,class EIM, class ECTM, class CF, class PF, class V>
@ -400,9 +400,9 @@ EdgeCollapse(TM& aSurface,
}
}
CGAL_SMS_TRACE(0,"EdgeCollapse of TM with " << (num_edges(aSurface)/2) << " edges");
CGAL_SMS_TRACE(0, "EdgeCollapse of TM with " << (num_edges(aSurface)/2) << " edges");
CGAL_SMS_DEBUG_CODE (mStep = 0;)
CGAL_SMS_DEBUG_CODE(mStep = 0;)
#ifdef CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE
for(vertex_descriptor vd : vertices(mSurface))
@ -428,7 +428,7 @@ run()
// Then proceed to collapse each edge in turn
loop();
CGAL_SMS_TRACE(0,"Finished: " << (mInitialEdgeCount - mCurrentEdgeCount) << " edges removed.");
CGAL_SMS_TRACE(0, "Finished: " << (mInitialEdgeCount - mCurrentEdgeCount) << " edges removed.");
int r = int(mInitialEdgeCount - mCurrentEdgeCount);
@ -442,7 +442,7 @@ void
EdgeCollapse<M,SP,VIM,VPM,EIM,ECTM,CF,PF,V>::
collect()
{
CGAL_SMS_TRACE(0,"collecting edges...");
CGAL_SMS_TRACE(0, "collecting edges...");
// loop over all the _undirected_ edges in the surface putting them in the PQ
@ -456,7 +456,7 @@ collect()
mEdgeDataArray.reset(new Edge_data[lSize]);
mPQ.reset(new PQ (lSize, Compare_cost(this), edge_id(this)));
mPQ.reset(new PQ(lSize, Compare_cost(this), edge_id(this)));
std::size_t id = 0;
CGAL_SURF_SIMPL_TEST_assertion_code(size_type lInserted = 0);
@ -485,18 +485,18 @@ collect()
Visitor.OnCollected(lProfile, lData.cost());
CGAL_SURF_SIMPL_TEST_assertion_code (++ lInserted);
CGAL_SURF_SIMPL_TEST_assertion_code(++lInserted);
}
else
{
zero_length_edges.insert(primary_edge(lEdge));
CGAL_SURF_SIMPL_TEST_assertion_code (++ lNotInserted);
CGAL_SURF_SIMPL_TEST_assertion_code(++lNotInserted);
}
CGAL_SMS_TRACE(2,edge_to_string(lEdge));
}
CGAL_SURF_SIMPL_TEST_assertion (lInserted + lNotInserted == mInitialEdgeCount);
CGAL_SURF_SIMPL_TEST_assertion(lInserted + lNotInserted == mInitialEdgeCount);
for(halfedge_descriptor hd : zero_length_edges)
{
@ -545,11 +545,11 @@ collect()
//the placement is trivial, it's always the point itself
Placement_type lPlacement = lProfile.p0();
vertex_descriptor rResult = halfedge_collapse_bk_compatibility(lProfile.v0_v1(), Edge_is_constrained_map);
put(Vertex_point_map,rResult,*lPlacement);
Visitor.OnCollapsed(lProfile,rResult);
put(Vertex_point_map, rResult, *lPlacement);
Visitor.OnCollapsed(lProfile, rResult);
}
CGAL_SMS_TRACE(0,"Initial edge count: " << mInitialEdgeCount);
CGAL_SMS_TRACE(0, "Initial edge count: " << mInitialEdgeCount);
}
template<class M,class SP, class VIM, class VPM,class EIM,class ECTM, class CF,class PF,class V>
@ -557,10 +557,10 @@ void
EdgeCollapse<M,SP,VIM,VPM,EIM,ECTM,CF,PF,V>::
loop()
{
CGAL_SMS_TRACE(0,"Collapsing edges...");
CGAL_SMS_TRACE(0, "Collapsing edges...");
CGAL_SURF_SIMPL_TEST_assertion_code (size_type lloop_watchdog = 0);
CGAL_SURF_SIMPL_TEST_assertion_code (size_type lNonCollapsableCount = 0);
CGAL_SURF_SIMPL_TEST_assertion_code(size_type lloop_watchdog = 0);
CGAL_SURF_SIMPL_TEST_assertion_code(size_type lNonCollapsableCount = 0);
// Pops and processes each edge from the PQ
@ -571,7 +571,7 @@ loop()
while((lEdge = pop_from_PQ()))
{
CGAL_SURF_SIMPL_TEST_assertion(lloop_watchdog ++ < mInitialEdgeCount);
CGAL_SURF_SIMPL_TEST_assertion(lloop_watchdog++ < mInitialEdgeCount);
CGAL_SMS_TRACE(1, "Popped " << edge_to_string(*lEdge));
CGAL_assertion(!is_constrained(*lEdge));
@ -947,7 +947,6 @@ are_shared_triangles_valid(const Point& p0, const Point& p1, const Point& p2, co
return rR;
}
// Returns the directed halfedge connecting v0 to v1, if exists.
template<class M, class SP, class VIM, class VPM, class EIM, class ECTM, class CF, class PF, class V>
typename EdgeCollapse<M,SP,VIM,VPM,EIM,ECTM,CF,PF,V>::halfedge_descriptor
@ -1043,10 +1042,10 @@ is_collapse_geometrically_valid(const Profile& aProfile, Placement_type k0)
if(!are_shared_triangles_valid(*k0, get_point(k1), get_point(k2), get_point(k3)))
{
CGAL_SMS_TRACE(3, " Triangles VX-V" << get(Vertex_index_map, k1)
<< "-V" << get(Vertex_index_map, k2)
<< " and VX-V" << get(Vertex_index_map, k3)
<< " are not geometrically valid. Collapse rejected");
CGAL_SMS_TRACE(3, " Triangles VX-V" << get(Vertex_index_map, k1)
<< "-V" << get(Vertex_index_map, k2)
<< " and VX-V" << get(Vertex_index_map, k3)
<< " are not geometrically valid. Collapse rejected");
rR = false;
}
}
@ -1122,7 +1121,7 @@ collapse(const Profile& aProfile,
if(aProfile.left_face_exists())
{
halfedge_descriptor lV0VL = primary_edge(aProfile.vL_v0());
if(is_constrained(lV0VL)) //make sure a constrained edge will not disappear
if(is_constrained(lV0VL)) // make sure a constrained edge will not disappear
lV0VL=primary_edge(aProfile.v1_vL());
CGAL_SMS_TRACE(3, "V0VL E" << get(Edge_index_map,lV0VL)
@ -1197,7 +1196,7 @@ collapse(const Profile& aProfile,
update_neighbors(rResult);
CGAL_SMS_DEBUG_CODE (++mStep;)
CGAL_SMS_DEBUG_CODE(++mStep;)
}
template<class M, class SP, class VIM, class VPM, class EIM, class ECTM, class CF, class PF, class V>

View File

@ -75,9 +75,9 @@ public:
Vector n1 = Traits().construct_cross_product_vector_3_object()(eqp,eqr);
Vector n2 = Traits().construct_cross_product_vector_3_object()(eq2p,eq2r);
if(! is_positive(Traits().compute_scalar_product_3_object()(n1, n2))){
if(!is_positive(Traits().compute_scalar_product_3_object()(n1, n2)))
return boost::optional<typename Profile::Point>();
}
++it;
}
}
@ -86,10 +86,10 @@ public:
}
private:
Placement mPlacement;
Placement mPlacement;
};
} // namespace Surface_mesh_simplification
} //namespace CGAL
} // namespace CGAL
#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_NORMAL_CHANGE_PLACEMENT_H

View File

@ -36,7 +36,7 @@ public:
EdgeIsConstrainedMap Edge_is_constrained_map;
Constrained_placement(EdgeIsConstrainedMap map=EdgeIsConstrainedMap(),
BasePlacement base=BasePlacement())
BasePlacement base = BasePlacement())
: BasePlacement(base),
Edge_is_constrained_map(map)
{}
@ -44,24 +44,19 @@ public:
template <typename Profile>
optional<typename Profile::Point> operator()(const Profile& aProfile) const
{
typedef typename Profile::TM TM;
typedef typename CGAL::Halfedge_around_target_iterator<TM> in_edge_iterator;
typedef typename Profile::TM TM;
typedef typename boost::graph_traits<TM>::halfedge_descriptor halfedge_descriptor;
in_edge_iterator eb, ee;
for(boost::tie(eb,ee) = halfedges_around_target(aProfile.v0(),aProfile.surface_mesh());
eb != ee; ++ eb)
for(halfedge_descriptor h : halfedges_around_target(aProfile.v0(), aProfile.surface_mesh()))
{
if(get(Edge_is_constrained_map, edge(*eb,aProfile.surface_mesh())))
return get(aProfile.vertex_point_map(),
aProfile.v0());
if(get(Edge_is_constrained_map, edge(h, aProfile.surface_mesh())))
return get(aProfile.vertex_point_map(), aProfile.v0());
}
for(boost::tie(eb,ee) = halfedges_around_target(aProfile.v1(),aProfile.surface_mesh());
eb != ee; ++ eb)
for(halfedge_descriptor h : halfedges_around_target(aProfile.v1(), aProfile.surface_mesh()))
{
if(get(Edge_is_constrained_map, edge(*eb,aProfile.surface_mesh())))
return get(aProfile.vertex_point_map(),
aProfile.v1());
if(get(Edge_is_constrained_map, edge(h, aProfile.surface_mesh())))
return get(aProfile.vertex_point_map(), aProfile.v1());
}
return static_cast<const BasePlacement*>(this)->operator()(aProfile);
@ -69,6 +64,6 @@ public:
};
} // namespace Surface_mesh_simplification
} //namespace CGAL
} // namespace CGAL
#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_CONSTRAINED_PLACEMENT_H

View File

@ -18,7 +18,7 @@
// Author(s) : Fernando Cacciola <fernando.cacciola@geometryfactory.com>
//
#ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_COUNT_RATIO_STOP_PREDICATE_H
#define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_COUNT_RATIO_STOP_PREDICATE_H 1
#define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_COUNT_RATIO_STOP_PREDICATE_H
#include <CGAL/license/Surface_mesh_simplification.h>
@ -63,6 +63,6 @@ private:
};
} // namespace Surface_mesh_simplification
} //namespace CGAL
} // namespace CGAL
#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_COUNT_RATIO_STOP_PREDICATE_H

View File

@ -60,6 +60,6 @@ private:
};
} // namespace Surface_mesh_simplification
} //namespace CGAL
} // namespace CGAL
#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_COUNT_STOP_PREDICATE_H

View File

@ -18,7 +18,7 @@
// Author(s) : Fernando Cacciola <fernando_cacciola@ciudad.com.ar>
//
#ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_DETAIL_LINDSTROM_TURK_CORE_H
#define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_DETAIL_LINDSTROM_TURK_CORE_H 1
#define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_DETAIL_LINDSTROM_TURK_CORE_H
#include <CGAL/license/Surface_mesh_simplification.h>
@ -28,6 +28,7 @@
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Edge_profile.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/LindstromTurk_params.h>
#include <limits>
#include <vector>
// This should be in
@ -77,7 +78,7 @@ public:
typedef typename Profile::halfedge_descriptor_vector::const_iterator const_border_edge_iterator;
public:
LindstromTurkCore(Params const& aParams, const Profile& aProfile);
LindstromTurkCore(const Params& aParams, const Profile& aProfile);
Optional_point compute_placement();
Optional_FT compute_cost(const Optional_point& p);
@ -111,12 +112,13 @@ private :
void add_boundary_preservation_constraints(const Boundary_data_vector& aBdry);
void add_volume_preservation_constraints(const Triangle_data_vector& aTriangles);
void add_boundary_and_volume_optimization_constraints(const Boundary_data_vector& aBdry, const Triangle_data_vector& aTriangles);
void add_boundary_and_volume_optimization_constraints(const Boundary_data_vector& aBdry,
const Triangle_data_vector& aTriangles);
void add_shape_optimization_constraints(const vertex_descriptor_vector& aLink);
FT compute_boundary_cost(const Vector& v, const Boundary_data_vector& aBdry);
FT compute_volume_cost(const Vector& v, const Triangle_data_vector& aTriangles);
FT compute_shape_cost(Point const& p, const vertex_descriptor_vector& aLink);
FT compute_shape_cost(const Point& p, const vertex_descriptor_vector& aLink);
Point get_point(const vertex_descriptor v) const
{
@ -156,12 +158,12 @@ private :
static bool is_finite(const Matrix& m) { return is_finite(m.r0()) && is_finite(m.r1()) && is_finite(m.r2()); }
template<class T>
static optional<T> filter_infinity (T const& n) { return is_finite(n) ? optional<T>(n) : optional<T>(); }
static optional<T> filter_infinity(const T& n) { return is_finite(n) ? optional<T>(n) : optional<T>(); }
TM& surface() const { return mProfile.surface(); }
private:
Params const& mParams;
const Params& mParams;
const Profile& mProfile;
void add_constraint_if_alpha_compatible(const Vector& Ai, const FT& bi);
@ -183,7 +185,7 @@ private:
template<class TM, class K>
LindstromTurkCore<TM,K>::
LindstromTurkCore(Params const& aParams, const Profile& aProfile)
LindstromTurkCore(const Params& aParams, const Profile& aProfile)
:
mParams(aParams),
mProfile(aProfile),
@ -209,13 +211,12 @@ LindstromTurkCore<TM,K>::
extract_boundary_data()
{
mBdry_data.reserve(mProfile.border_edges().size());
for(const_border_edge_iterator it = mProfile.border_edges().begin(), eit = mProfile.border_edges().end(); it != eit; ++ it)
for(halfedge_descriptor border_edge : mProfile.border_edges())
{
halfedge_descriptor border_edge = *it;
halfedge_descriptor face_edge = opposite(border_edge,surface());
halfedge_descriptor face_edge = opposite(border_edge, surface());
vertex_descriptor sv = source(face_edge,surface());
vertex_descriptor tv = target(face_edge,surface());
vertex_descriptor sv = source(face_edge, surface());
vertex_descriptor tv = target(face_edge, surface());
const Point& sp = get_point(sv);
const Point& tp = get_point(tv);
@ -236,10 +237,9 @@ LindstromTurkCore<TM,K>::
extract_triangle_data()
{
mTriangle_data.reserve(mProfile.triangles().size());
for(const_triangle_iterator it = mProfile.triangles().begin(), eit = mProfile.triangles().end(); it != eit; ++ it)
{
Triangle const& tri = *it;
for(const Triangle& tri : mProfile.triangles())
{
const Point& p0 = get_point(tri.v0);
const Point& p1 = get_point(tri.v1);
const Point& p2 = get_point(tri.v2);
@ -248,7 +248,7 @@ extract_triangle_data()
Vector v02 = p2 - p0;
Vector lNormalV = cross_product(v01,v02);
FT lNormalL = point_cross_product(p0,p1) * (p2-ORIGIN);
FT lNormalL = point_cross_product(p0,p1) * (p2 - ORIGIN);
CGAL_SMS_LT_TRACE(1, " Extracting triangle v" << tri.v0 << "->v" << tri.v1 << "->v" << tri.v2
<< " N:" << xyz_to_string(lNormalV) << " L:" << n_to_string(lNormalL));
@ -347,11 +347,11 @@ compute_cost(const Optional_point& aP)
CGAL_SMS_LT_TRACE(0,"Computing LT cost for E" << mProfile.v0_v1());
Vector lV = (*aP) - ORIGIN;
FT lSquaredLength = squared_distance(mProfile.p0(),mProfile.p1());
FT lSquaredLength = squared_distance(mProfile.p0(), mProfile.p1());
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 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
@ -384,7 +384,7 @@ add_boundary_preservation_constraints(const Boundary_data_vector& aBdry)
e1y = FT(0),
e1z = FT(0);
for(typename Boundary_data_vector::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;
@ -447,12 +447,9 @@ add_boundary_and_volume_optimization_constraints(const Boundary_data_vector& aBd
Vector c = NULL_VECTOR;
// Volume optimization
for(typename Triangle_data_vector::const_iterator it = aTriangles.begin(), eit = aTriangles.end(); it != eit; ++it)
for(const Triangle_data& lTri : aTriangles)
{
Triangle_data const& lTri = *it;
H += direct_product(lTri.NormalV, lTri.NormalV);
c = c - (lTri.NormalL * lTri.NormalV);
}
@ -464,10 +461,10 @@ add_boundary_and_volume_optimization_constraints(const Boundary_data_vector& aBd
Matrix Hb = NULL_MATRIX;
Vector cb = NULL_VECTOR;
for(typename Boundary_data_vector::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);
Vector c = cross_product(it->v, it->n);
Hb += H;
cb = cb + c;
@ -484,8 +481,8 @@ add_boundary_and_volume_optimization_constraints(const Boundary_data_vector& aBd
H += lScaledBoundaryWeight * Hb;
c = c + (lScaledBoundaryWeight * cb);
CGAL_SMS_LT_TRACE(2," H:" << matrix_to_string(H) << "\n c:" << xyz_to_string(c));
CGAL_SMS_LT_TRACE(2," VolW:" << mParams.VolumeWeight << " BdryW:" << mParams.BoundaryWeight << " ScaledBdryW:" << lScaledBoundaryWeight);
CGAL_SMS_LT_TRACE(2, " H:" << matrix_to_string(H) << "\n c:" << xyz_to_string(c));
CGAL_SMS_LT_TRACE(2, " VolW:" << mParams.VolumeWeight << " BdryW:" << mParams.BoundaryWeight << " ScaledBdryW:" << lScaledBoundaryWeight);
}
add_constraint_from_gradient(H,c);
@ -498,14 +495,13 @@ add_shape_optimization_constraints(const vertex_descriptor_vector& aLink)
{
FT s(double(aLink.size()));
Matrix H (s, 0.0, 0.0,
0.0, s, 0.0,
0.0, 0.0, s);
Matrix H(s, 0.0, 0.0,
0.0, s, 0.0,
0.0, 0.0, s);
Vector c = NULL_VECTOR;
for(typename vertex_descriptor_vector::const_iterator it = aLink.begin(), eit = aLink.end(); it != eit; ++it)
c = c + (ORIGIN - get_point(*it));
for(const vertex_descriptor v : aLink)
c = c + (ORIGIN - get_point(v));
CGAL_SMS_LT_TRACE(1," Adding shape optimization constraint. Shape vector: " << xyz_to_string(c));
@ -519,10 +515,10 @@ compute_boundary_cost(const Vector& v,
const Boundary_data_vector& aBdry)
{
FT rCost(0);
for(typename Boundary_data_vector::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);
Vector c = cross_product(it->v, u);
rCost += c*c;
}
@ -537,11 +533,9 @@ compute_volume_cost(const Vector& v,
{
FT rCost(0);
for(typename Triangle_data_vector::const_iterator it = aTriangles.begin(), eit = aTriangles.end(); it != eit; ++it)
for(const Triangle_data& lTri : aTriangles)
{
Triangle_data const& lTri = *it;
FT lF = lTri.NormalV * v - lTri.NormalL;
rCost += (lF * lF);
}
@ -555,9 +549,8 @@ compute_shape_cost(const Point& p,
const vertex_descriptor_vector& aLink)
{
FT rCost(0);
for(typename vertex_descriptor_vector::const_iterator it = aLink.begin(), eit = aLink.end(); it != eit; ++it)
rCost += squared_distance(p,get_point(*it));
for(const vertex_descriptor v : aLink)
rCost += squared_distance(p, get_point(v));
return rCost;
}
@ -582,7 +575,7 @@ add_constraint_if_alpha_compatible(const Vector& Ai,
{
Vector Ain = Ai / l;
FT bin = bi / l;
CGAL_SMS_LT_TRACE(3," Ain: " << xyz_to_string(Ain) << " bin:" << n_to_string(bin));
CGAL_SMS_LT_TRACE(3, " Ain: " << xyz_to_string(Ain) << " bin:" << n_to_string(bin));
bool lAddIt = true;
@ -593,7 +586,8 @@ add_constraint_if_alpha_compatible(const Vector& Ai,
FT sd01 = d01 * d01;
FT max = sla0 * slai * mSquared_cos_alpha;
CGAL_SMS_LT_TRACE(3," Second constraint. d01: " << n_to_string(d01) << " sla0:" << n_to_string(sla0) << " sd01:" << n_to_string(sd01) << " max:" << n_to_string(max));
CGAL_SMS_LT_TRACE(3, " Second constraint. d01: " << n_to_string(d01) << " sla0:" << n_to_string(sla0)
<< " sd01:" << n_to_string(sd01) << " max:" << n_to_string(max));
if(sd01 > max)
lAddIt = false;
@ -603,13 +597,13 @@ add_constraint_if_alpha_compatible(const Vector& Ai,
Vector N = cross_product(mConstraints_A.r0(),mConstraints_A.r1());
FT dc012 = N * Ai;
FT slc01 = N * N;
FT sdc012 = dc012 * dc012;
FT min = slc01 * slai * mSquared_sin_alpha;
CGAL_SMS_LT_TRACE(3, " Third constraint. N: " << xyz_to_string(N) << " dc012:" << n_to_string(dc012) << " slc01:" << n_to_string(slc01)
CGAL_SMS_LT_TRACE(3, " Third constraint. N: " << xyz_to_string(N)
<< " dc012:" << n_to_string(dc012) << " slc01:" << n_to_string(slc01)
<< " sdc012:" << n_to_string(sdc012) << " min:" << n_to_string(min));
if(sdc012 <= min)
@ -634,28 +628,28 @@ add_constraint_if_alpha_compatible(const Vector& Ai,
break;
}
CGAL_SMS_LT_TRACE(3," Accepting # " << mConstraints_n << " A:" << matrix_to_string(mConstraints_A) << " b:" << xyz_to_string(mConstraints_b));
CGAL_SMS_LT_TRACE(3, " Accepting # " << mConstraints_n << " A:" << matrix_to_string(mConstraints_A) << " b:" << xyz_to_string(mConstraints_b));
++ mConstraints_n;
++mConstraints_n;
}
else
{
CGAL_SMS_LT_TRACE(3," INCOMPATIBLE. Discarded");
CGAL_SMS_LT_TRACE(3, " INCOMPATIBLE. Discarded");
}
}
else
{
CGAL_SMS_LT_TRACE(3," l is ZERO. Discarded");
CGAL_SMS_LT_TRACE(3, " l is ZERO. Discarded");
}
}
else
{
CGAL_SMS_LT_TRACE(3," OVERFLOW. Discarded");
CGAL_SMS_LT_TRACE(3, " OVERFLOW. Discarded");
}
}
template<class V>
int index_of_max_component (V const& v)
int index_of_max_component(const V& v)
{
typedef typename Kernel_traits<V>::Kernel::FT FT;
@ -683,16 +677,16 @@ LindstromTurkCore<TM,K>::
add_constraint_from_gradient(const Matrix& H,
const Vector& c)
{
CGAL_SMS_LT_TRACE(3," Adding constraint from gradient. Current n=" << mConstraints_n);
CGAL_SMS_LT_TRACE(3, " Adding constraint from gradient. Current n=" << mConstraints_n);
CGAL_precondition(mConstraints_n >= 0 && mConstraints_n<=2);
CGAL_precondition(mConstraints_n >= 0 && mConstraints_n <= 2);
switch(mConstraints_n)
{
case 0:
add_constraint_if_alpha_compatible(H.r0(),-c.x());
add_constraint_if_alpha_compatible(H.r1(),-c.y());
add_constraint_if_alpha_compatible(H.r2(),-c.z());
add_constraint_if_alpha_compatible(H.r0(), -c.x());
add_constraint_if_alpha_compatible(H.r1(), -c.y());
add_constraint_if_alpha_compatible(H.r2(), -c.z());
break;
case 1:
{
@ -722,12 +716,11 @@ add_constraint_from_gradient(const Matrix& H,
Q0 = NULL_VECTOR; // This should never happen!
}
CGAL_SMS_LT_TRACE(3," Q0:" << xyz_to_string(Q0));
CGAL_SMS_LT_TRACE(3, " Q0:" << xyz_to_string(Q0));
CGAL_assertion(Q0 != NULL_VECTOR);
Vector Q1 = cross_product(A0,Q0);
Vector Q1 = cross_product(A0, Q0);
Vector A1 = H * Q0;
Vector A2 = H * Q1;
@ -735,7 +728,7 @@ add_constraint_from_gradient(const Matrix& H,
FT b2 = - (Q1 * c);
CGAL_SMS_LT_TRACE(3, " Q1:" << xyz_to_string(Q1) << "\n A1: " << xyz_to_string(A1) << "\n A2:" << xyz_to_string(A2)
<< "\n b1:" << n_to_string(b1) << "\n b2:" << n_to_string(b2));
<< "\n b1:" << n_to_string(b1) << "\n b2:" << n_to_string(b2));
add_constraint_if_alpha_compatible(A1,b1);
add_constraint_if_alpha_compatible(A2,b2);
@ -747,7 +740,7 @@ add_constraint_from_gradient(const Matrix& H,
Vector Q = cross_product(mConstraints_A.r0(),mConstraints_A.r1());
Vector A2 = H * Q;
FT b2 = - (Q * c);
CGAL_SMS_LT_TRACE(3," Q:" << xyz_to_string(Q) << "\n A2: " << xyz_to_string(A2) << "\n b2:" << n_to_string(b2));
CGAL_SMS_LT_TRACE(3, " Q:" << xyz_to_string(Q) << "\n A2: " << xyz_to_string(A2) << "\n b2:" << n_to_string(b2));
add_constraint_if_alpha_compatible(A2,b2);
}

View File

@ -44,6 +44,6 @@ public:
};
} // namespace Surface_mesh_simplification
} //namespace CGAL
} // namespace CGAL
#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_EDGE_LENGHT_COST_H

View File

@ -18,7 +18,7 @@
// Author(s) : Sebastien Loriot <sebastien.loriot@geometryfactory.com>
//
#ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_EDGE_LENGTH_STOP_PREDICATE_H
#define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_EDGE_LENGTH_STOP_PREDICATE_H 1
#define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_EDGE_LENGTH_STOP_PREDICATE_H
#include <CGAL/license/Surface_mesh_simplification.h>
#include <CGAL/squared_distance_3.h>
@ -47,6 +47,6 @@ public:
};
} // namespace Surface_mesh_simplification
} //namespace CGAL
} // namespace CGAL
#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_EDGE_LENGTH_STOP_PREDICATE_H

View File

@ -352,6 +352,6 @@ extract_triangles_and_link()
}
} // namespace Surface_mesh_simplification
} //namespace CGAL
} // namespace CGAL
#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_DETAIL_EDGE_PROFILE_H

View File

@ -34,7 +34,7 @@ class LindstromTurk_cost
public:
typedef TM_ TM;
LindstromTurk_cost(LindstromTurk_params const& aParams = LindstromTurk_params())
LindstromTurk_cost(const LindstromTurk_params& aParams = LindstromTurk_params())
: mParams(aParams)
{}
@ -51,6 +51,6 @@ private:
};
} // namespace Surface_mesh_simplification
} //namespace CGAL
} // namespace CGAL
#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_LINDSTROMTURK_COST_H

View File

@ -18,7 +18,7 @@
// Author(s) : Fernando Cacciola <fernando.cacciola@geometryfactory.com>
//
#ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_LINDSTROMTURK_PLACEMENT_H
#define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_LINDSTROMTURK_PLACEMENT_H 1
#define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_LINDSTROMTURK_PLACEMENT_H
#include <CGAL/license/Surface_mesh_simplification.h>
@ -34,7 +34,7 @@ class LindstromTurk_placement
public:
typedef TM_ TM;
LindstromTurk_placement(LindstromTurk_params const& aParams = LindstromTurk_params())
LindstromTurk_placement(const LindstromTurk_params& aParams = LindstromTurk_params())
: mParams(aParams)
{}
@ -49,6 +49,6 @@ private:
};
} // namespace Surface_mesh_simplification
} //namespace CGAL
} // namespace CGAL
#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_LINDSTROMTURK_PLACEMENT_H

View File

@ -18,7 +18,7 @@
// Author(s) : Fernando Cacciola <fernando.cacciola@geometryfactory.com>
//
#ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_MIDPOINT_PLACEMENT_H
#define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_MIDPOINT_PLACEMENT_H 1
#define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_MIDPOINT_PLACEMENT_H
#include <CGAL/license/Surface_mesh_simplification.h>
@ -27,32 +27,24 @@
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Edge_profile.h>
namespace CGAL {
namespace Surface_mesh_simplification {
namespace Surface_mesh_simplification
{
template<class TM_>
template<class TM_>
class Midpoint_placement
{
public:
typedef TM_ TM;
Midpoint_placement() {}
typedef TM_ TM;
Midpoint_placement()
{}
template <typename Profile>
optional<typename Profile::Point> operator()(const Profile& aProfile) const
{
return optional<typename Profile::Point> (midpoint(aProfile.p0(),aProfile.p1()));
return optional<typename Profile::Point>(midpoint(aProfile.p0(), aProfile.p1()));
}
};
} // namespace Surface_mesh_simplification
} // namespace CGAL
} //namespace CGAL
#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_MIDPOINT_PLACEMENT_H //
// EOF //
#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_MIDPOINT_PLACEMENT_H

View File

@ -18,7 +18,7 @@
// Author(s) : Fernando Cacciola <fernando.cacciola@geometryfactory.com>
//
#ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_EDGE_COLLAPSE_H
#define CGAL_SURFACE_MESH_SIMPLIFICATION_EDGE_COLLAPSE_H 1
#define CGAL_SURFACE_MESH_SIMPLIFICATION_EDGE_COLLAPSE_H
#include <CGAL/license/Surface_mesh_simplification.h>
@ -73,21 +73,21 @@ struct Dummy_visitor
template<class Profile>
void OnStopConditionReached(const Profile&) const {}
template<class Profile, class OFT>
void OnCollected(Profile const&, const OFT&) const {}
void OnCollected(const Profile&, const OFT&) const {}
template<class Profile, class OFT, class Size_type>
void OnSelected(Profile const&, const OFT&, Size_type, Size_type) const {}
void OnSelected(const Profile&, const OFT&, Size_type, Size_type) const {}
template<class Profile, class OPoint>
void OnCollapsing(const Profile&, const OPoint&) const {}
template<class Profile, class VH>
void OnCollapsed(const Profile&, VH) const {}
template<class Profile>
void OnNonCollapsable(Profile const&) const {}
void OnNonCollapsable(const Profile&) const {}
};
template<class TM, class ShouldStop, class P, class T, class R>
int edge_collapse(TM& aSurface,
const ShouldStop& aShould_stop,
cgal_bgl_named_params<P,T,R> const& aParams)
const cgal_bgl_named_params<P,T,R>& aParams)
{
using boost::choose_param;
using boost::choose_const_pmap;
@ -108,8 +108,8 @@ int edge_collapse(TM& aSurface,
template<class TM, class ShouldStop, class GT, class P, class T, class R>
int edge_collapse(TM& aSurface,
ShouldStop const& aShould_stop,
cgal_bgl_named_params<P,T,R> const& aParams)
const ShouldStop& aShould_stop,
const cgal_bgl_named_params<P,T,R>& aParams)
{
using boost::choose_param;
using boost::choose_const_pmap;

View File

@ -15,7 +15,7 @@
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0+
//
//
//
// Author(s) : Fernando Cacciola <fernando.cacciola@gmail.com>
@ -24,7 +24,7 @@
#endif
#include "basics.h"
#include "test_self_intersection.h"
#include "test_self_intersection.h"
//#define TEST_TEST_TRACE_ENABLED
@ -41,14 +41,14 @@ template<std::size_t N> struct eat_sizeof {};
// This is here only to allow a breakpoint to be placed so I can trace back the problem.
void error_handler (char const* what, char const* expr, char const* file, int line, char const* msg)
{
cerr << "CGAL error: " << what << " violation!" << endl
cerr << "CGAL error: " << what << " violation!" << endl
<< "Expr: " << expr << endl
<< "File: " << file << endl
<< "File: " << file << endl
<< "Line: " << line << endl;
if(msg != 0)
cerr << "Explanation:" << msg << endl;
throw std::runtime_error(expr);
throw std::runtime_error(expr);
}
namespace SMS = CGAL::Surface_mesh_simplification;
@ -58,30 +58,31 @@ typedef SMS::Edge_profile<Surface> Profile;
typedef boost::shared_ptr<Surface> SurfaceSP;
// Constructs a flat polyhedron containing just the link of an edge or vertex.
class Link_builder : public CGAL::Modifier_base<Surface::HalfedgeDS>
class Link_builder : public CGAL::Modifier_base<Surface::HalfedgeDS>
{
map<std::size_t, std::size_t> mMap;
int mVIdx;
protected:
typedef boost::graph_traits<Surface> GraphTraits;
typedef CGAL::Halfedge_around_source_iterator<Surface> out_edge_iterator;
typedef GraphTraits::halfedge_descriptor halfedge_descriptor;
typedef GraphTraits::vertex_descriptor vertex_descriptor;
typedef CGAL::Polyhedron_incremental_builder_3<Surface::HalfedgeDS> Builder;
Link_builder() : mVIdx(0) {}
void add_vertex(Builder& aBuilder, Vertex_const_handle v)
{
aBuilder.add_vertex(v->point());
mMap.insert(make_pair(v->id(),mVIdx++));
}
void add_triangle(Builder& aBuilder, Profile::Triangle const& aTri)
void add_triangle(Builder& aBuilder,
const Profile::Triangle& aTri)
{
aBuilder.begin_facet();
aBuilder.add_vertex_to_facet(mMap[aTri.v0->id()]);
@ -93,29 +94,29 @@ protected:
// Constructs a flat polyhedron containing just the link of an edge
class Edge_link_builder : public Link_builder
{
{
const Profile& mProfile;
public:
Edge_link_builder(const Profile& aProfile) : mProfile(aProfile) {}
void operator()(Surface::HalfedgeDS& hds)
void operator()(Surface::HalfedgeDS& hds)
{
Builder B(hds, true);
B.begin_surface(2 + mProfile.link().size(), mProfile.triangles().size());
this->add_vertex(B,mProfile.v0());
this->add_vertex(B,mProfile.v1());
for(Profile::vertex_descriptor_vector::const_iterator vit = mProfile.link().begin(); vit != mProfile.link().end(); ++ vit)
this->add_vertex(B, *vit);
for(Profile::Triangle_vector::const_iterator tit = mProfile.triangles().begin(); tit != mProfile.triangles().end(); ++ tit)
this->add_triangle(B,*tit);
B.end_surface();
}
};
@ -125,38 +126,38 @@ class Vertex_link_builder : public Link_builder
{
Surface* m_tm;
Vertex_handle mV;
Surface& tm() { return *m_tm; }
public:
Vertex_link_builder(Surface& aTM, Vertex_handle aV) : m_tm(&aTM), mV(aV) {}
void operator()(Surface::HalfedgeDS& hds)
void operator()(Surface::HalfedgeDS& hds)
{
Builder B(hds, true);
B.begin_surface(1 + out_degree(mV,tm()), out_degree(mV,tm()));
this->add_vertex(B,mV);
Profile::Triangle_vector triangles;
out_edge_iterator eb, ee;
out_edge_iterator eb, ee;
for(boost::tie(eb,ee) = halfedges_around_source(opposite(halfedge(mV,tm()),tm()),tm()); eb != ee; ++ eb)
{
halfedge_descriptor out_edge1 = *eb;
halfedge_descriptor out_edge2 = out_edge1->opposite()->next();
halfedge_descriptor out_edge2 = out_edge1->opposite()->next();
vertex_descriptor v1 = target(out_edge1,tm());
vertex_descriptor v2 = target(out_edge2,tm());
this->add_vertex(B,v1);
triangles.push_back(Profile::Triangle(mV,v1,v2));
}
}
for(Profile::Triangle_vector::const_iterator tit = triangles.begin(); tit != triangles.end(); ++ tit)
this->add_triangle(B,*tit);
B.end_surface();
}
};
@ -164,18 +165,18 @@ public:
SurfaceSP create_edge_link (const Profile& aProfile)
{
SurfaceSP rLink(new Surface);
try
{
Edge_link_builder lBuilder(aProfile);
rLink->delegate(lBuilder);
}
catch(...)
{
cerr << "Unable to create local mesh" << endl;
}
return rLink;
}
@ -184,17 +185,17 @@ SurfaceSP create_vertex_link (const Profile& aProfile, Vertex_handle aV)
SurfaceSP rLink(new Surface);
try
{
{
Vertex_link_builder lBuilder(aProfile.surface(),aV);
rLink->delegate(lBuilder);
}
catch (...)
{
cerr << "Unable to create local mesh" << endl;
}
return rLink;
}
return rLink;
}
void write (SurfaceSP aSurface, string aName)
@ -204,13 +205,15 @@ void write (SurfaceSP aSurface, string aName)
}
template<class T>
string opt2str (boost::optional<T> const& o)
string opt2str (const boost::optional<T>& o)
{
ostringstream ss;
if(o)
ss << *o;
else ss << "<none>";
return ss.str();
ss << *o;
else
ss << "<none>";
return ss.str();
}
template<class N>
@ -220,120 +223,120 @@ string float2str (N n)
}
template<class P>
string point2str (P const& p)
string point2str (const P& p)
{
return boost::str(boost::format("(%+05.19g %+05.19g %+05.19g)") % to_double(p.x()) % to_double(p.y()) % to_double(p.z()));
}
template<class P>
string optpoint2str (boost::optional<P> const& p)
string optpoint2str (const boost::optional<P>& p)
{
ostringstream ss;
if(p)
ss << point2str(*p);
else ss << "<none>";
return ss.str();
return ss.str();
}
template<class N>
string optfloat2str (boost::optional<N> const& n)
string optfloat2str (const boost::optional<N>& n)
{
ostringstream ss;
if(n)
ss << float2str(*n);
else ss << "<none>";
return ss.str();
return ss.str();
}
template<class V>
string vertex2str (V const& v)
string vertex2str (const V& v)
{
ostringstream ss;
ss << "[V" << v->id() << point2str(v->point()) << "]";
return ss.str();
return ss.str();
}
template<class E>
string edge2str (E const& e)
string edge2str (const E& e)
{
ostringstream ss;
ss << "{E" << e->id() << vertex2str(e->opposite()->vertex()) << "->" << vertex2str(e->vertex()) << "}";
return ss.str();
return ss.str();
}
template<class T> ostream& operator << (ostream& os, boost::optional<T> const& o) { return os << opt2str(o); }
template<class T> ostream& operator << (ostream& os, const boost::optional<T>& o) { return os << opt2str(o); }
string normalize_EOL (string line)
{
string::size_type l = line.length();
string::size_type d = (l > 0 && line[l-1] == '\r') ? 1 : 0;
string::size_type d = (l > 0 && line[l-1] == '\r') ? 1 : 0;
return line.substr(0, l-d);
}
#define REPORT_ERROR(msg) error(__FILE__,__LINE__,0, msg);
#define REPORT_ERROR2(pred,msg) REPORT_ERROR(msg)
#define CHECK_MSG(pred,msg) if(!(pred)) REPORT_ERROR2(#pred,msg)
#define CHECK_MSG(pred,msg) if(!(pred)) REPORT_ERROR2(#pred,msg)
#define CHECK(pred) CHECK_MSG(pred,string(""))
#define CHECK_EQUAL(x,y) CHECK_MSG(((x)==(y)), str(format("Assertion failed: %1%(=%2%)==%3%(=%4%)") % (#x) % (x) % (#y) % (y)))
#define CHECK_NOT_EQUAL(x,y) CHECK_MSG(((x)!=(y)), str(format("Assertion failed: %1%(=%2%)!=%3%(=%4%)") % (#x) % (x) % (#y) % (y)))
class Visitor : public SMS::Edge_collapse_visitor_base<Surface>
{
{
public :
Visitor(string aTestCase) : mTestCase(aTestCase)
Visitor(string aTestCase) : mTestCase(aTestCase)
{
#ifdef CGAL_SMS_TRACE_IMPL
#ifdef CGAL_SMS_TRACE_IMPL
::internal::cgal_enable_sms_trace = true;
#endif
mStep = 0;
#endif
mStep = 0;
}
virtual ~Visitor()
{
}
virtual void OnStarted(Surface&) const
virtual void OnStarted(Surface&) const
{
}
virtual void OnFinished (Surface& aSurface) const
{
virtual void OnFinished (Surface& aSurface) const
{
CHECK(aSurface.is_valid());
}
virtual void OnCollected(const Profile& aProfile, boost::optional<FT> const& aCost) const
}
virtual void OnCollected(const Profile& aProfile, const boost::optional<FT>& aCost) const
{
TEST_TRACE(str (format("Collecting %1% : cost=%2%") % edge2str(aProfile.v0_v1()) % optfloat2str(aCost)));
}
virtual void OnCollapsing(const Profile& aProfile, boost::optional<Point> const& aP) const
}
virtual void OnCollapsing(const Profile& aProfile, const boost::optional<Point>& aP) const
{
TEST_TRACE(str (format("S %1% - Collapsing %2% : placement=%3%") % mStep % edge2str(aProfile.v0_v1()) % optpoint2str(aP)));
//mBefore = create_edge_link(aProfile);
}
virtual void OnCollapsed(const Profile& aProfile, Vertex_handle const& aV) const
virtual void OnCollapsed(const Profile& aProfile, const Vertex_handle& aV) const
{
// Some collapse can result in self-intersections in any case, so we can't mark it as a failure
if(false && Is_self_intersecting(aProfile.surface()))
{
SurfaceSP lAfter = create_vertex_link(aProfile, aV);
write(mBefore, str(format("%1%.step-%2%-before.off") % mTestCase % mStep));
write(lAfter , str(format("%1%.step-%2%-after.off") % mTestCase % mStep));
REPORT_ERROR(str(format("Resulting surface self-intersects after step %1% (%2% edges left)") % mStep % (aProfile.surface().size_of_halfedges() / 2)));
}
++ mStep;
}
++mStep;
}
private:
@ -344,69 +347,67 @@ private:
if(pred)
cerr << " Assertion failed: " << pred << endl;
cerr << " " << msg << endl;
throw runtime_error("");
}
private:
string mTestCase;
mutable int mStep;
string mTestCase;
mutable int mStep;
mutable SurfaceSP mBefore;
};
bool sWriteResult = false;
bool sUseMP = false;
bool sUseMP = false;
int sStop = 1;
bool Test (string aName)
{
bool rSucceeded = false;
try
{
string off_name = aName;
ifstream off_is(off_name.c_str());
if(off_is)
{
Surface lSurface;
Surface lSurface;
off_is >> lSurface;
if(lSurface.is_valid())
{
if(lSurface.is_pure_triangle())
{
cerr << "Processing " << aName << " (" << (lSurface.size_of_halfedges() / 2) << " edges)" << endl;
Visitor vis(aName);
set_halfedgeds_items_id(lSurface);
SMS::Count_stop_predicate<Surface> stop(sStop);
Real_timer t; t.start();
Real_timer t; t.start();
if(sUseMP)
{
SMS::Edge_length_cost <Surface> cost;
SMS::Midpoint_placement<Surface> placement;
edge_collapse(lSurface,stop,CGAL::parameters::get_cost(cost).get_placement(placement).visitor(vis));
}
else
{
SMS::LindstromTurk_cost <Surface> cost;
SMS::LindstromTurk_placement<Surface> placement;
edge_collapse(lSurface,stop,CGAL::parameters::get_cost(cost).get_placement(placement).visitor(vis));
}
}
t.stop();
rSucceeded = lSurface.is_valid() && lSurface.is_pure_triangle();
cerr << "\r" << aName << (rSucceeded ? " succeeded" : "FAILED") << ". Elapsed time=" << t.time() << " seconds." << endl;
if(sWriteResult)
@ -431,36 +432,35 @@ bool Test (string aName)
else
{
cerr << "Unable to open test file " << aName << endl;
}
}
}
catch (std::exception const& x)
catch (const std::exception& x)
{
string what(x.what());
if(what.length() > 0)
cerr << "Exception caught: " << what << endl;
}
return rSucceeded;
}
int main(int argc, char** argv)
int main(int argc, char** argv)
{
set_error_handler (error_handler);
set_warning_handler(error_handler);
cout << setprecision(4);
cerr << setprecision(4);
vector<string> lCases;
for(int i = 1; i < argc; ++i)
{
if(argv[i][0] == '-')
{
switch(argv[i][1])
{
{
case 'w': sWriteResult = true; break;
case 's': sStop = atoi(&argv[i][2]); break;
case 'm': sUseMP = true; break;
@ -478,12 +478,12 @@ int main(int argc, char** argv)
}
}
}
if(lCases.size() == 0)
{
cout << "collapse_edge_test file0 [-w] [-sNUM_EDGES] [-m] file1 ... fileN\n";
return 1;
}
}
else
{
unsigned lOK = 0;
@ -491,12 +491,12 @@ int main(int argc, char** argv)
{
if(Test(*it))
++ lOK;
}
}
cout << endl
<< lOK << " cases succedded." << endl
<< (lCases.size() - lOK) << " cases failed." << endl;
return lOK == lCases.size() ? 0 : 1;
}
}
@ -519,9 +519,4 @@ void postcondition_fail(const char* expr, const char* file, int line)
}
}
#endif
// EOF //

View File

@ -11,9 +11,9 @@ typedef CGAL::Box_intersection_d::Box_with_handle_d<double, 3, Facet_const_handl
std::vector<Triangle> triangles;
struct Intersect_facets
struct Intersect_facets
{
void operator()(const Box* b, const Box* c) const
void operator()(const Box* b, const Box* c) const
{
Halfedge_const_handle h = b->handle()->halfedge();
// check for shared egde --> no intersection
@ -21,6 +21,7 @@ struct Intersect_facets
|| h->next()->opposite()->facet() == c->handle()
|| h->next()->next()->opposite()->facet() == c->handle())
return;
// check for shared vertex --> maybe intersection, maybe not
Halfedge_const_handle g = c->handle()->halfedge();
Halfedge_const_handle v;
@ -48,6 +49,7 @@ struct Intersect_facets
v = g->next()->next();
}
}
if(v != Halfedge_const_handle()) {
// found shared vertex:
assert(h->vertex() == v->vertex());
@ -75,6 +77,7 @@ struct Intersect_facets
}
return;
}
// check for geometric intersection
Triangle t1(h->vertex()->point(),
h->next()->vertex()->point(),
@ -82,6 +85,7 @@ struct Intersect_facets
Triangle t2(g->vertex()->point(),
g->next()->vertex()->point(),
g->next()->next()->vertex()->point());
if(CGAL::do_intersect(t1, t2)) {
//cerr << "Triangles intersect:\n T1: " << t1 << "\n T2 :"
// << t2 << endl;
@ -91,8 +95,7 @@ struct Intersect_facets
}
};
bool Is_self_intersecting(Surface const& s)
bool Is_self_intersecting(const Surface& s)
{
std::vector<Box> boxes;
boxes.reserve(s.size_of_facets());
@ -113,5 +116,5 @@ bool Is_self_intersecting(Surface const& s)
CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),
Intersect_facets(), std::ptrdiff_t(2000));
return triangles.size() > 0;
return triangles.size() > 0;
}