Merge branch 'Mesh_3-compare_index-GF-old' into Mesh_3-compare_index-GF

Conflicts:
	Mesh_3/include/CGAL/Mesh_3/Detect_features_in_polyhedra.h
	Mesh_3/include/CGAL/Mesh_domain_with_polyline_features_3.h
	Mesh_3/include/CGAL/Mesh_polyhedron_3.h
	Mesh_3/test/Mesh_3/test_meshing_polylines_only.cpp
	STL_Extension/include/CGAL/Compact_container.h
	STL_Extension/test/STL_Extension/test_Compact_container.cpp
This commit is contained in:
Sébastien Loriot 2014-05-21 18:24:17 +02:00
commit 3fa09693a3
34 changed files with 1034 additions and 330 deletions

View File

@ -1,3 +1,5 @@
#define CGAL_MESH_3_VERBOSE
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Mesh_triangulation_3.h>

View File

@ -31,7 +31,8 @@ FT sphere_function (const Point& p)
int main()
{
// Domain (Warning: Sphere_3 constructor uses squared radius !)
Mesh_domain domain(sphere_function, K::Sphere_3(CGAL::ORIGIN, 2.));
Mesh_domain domain(sphere_function,
K::Sphere_3(CGAL::ORIGIN, 2.));
// Mesh criteria
Mesh_criteria criteria(facet_angle=30, facet_size=0.1, facet_distance=0.025,

View File

@ -45,7 +45,8 @@ FT sphere_function (const Point& p)
int main()
{
// Domain (Warning: Sphere_3 constructor uses squared radius !)
Mesh_domain domain(sphere_function, K::Sphere_3(CGAL::ORIGIN, 2.));
Mesh_domain domain(sphere_function,
K::Sphere_3(CGAL::ORIGIN, 2.));
// Mesh criteria
Spherical_sizing_field size;

View File

@ -53,7 +53,8 @@ FT sphere_function (const Point& p)
int main()
{
// Domain (Warning: Sphere_3 constructor uses squared radius !)
Mesh_domain domain(sphere_function, K::Sphere_3(Point(1, 0, 0), 6.));
Mesh_domain domain(sphere_function,
K::Sphere_3(Point(1, 0, 0), 6.));
// Mesh criteria
Mesh_criteria criteria(edge_size = 0.15,

View File

@ -28,6 +28,8 @@
#include <CGAL/basic.h>
#include <CGAL/triangulation_assertions.h>
#include <CGAL/internal/Dummy_tds_3.h>
#include <CGAL/tags.h>
#include <CGAL/Has_timestamp.h>
#include <CGAL/Regular_triangulation_cell_base_3.h>
#include <CGAL/Mesh_3/io_signature.h>
@ -89,13 +91,13 @@ public:
, next_intrusive_()
, previous_intrusive_()
#endif
, time_stamp_(-1)
, surface_center_index_table_()
, sliver_value_(FT(0.))
, subdomain_index_()
, bits_(0)
, sliver_cache_validity_(false)
{
}
{}
Compact_mesh_cell_base_3(const Compact_mesh_cell_base_3& rhs)
: circumcenter_(NULL)
@ -103,6 +105,7 @@ public:
, next_intrusive_(rhs.next_intrusive_)
, previous_intrusive_(rhs.previous_intrusive_)
#endif
, time_stamp_(rhs.time_stamp_)
, sliver_value_(rhs.sliver_value_)
, subdomain_index_(rhs.subdomain_index_)
, bits_(0)
@ -126,6 +129,7 @@ public:
, next_intrusive_()
, previous_intrusive_()
#endif
, time_stamp_(-1)
, surface_center_index_table_()
, sliver_value_(FT(0.))
, subdomain_index_()
@ -151,6 +155,7 @@ public:
, next_intrusive_()
, previous_intrusive_()
#endif
, time_stamp_(-1)
, surface_center_index_table_()
, sliver_value_(FT(0.))
, subdomain_index_()
@ -458,6 +463,17 @@ public:
}
#endif // CGAL_INTRUSIVE_LIST
/// For the determinism of Compact_container iterators
///@{
typedef Tag_true Has_timestamp;
std::size_t time_stamp() const {
return time_stamp_;
}
void set_time_stamp(const std::size_t& ts) {
time_stamp_ = ts;
}
///@}
private:
@ -476,6 +492,7 @@ private:
#ifdef CGAL_INTRUSIVE_LIST
Cell_handle next_intrusive_, previous_intrusive_;
#endif
std::size_t time_stamp_;
CGAL::cpp11::array<Index, 4> surface_center_index_table_;
/// Stores visited facets (4 first bits)
@ -494,8 +511,6 @@ private:
}; // end class Compact_mesh_cell_base_3
template < class GT, class MT, class Cb >
std::istream&
operator>>(std::istream &is,

View File

@ -31,6 +31,7 @@
# pragma warning(disable:4180) // qualifier applied to function type has no meaning; ignored
#endif
#include <CGAL/Random.h>
#include <CGAL/Mesh_3/Labeled_mesh_domain_3.h>
#include <CGAL/Mesh_3/Implicit_to_labeled_function_wrapper.h>
@ -47,7 +48,7 @@ template<class Function,
class BGT,
class Wrapper = Mesh_3::Implicit_to_labeled_function_wrapper<Function,BGT> >
class Implicit_mesh_domain_3
: public Mesh_3::Labeled_mesh_domain_3<Wrapper, BGT >
: public Mesh_3::Labeled_mesh_domain_3<Wrapper, BGT>
{
public:
/// Base type
@ -66,8 +67,9 @@ public:
*/
Implicit_mesh_domain_3(const Function& f,
const Sphere_3& bounding_sphere,
const FT& error_bound = FT(1e-3))
: Base(Wrapper(f), bounding_sphere, error_bound) {}
const FT& error_bound = FT(1e-3),
CGAL::Random* p_rng = NULL)
: Base(Wrapper(f), bounding_sphere, error_bound, p_rng) {}
/// Destructor
virtual ~Implicit_mesh_domain_3() {}

View File

@ -27,7 +27,7 @@
#ifndef CGAL_LABELED_IMAGE_MESH_DOMAIN_3_H
#define CGAL_LABELED_IMAGE_MESH_DOMAIN_3_H
#include <CGAL/Random.h>
#include <CGAL/Mesh_3/Labeled_mesh_domain_3.h>
#include <CGAL/Mesh_3/Image_to_labeled_function_wrapper.h>
@ -41,6 +41,7 @@ namespace CGAL {
*/
template<class Image,
class BGT,
class Wrapper = Mesh_3::Image_to_labeled_function_wrapper<Image, BGT> >
class Labeled_image_mesh_domain_3
: public Mesh_3::Labeled_mesh_domain_3<Wrapper, BGT>
@ -55,10 +56,12 @@ public:
/// Constructor
Labeled_image_mesh_domain_3(const Image& image,
const FT& error_bound = FT(1e-3))
const FT& error_bound = FT(1e-3),
CGAL::Random* p_rng = NULL)
: Base(Wrapper(image),
compute_bounding_box(image),
error_bound)
error_bound,
p_rng)
{}
/// Destructor

View File

@ -55,8 +55,8 @@ public:
typedef typename Polyhedron::Facet Facet;
typedef typename Facet::Patch_id Patch_id;
typedef std::set<Facet*> Facet_handle_set;
typedef std::set<Halfedge*> He_handle_set;
typedef std::set<Facet_handle> Facet_handle_set;
typedef std::set<Halfedge_handle> He_handle_set;
public:
Detect_features_in_polyhedra() : current_surface_index_(1) {}
@ -69,7 +69,7 @@ public:
private:
Vector_3 facet_normal(const Facet_handle& f) const;
bool is_sharp(const Halfedge_handle& he, FT cos_angle) const;
void flood(Facet& f, const Patch_id id,
void flood(Facet_handle f, const Patch_id id,
Facet_handle_set& unsorted_faces) const;
template <typename Int>
@ -143,18 +143,19 @@ detect_surface_patches(Polyhedron& polyhedron)
for ( typename Polyhedron::Facet_iterator fit = polyhedron.facets_begin(),
end = polyhedron.facets_end() ; fit != end ; ++fit )
{
unsorted_faces.insert(&*fit);
Facet_handle fh = fit;
unsorted_faces.insert(fh);
}
// Flood
while ( ! unsorted_faces.empty() )
{
Facet& f = **(unsorted_faces.begin());
Facet_handle f = *(unsorted_faces.begin());
unsorted_faces.erase(unsorted_faces.begin());
const Patch_id patch_id = generate_patch_id(Patch_id(),
current_surface_index_);
f.set_patch_id(patch_id);
f->set_patch_id(patch_id);
flood(f,patch_id,unsorted_faces);
++current_surface_index_;
}
@ -245,52 +246,52 @@ is_sharp(const Halfedge_handle& he, FT cos_angle) const
template <typename P_>
void
Detect_features_in_polyhedra<P_>::
flood(Facet& f, const Patch_id patch_id, Facet_handle_set& unsorted_faces) const
flood(Facet_handle f, const Patch_id patch_id, Facet_handle_set& unsorted_faces) const
{
typedef typename Facet::Halfedge_around_facet_circulator Facet_he_circ;
Facet_he_circ begin = f.facet_begin();
Facet_he_circ begin = f->facet_begin();
Facet_he_circ done = begin;
// Initialize he_to_explore with halfedges of the starting facet
He_handle_set he_to_explore;
CGAL_For_all(begin,done)
{
he_to_explore.insert(&*(begin->opposite()));
he_to_explore.insert(begin->opposite());
}
// While there is something to explore
while ( ! he_to_explore.empty() )
{
// Get next halfedge to explore
Halfedge& he = **(he_to_explore.begin());
Halfedge_handle he = *(he_to_explore.begin());
he_to_explore.erase(he_to_explore.begin());
// If we don't go through a border of the patch
if ( ! he.is_feature_edge() && ! he.is_border() )
if ( ! he->is_feature_edge() && ! he->is_border() )
{
Facet& explored_facet = *(he.facet());
Facet_handle explored_facet = he->facet();
// Mark facet and delete it from unsorted
explored_facet.set_patch_id(patch_id);
unsorted_faces.erase(&explored_facet);
explored_facet->set_patch_id(patch_id);
unsorted_faces.erase(explored_facet);
// Add/Remove facet's halfedge to/from explore list
Facet_he_circ he_begin = explored_facet.facet_begin();
Facet_he_circ he_begin = explored_facet->facet_begin();
Facet_he_circ he_done = he_begin;
CGAL_For_all(he_begin,he_done)
{
Halfedge& current_he = *he_begin;
Halfedge_handle current_he = he_begin;
// do not explore heh again
if ( &current_he == &he ) { continue; }
if ( current_he == he ) { continue; }
// if current_he is not in to_explore set, add it, otherwise remove it
// (because we just explore the facet he_begin is pointing to)
if ( he_to_explore.erase(&current_he) == 0 )
if ( he_to_explore.erase(current_he) == 0 )
{
he_to_explore.insert(&*(current_he.opposite()));
he_to_explore.insert(current_he->opposite());
}
}
}

View File

@ -23,15 +23,46 @@
#define CGAL_MESH_3_DETECT_POLYLINES_IN_POLYHEDRA_H
#include <CGAL/Mesh_3/Detect_polylines_in_polyhedra_fwd.h>
#include <CGAL/Has_timestamp.h>
#include <CGAL/Default.h>
#include <algorithm>
#include <boost/foreach.hpp>
#include <boost/mpl/if.hpp>
namespace CGAL { namespace Mesh_3 {
struct Detect_polyline_less {
template <typename Handle>
bool operator()(const Handle& va, const Handle& vb) const {
return &*va < &*vb;
template <typename Handle>
struct CGAL_with_time_stamp
{
public:
static bool less(Handle h1, Handle h2)
{
return h1->time_stamp() < h2->time_stamp();
}
};
template <typename Handle>
struct CGAL_no_time_stamp
{
public:
static bool less(Handle h1, Handle h2)
{
return &*h1 < &*h2;
}
};
struct Detect_polyline_less
{
template<typename Handle>
bool operator()(const Handle& h1, const Handle& h2) const
{
typedef typename std::iterator_traits<Handle>::value_type Type;
typedef typename boost::mpl::if_c<
CGAL::internal::Has_timestamp<Type>::value,
CGAL_with_time_stamp<Handle>,
CGAL_no_time_stamp<Handle> >::type Comparator;
return Comparator::less(h1, h2);
}
};

View File

@ -38,6 +38,7 @@
#include <boost/optional.hpp>
#include <CGAL/tuple.h>
#include <CGAL/Origin.h>
#include <CGAL/Random.h>
namespace CGAL {
@ -55,7 +56,8 @@ namespace Mesh_3 {
* tags of it's incident subdomain.
* Thus, a boundary facet of the domain is labelled <0,b>, where b!=0.
*/
template<class Function, class BGT>
template<class Function,
class BGT>
class Labeled_mesh_domain_3
{
public:
@ -94,14 +96,20 @@ public:
*/
Labeled_mesh_domain_3(const Function& f,
const Sphere_3& bounding_sphere,
const FT& error_bound = FT(1e-3));
const FT& error_bound = FT(1e-3),
CGAL::Random* p_rng = NULL);
Labeled_mesh_domain_3(const Function& f,
const Bbox_3& bbox,
const FT& error_bound = FT(1e-3));
const FT& error_bound = FT(1e-3),
CGAL::Random* p_rng = NULL);
/// Destructor
virtual ~Labeled_mesh_domain_3() {}
virtual ~Labeled_mesh_domain_3()
{
if(delete_rng_)
delete p_rng_;
}
/**
* Constructs a set of \ccc{n} points on the surface, and output them to
@ -461,6 +469,9 @@ private:
const Function function_;
/// The bounding box
const Iso_cuboid_3 bbox_;
/// The random number generator used by Construct_initial_points
CGAL::Random* p_rng_;
bool delete_rng_;
/// Error bound relative to sphere radius
FT squared_error_bound_;
@ -483,24 +494,40 @@ template<class F, class BGT>
Labeled_mesh_domain_3<F,BGT>::Labeled_mesh_domain_3(
const F& f,
const Sphere_3& bounding_sphere,
const FT& error_bound )
const FT& error_bound,
CGAL::Random* p_rng)
: function_(f)
, bbox_(iso_cuboid(bounding_sphere.bbox()))
, p_rng_(p_rng)
, delete_rng_(false)
, squared_error_bound_(squared_error_bound(bounding_sphere,error_bound))
{
// TODO : CGAL_ASSERT(0 < f(bounding_sphere.get_center()) ) ?
if(!p_rng_)
{
p_rng_ = new CGAL::Random(0);
delete_rng_ = true;
}
}
template<class F, class BGT>
Labeled_mesh_domain_3<F,BGT>::Labeled_mesh_domain_3(
const F& f,
const Bbox_3& bbox,
const FT& error_bound )
const FT& error_bound,
CGAL::Random* p_rng)
: function_(f)
, bbox_(iso_cuboid(bbox))
, p_rng_(p_rng)
, delete_rng_(false)
, squared_error_bound_(squared_error_bound(bbox_,error_bound))
{
// TODO : CGAL_ASSERT(0 < f(bounding_sphere.get_center()) ) ?
if(!p_rng_)
{
p_rng_ = new CGAL::Random(0);
delete_rng_ = true;
}
}
@ -522,8 +549,9 @@ Labeled_mesh_domain_3<F,BGT>::Construct_initial_points::operator()(
const double radius = std::sqrt(CGAL::to_double(squared_radius));
Random_points_on_sphere_3 random_point_on_sphere(radius);
Random_points_in_sphere_3 random_point_in_sphere(radius);
CGAL::Random& rng = *(r_domain_.p_rng_);
Random_points_on_sphere_3 random_point_on_sphere(radius, rng);
Random_points_in_sphere_3 random_point_in_sphere(radius, rng);
// Get some functors
typename BGT::Construct_segment_3 segment_3 =

View File

@ -231,7 +231,7 @@ public:
Index index(const Vertex_handle& v) const { return v->index(); }
/// Outputs the mesh to medit
void output_to_medit(std::ofstream& os,
void output_to_medit(std::ostream& os,
bool rebind = true,
bool show_patches = false) const
{

View File

@ -918,6 +918,9 @@ insert_balls(const Vertex_handle& vp,
std::cerr << "Number of to-be-inserted balls is: "
<< n << "\n between points ("
<< vp->point() << ") and (" << vq->point()
<< ") (geodesic distance: "
<< domain_.geodesic_distance(vp->point(), vq->point(),
curve_index)
<< ")\n";
#endif
const Bare_point new_point =

View File

@ -46,6 +46,7 @@
#include <CGAL/Timer.h>
#include <CGAL/Mesh_3/Null_perturber_visitor.h>
#include <CGAL/Mesh_3/sliver_criteria.h>
#include <CGAL/Has_timestamp.h>
#include <boost/format.hpp>
#ifdef CGAL_MESH_3_USE_RELAXED_HEAP
@ -61,6 +62,29 @@
namespace CGAL {
namespace internal { namespace Mesh_3 {
// Hash function for boost::unordered_map<Vertex_handle,...>
template <typename Tr, bool HasTimestamp>
struct VHash
{
typedef typename Tr::Vertex_handle Vertex_handle;
std::size_t operator()(Vertex_handle vh) const
{
return vh->time_stamp();
}
};
template <typename Tr>
struct VHash<Tr, false>
{
typedef typename Tr::Vertex_handle Vertex_handle;
std::size_t operator()(Vertex_handle vh) const
{
return boost::hash_value(&*vh);
}
};
}} // end internal::Mesh_3
namespace Mesh_3 {
template < typename C3T3,
@ -250,14 +274,6 @@ public:
private:
struct VHash
{
std::size_t operator()(Vertex_handle vh) const
{
return boost::hash_value(&*vh);
}
};
// -----------------------------------
// Private methods
// -----------------------------------
@ -651,7 +667,12 @@ build_priority_queue(const FT& sliver_bound, PQueue& pqueue) const
int pqueue_size = 0;
typedef boost::unordered_map<Vertex_handle,PVertex,VHash> M;
typedef typename std::iterator_traits<Vertex_handle>::value_type Vertex;
typedef CGAL::internal::Has_timestamp<Vertex> Vertex_has_timestamp;
using CGAL::internal::Mesh_3::VHash;
typedef VHash<Tr, Vertex_has_timestamp::value> Hash_fct;
typedef boost::unordered_map<Vertex_handle,PVertex,Hash_fct> M;
M vpm;
for ( typename Tr::Finite_cells_iterator cit = tr_.finite_cells_begin();
cit != tr_.finite_cells_end() ;

View File

@ -33,6 +33,7 @@
#include <CGAL/Regular_triangulation_cell_base_with_weighted_circumcenter_3.h>
#include <CGAL/Mesh_3/Mesh_surface_cell_base_3.h>
#include <CGAL/Mesh_3/io_signature.h>
#include <CGAL/tags.h>
namespace CGAL {
@ -83,6 +84,7 @@ public:
, next_intrusive_()
, previous_intrusive_()
#endif
, time_stamp_(-1)
{}
Mesh_cell_base_3 (Vertex_handle v0,
@ -97,6 +99,7 @@ public:
, next_intrusive_()
, previous_intrusive_()
#endif
, time_stamp_(-1)
{}
Mesh_cell_base_3 (Vertex_handle v0,
@ -115,6 +118,7 @@ public:
, next_intrusive_()
, previous_intrusive_()
#endif
, time_stamp_(-1)
{}
// Default copy constructor and assignment operator are ok
@ -158,6 +162,18 @@ public:
}
#endif // CGAL_INTRUSIVE_LIST
/// For the determinism of Compact_container iterators
///@{
typedef Tag_true Has_timestamp;
std::size_t time_stamp() const {
return time_stamp_;
}
void set_time_stamp(const std::size_t& ts) {
time_stamp_ = ts;
}
///@}
private:
// The index of the cell of the input complex that contains me
Subdomain_index subdomain_index_;
@ -168,11 +184,10 @@ private:
#ifdef CGAL_INTRUSIVE_LIST
Cell_handle next_intrusive_, previous_intrusive_;
#endif
std::size_t time_stamp_;
}; // end class Mesh_cell_base_3
template < class GT, class MT, class Cb >
std::istream&
operator>>(std::istream &is,

View File

@ -150,8 +150,8 @@ public:
else if ( distance > length() ) { distance -= length(); }
}
CGAL_assertion( distance > FT(0) );
CGAL_assertion( distance < length() );
CGAL_assertion( distance >= FT(0) );
CGAL_assertion( distance <= length() );
// Initialize iterators
const_iterator pit = points_.begin();

View File

@ -27,6 +27,8 @@
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Polyhedron_items_3.h>
#include <CGAL/Has_timestamp.h>
#include <CGAL/tags.h>
#include <set>
@ -44,6 +46,8 @@ private:
typedef CGAL::HalfedgeDS_vertex_base<Refs, Tag, Point> Pdv_base;
Set_of_indices indices;
std::size_t time_stamp_;
public:
int nb_of_feature_edges;
@ -59,6 +63,18 @@ public:
indices.insert(i);
}
/// For the determinism of Compact_container iterators
///@{
typedef Tag_true Has_timestamp;
std::size_t time_stamp() const {
return time_stamp_;
}
void set_time_stamp(const std::size_t& ts) {
time_stamp_ = ts;
}
///@}
const Set_of_indices&
incident_patches_ids_set() const {
return indices;
@ -74,6 +90,8 @@ public CGAL::HalfedgeDS_halfedge_base<Refs,Tprev,Tvertex,Tface>
{
private:
bool feature_edge;
std::size_t time_stamp_;
public:
Mesh_polyhedron_halfedge()
@ -87,6 +105,18 @@ public:
feature_edge = b;
this->opposite()->feature_edge = b;
}
/// For the determinism of Compact_container iterators
///@{
typedef Tag_true Has_timestamp;
std::size_t time_stamp() const {
return time_stamp_;
}
void set_time_stamp(const std::size_t& ts) {
time_stamp_ = ts;
}
///@}
};
template <typename Integral>
@ -108,6 +138,8 @@ public CGAL::HalfedgeDS_face_base<Refs,T_,Pln_>
{
private:
Patch_id_ patch_id_;
std::size_t time_stamp_;
public:
typedef Patch_id_ Patch_id;
@ -122,8 +154,22 @@ public:
void set_patch_id(const Patch_id& i) {
patch_id_ = i;
}
/// For the determinism of Compact_container iterators
///@{
typedef Tag_true Has_timestamp;
std::size_t time_stamp() const {
return time_stamp_;
}
void set_time_stamp(const std::size_t& ts) {
time_stamp_ = ts;
}
///@}
};
template <typename Patch_id>
class Mesh_polyhedron_items : public CGAL::Polyhedron_items_3 {
public:
@ -166,7 +212,6 @@ struct Mesh_polyhedron_3
typedef type Type;
};
} // end namespace CGAL
#endif // CGAL_MESH_POLYHEDRON_3_H

View File

@ -30,9 +30,10 @@
#define CGAL_COMPACT_MESH_VERTEX_BASE_3_H
#include <CGAL/Triangulation_vertex_base_3.h>
#include <CGAL/Mesh_3/Has_features.h>
#include <CGAL/internal/Mesh_3/get_index.h>
#include <CGAL/Mesh_3/io_signature.h>
#include <CGAL/Has_timestamp.h>
#include <CGAL/tags.h>
namespace CGAL {
@ -74,6 +75,7 @@ public:
, next_intrusive_()
, previous_intrusive_()
#endif //CGAL_INTRUSIVE_LIST
, time_stamp_(-1)
{}
// Default copy constructor and assignment operator are ok
@ -124,6 +126,18 @@ public:
}
#endif
/// For the determinism of Compact_container iterators
///@{
typedef Tag_true Has_timestamp;
std::size_t time_stamp() const {
return time_stamp_;
}
void set_time_stamp(const std::size_t& ts) {
time_stamp_ = ts;
}
///@}
bool is_c2t3_cache_valid() const {
return cache_validity;
}
@ -179,12 +193,9 @@ private:
Vertex_handle next_intrusive_;
Vertex_handle previous_intrusive_;
#endif
}; // end class Mesh_vertex_base_3
std::size_t time_stamp_;
namespace internal {
namespace Mesh_3 {
} // end namespace internal::Mesh_3
} // end namespace internal
}; // end class Mesh_vertex_base_3
template<class GT,
class MD,

View File

@ -36,6 +36,7 @@
#include <CGAL/AABB_traits.h>
#include <sstream>
#include <CGAL/Random.h>
#include <CGAL/point_generators_3.h>
#include <CGAL/Mesh_3/Creator_weighted_point_3.h>
#include <CGAL/Mesh_3/Profile_counter.h>
@ -203,36 +204,57 @@ public:
Polyhedral_mesh_domain_3()
: tree_()
, bounding_tree_(&tree_)
, has_cache(false) {}
, has_cache(false)
, p_rng_(NULL)
, delete_rng_(true)
{
p_rng_ = new CGAL::Random(0);
}
/**
* @brief Constructor. Contruction from a polyhedral surface
* @param polyhedron the polyhedron describing the polyhedral surface
*/
Polyhedral_mesh_domain_3(const Polyhedron& p)
Polyhedral_mesh_domain_3(const Polyhedron& p,
CGAL::Random* p_rng = NULL)
: tree_(TriangleAccessor().triangles_begin(p),
TriangleAccessor().triangles_end(p)),
bounding_tree_(&tree_) // the bounding tree is tree_
, has_cache(false)
, p_rng_(p_rng)
, delete_rng_(false)
{
if(!p.is_pure_triangle()) {
std::cerr << "Your input polyhedron must be triangulated!\n";
CGAL_error_msg("Your input polyhedron must be triangulated!");
}
if(!p_rng_)
{
p_rng_ = new CGAL::Random(0);
delete_rng_ = true;
}
}
Polyhedral_mesh_domain_3(const Polyhedron& p,
const Polyhedron& bounding_polyhedron)
const Polyhedron& bounding_polyhedron,
CGAL::Random* p_rng = NULL)
: tree_(TriangleAccessor().triangles_begin(p),
TriangleAccessor().triangles_end(p))
, bounding_tree_(new AABB_tree_(TriangleAccessor().triangles_begin(bounding_polyhedron),
TriangleAccessor().triangles_end(bounding_polyhedron)))
, has_cache(false)
, p_rng_(p_rng)
, delete_rng_(false)
{
tree_.insert(TriangleAccessor().triangles_begin(bounding_polyhedron),
TriangleAccessor().triangles_end(bounding_polyhedron));
tree_.build();
bounding_tree_->build();
if(!p_rng_)
{
p_rng_ = new CGAL::Random(0);
delete_rng_ = true;
}
}
/**
@ -249,8 +271,11 @@ public:
template <typename InputPolyhedraPtrIterator>
Polyhedral_mesh_domain_3(InputPolyhedraPtrIterator begin,
InputPolyhedraPtrIterator end,
const Polyhedron& bounding_polyhedron)
const Polyhedron& bounding_polyhedron,
CGAL::Random* p_rng = NULL)
: has_cache(false)
, p_rng_(p_rng)
, delete_rng_(false)
{
if(begin != end) {
for(; begin != end; ++begin) {
@ -270,6 +295,11 @@ public:
TriangleAccessor().triangles_end(bounding_polyhedron));
bounding_tree_ = &tree_;
}
if(!p_rng_)
{
p_rng_ = new CGAL::Random(0);
delete_rng_ = true;
}
}
/**
@ -284,8 +314,11 @@ public:
*/
template <typename InputPolyhedraPtrIterator>
Polyhedral_mesh_domain_3(InputPolyhedraPtrIterator begin,
InputPolyhedraPtrIterator end)
InputPolyhedraPtrIterator end,
CGAL::Random* p_rng = NULL)
: has_cache(false)
, p_rng_(p_rng)
, delete_rng_(false)
{
if(begin != end) {
for(; begin != end; ++begin) {
@ -295,6 +328,11 @@ public:
tree_.build();
}
bounding_tree_ = 0;
if(!p_rng_)
{
p_rng_ = new CGAL::Random(0);
delete_rng_ = true;
}
}
/// Destructor
@ -302,6 +340,8 @@ public:
if(bounding_tree_ != 0 && bounding_tree_ != &tree_) {
delete bounding_tree_;
}
if(delete_rng_)
delete p_rng_;
}
/**
@ -595,6 +635,10 @@ private:
mutable Cached_query cached_query;
mutable AABB_primitive_id cached_primitive_id;
//random number generator for Construct_initial_points
CGAL::Random* p_rng_;
bool delete_rng_;
public:
template <typename Query>
@ -611,6 +655,20 @@ public:
return has_cache && (cached_query == Cached_query(q));
}
void set_random_generator(CGAL::Random* p_rng)
{
if(delete_rng_) delete p_rng_;
if(!p_rng_)
{
p_rng_ = new CGAL::Random(0);
delete_rng_ = true;
}
else {
p_rng_ = p_rng;
delete_rng_ = false;
}
}
private:
// Disabled copy constructor & assignment operator
typedef Polyhedral_mesh_domain_3 Self;
@ -623,7 +681,8 @@ private:
template<typename P_, typename IGT_, typename TA, typename Tag, typename E_tag_>
template<typename P_, typename IGT_, typename TA,
typename Tag, typename E_tag_>
template<class OutputIterator>
OutputIterator
Polyhedral_mesh_domain_3<P_,IGT_,TA,Tag,E_tag_>::
@ -638,7 +697,8 @@ Construct_initial_points::operator()(OutputIterator pts,
FT( (bbox.ymin() + bbox.ymax()) / 2),
FT( (bbox.zmin() + bbox.zmax()) / 2) );
Random_points_on_sphere_3<Point_3> random_point(1.);
CGAL::Random& rng = *(r_domain_.p_rng_);
Random_points_on_sphere_3<Point_3> random_point(1., rng);
int i = n;
#ifdef CGAL_MESH_3_VERBOSE
@ -678,7 +738,8 @@ Construct_initial_points::operator()(OutputIterator pts,
}
template<typename P_, typename IGT_, typename TA, typename Tag, typename E_tag_>
template<typename P_, typename IGT_, typename TA,
typename Tag, typename E_tag_>
typename Polyhedral_mesh_domain_3<P_,IGT_,TA,Tag,E_tag_>::Subdomain
Polyhedral_mesh_domain_3<P_,IGT_,TA,Tag,E_tag_>::
Is_in_domain::operator()(const Point_3& p) const

View File

@ -28,11 +28,11 @@
#include <CGAL/Mesh_3/config.h>
#include <CGAL/Random.h>
#include <CGAL/Polyhedral_mesh_domain_3.h>
#include <CGAL/Mesh_domain_with_polyline_features_3.h>
#include <CGAL/Mesh_polyhedron_3.h>
#include <CGAL/Mesh_polyhedron_3.h>
#include <CGAL/Mesh_3/Detect_polylines_in_polyhedra.h>
#include <CGAL/Mesh_3/Polyline_with_context.h>
#include <CGAL/Mesh_3/Detect_features_in_polyhedra.h>
@ -94,11 +94,10 @@ public:
typedef CGAL::Tag_true Has_features;
/// Constructors
Polyhedral_mesh_domain_with_features_3(const Polyhedron& p);
Polyhedral_mesh_domain_with_features_3(const std::string& filename);
template <typename T1, typename T2>
Polyhedral_mesh_domain_with_features_3(const T1& a, const T2& b) : Base(a, b) {}
Polyhedral_mesh_domain_with_features_3(const Polyhedron& p,
CGAL::Random* p_rng = NULL);
Polyhedral_mesh_domain_with_features_3(const std::string& filename,
CGAL::Random* p_rng = NULL);
template <typename T1, typename T2, typename T3>
Polyhedral_mesh_domain_with_features_3(const T1& a, const T2& b, const T3& c)
@ -108,6 +107,8 @@ public:
~Polyhedral_mesh_domain_with_features_3() {}
/// Detect features
void initialize_ts(Polyhedron& p);
void detect_features(FT angle_in_degree, Polyhedron& p);
void detect_features(FT angle_in_degree = FT(60)) { detect_features(angle_in_degree, polyhedron_); }
@ -126,17 +127,20 @@ private:
template < typename GT_, typename P_, typename TA_,
typename Tag_, typename E_tag_>
Polyhedral_mesh_domain_with_features_3<GT_,P_,TA_,Tag_,E_tag_>::
Polyhedral_mesh_domain_with_features_3(const Polyhedron& p)
Polyhedral_mesh_domain_with_features_3(const Polyhedron& p,
CGAL::Random* p_rng)
: Base()
, polyhedron_(p)
{
this->add_primitives(polyhedron_);
this->set_random_generator(p_rng);
}
template < typename GT_, typename P_, typename TA_,
typename Tag_, typename E_tag_>
Polyhedral_mesh_domain_with_features_3<GT_,P_,TA_,Tag_,E_tag_>::
Polyhedral_mesh_domain_with_features_3(const std::string& filename)
Polyhedral_mesh_domain_with_features_3(const std::string& filename,
CGAL::Random* p_rng)
: Base()
, polyhedron_()
{
@ -144,6 +148,32 @@ Polyhedral_mesh_domain_with_features_3(const std::string& filename)
std::ifstream input(filename.c_str());
input >> polyhedron_;
this->add_primitives(polyhedron_);
this->set_random_generator(p_rng);
}
template < typename GT_, typename P_, typename TA_,
typename Tag_, typename E_tag_>
void
Polyhedral_mesh_domain_with_features_3<GT_,P_,TA_,Tag_,E_tag_>::
initialize_ts(Polyhedron& p)
{
std::size_t ts = 0;
for(typename Polyhedron::Vertex_iterator v = p.vertices_begin(),
end = p.vertices_end() ; v != end ; ++v)
{
v->set_time_stamp(ts++);
}
for(typename Polyhedron::Facet_iterator fit = p.facets_begin(),
end = p.facets_end() ; fit != end ; ++fit )
{
fit->set_time_stamp(ts++);
}
for(typename Polyhedron::Halfedge_iterator hit = p.halfedges_begin(),
end = p.halfedges_end() ; hit != end ; ++hit )
{
hit->set_time_stamp(ts++);
}
}
@ -153,6 +183,7 @@ void
Polyhedral_mesh_domain_with_features_3<GT_,P_,TA_,Tag_,E_tag_>::
detect_features(FT angle_in_degree, Polyhedron& p)
{
initialize_ts(p);
// Get sharp features
Mesh_3::detect_features(p,angle_in_degree);

View File

@ -41,6 +41,7 @@ if ( CGAL_FOUND )
create_single_source_cgal_program( "test_meshing_polyhedron_with_features.cpp" )
create_single_source_cgal_program( "test_meshing_unit_tetrahedron.cpp" )
create_single_source_cgal_program( "test_robust_weighted_circumcenter.cpp" )
create_single_source_cgal_program( "test_meshing_determinism.cpp" )
else()

View File

@ -240,11 +240,8 @@ struct Test_c3t3_io {
return false;
}
}
#ifdef WIN32
# ifdef _MSC_VER
# pragma message("Note: The Triangulation_3 facets iterator is not deterministic")
# endif
#else // not WIN32
#if 0
// Note: The Triangulation_3 facets iterator order changes after a reload
for(typename Tr::Finite_facets_iterator
fit1 = t1.finite_facets_begin(),
fit2 = t2.finite_facets_begin(),
@ -329,6 +326,10 @@ struct Test_c3t3_io {
<< c3t3_bis
<< "\n******end******" << std::endl;
assert(stream);
std::ostringstream ss_c3t3, ss_c3t3_bis;
ss_c3t3 << c3t3;
ss_c3t3_bis << c3t3_bis;
assert(ss_c3t3.str() == ss_c3t3_bis.str());
return check_equality(c3t3, c3t3_bis);
}

View File

@ -50,7 +50,10 @@ public:
//-------------------------------------------------------
Image image;
image.read("data/liver.inr.gz");
Mesh_domain domain(image,1e-9);
std::cout << "\tSeed is\t"
<< CGAL::default_random.get_seed() << std::endl;
Mesh_domain domain(image, 1e-9, &CGAL::default_random);
// Set mesh criteria
Facet_criteria facet_criteria(25, 20*image.vx(), 5*image.vx());

View File

@ -0,0 +1,108 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Mesh_triangulation_3.h>
#include <CGAL/Mesh_complex_3_in_triangulation_3.h>
#include <CGAL/Mesh_criteria_3.h>
#include <CGAL/Polyhedral_mesh_domain_with_features_3.h>
#include <CGAL/make_mesh_3.h>
#include <CGAL/lloyd_optimize_mesh_3.h>
#include <CGAL/odt_optimize_mesh_3.h>
#include <CGAL/perturb_mesh_3.h>
#include <CGAL/exude_mesh_3.h>
#include <sstream>
#include <cstring>
// Domain
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Polyhedral_mesh_domain_with_features_3<K> Mesh_domain;
// Triangulation
typedef CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<
Tr,Mesh_domain::Corner_index,Mesh_domain::Curve_segment_index> C3t3;
// Mesh Criteria
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
// To avoid verbose function and named parameters call
using namespace CGAL::parameters;
int main(int argc, char* argv[])
{
// Collect options
std::size_t nb_runs = 2;
unsigned int nb_lloyd = 2;
unsigned int nb_odt = 2;
double perturb_bound = 10.;
double exude_bound = 15.;
// Domain
std::cout << "\tSeed is\t 0" << std::endl;
Mesh_domain domain("data/cube.off");
//no random generator is given, so CGAL::Random(0) is used
// Get sharp features
domain.detect_features();
// Mesh criteria
Mesh_criteria criteria(edge_size = 0.2,
facet_angle = 25,
facet_size = 0.2,
facet_distance = 0.002,
cell_radius_edge_ratio = 3,
cell_size = 0.2);
// iterate
std::vector<std::string> output_c3t3;
output_c3t3.reserve(5 * nb_runs);
for(std::size_t i = 0; i < nb_runs; ++i)
{
std::cout << "------- Iteration " << (i+1) << " -------" << std::endl;
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria,
no_perturb(),
no_exude());
std::ostringstream oss;
c3t3.output_to_medit(oss);
output_c3t3.push_back(oss.str()); //[5*i]
oss.clear();
//LLOYD (1)
CGAL::lloyd_optimize_mesh_3(c3t3, domain, max_iteration_number = nb_lloyd);
c3t3.output_to_medit(oss);
output_c3t3.push_back(oss.str());//[i*5+1]
oss.clear();
//ODT (2)
CGAL::odt_optimize_mesh_3(c3t3, domain, max_iteration_number = nb_odt);
c3t3.output_to_medit(oss);
output_c3t3.push_back(oss.str());//[i*5+2]
oss.clear();
//PERTURB (3)
CGAL::perturb_mesh_3(c3t3, domain, sliver_bound=perturb_bound);
c3t3.output_to_medit(oss);
output_c3t3.push_back(oss.str());//[i*5+3]
oss.clear();
//EXUDE (4)
CGAL::exude_mesh_3(c3t3, sliver_bound=exude_bound);
c3t3.output_to_medit(oss);
output_c3t3.push_back(oss.str());//[i*5+4]
oss.clear();
if(i == 0)
continue;
//else check
for(std::size_t j = 0; j < 5; ++j)
{
if(0 != output_c3t3[5*(i-1)+j].compare(output_c3t3[5*i+j]))
{
std::cerr << "Meshing operation " << j << " is not deterministic.\n";
CGAL_assertion(false);
}
}
}
return 0;
}

View File

@ -57,8 +57,12 @@ struct Implicit_tester : public Tester<K>
//-------------------------------------------------------
// Data generation
//-------------------------------------------------------
std::cout << "\tSeed is\t"
<< CGAL::default_random.get_seed() << std::endl;
Mesh_domain domain(Implicit_tester<K>::sphere_function,
Sphere_3(CGAL::ORIGIN,2.));
Sphere_3(CGAL::ORIGIN,2.),
1e-3,
&CGAL::default_random);
// Set mesh criteria
Facet_criteria facet_criteria(0, 0, 0.3);

View File

@ -52,7 +52,9 @@ struct Polyhedron_tester : public Tester<K>
input >> polyhedron;
input.close();
Mesh_domain domain(polyhedron);
std::cout << "\tSeed is\t"
<< CGAL::default_random.get_seed() << std::endl;
Mesh_domain domain(polyhedron, &CGAL::default_random);
// Set mesh criteria
Facet_criteria facet_criteria(30, 0.2, 0.02);

View File

@ -51,7 +51,9 @@ struct Polyhedron_with_features_tester : public Tester<K>
//-------------------------------------------------------
// Data generation
//-------------------------------------------------------
Mesh_domain domain("data/cube.off");
std::cout << "\tSeed is\t"
<< CGAL::default_random.get_seed() << std::endl;
Mesh_domain domain("data/cube.off", &CGAL::default_random);
domain.detect_features();
// Set mesh criteria

View File

@ -46,7 +46,9 @@ int main(int argc, char** argv)
Point(0, 1, 0),
Point(0, 0, 1));
Mesh_domain domain(p);
std::cout << "\tSeed is\t"
<< CGAL::default_random.get_seed() << std::endl;
Mesh_domain domain(p, &CGAL::default_random);
typedef std::vector<K::Point_3> Polyline;
typedef std::vector<Polyline> Polylines;

View File

@ -8,6 +8,8 @@
// surface mesh
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Polyhedron_items_3.h>
#include <CGAL/Has_timestamp.h>
#include <CGAL/tags.h>
#include <set>
@ -23,6 +25,8 @@ private:
Set_of_indices indices;
std::size_t mID;
std::size_t time_stamp_;
public:
int nb_of_feature_edges;
@ -38,6 +42,18 @@ public:
indices.insert(i);
}
/// For the determinism of Compact_container iterators
///@{
typedef CGAL::Tag_true Has_timestamp;
std::size_t time_stamp() const {
return time_stamp_;
}
void set_time_stamp(const std::size_t& ts) {
time_stamp_ = ts;
}
///}@
const Set_of_indices&
incident_patches_ids_set() const {
return indices;
@ -57,6 +73,8 @@ class Polyhedron_demo_halfedge :
private:
bool feature_edge;
std::size_t mID;
std::size_t time_stamp_;
public:
Polyhedron_demo_halfedge()
@ -74,6 +92,17 @@ public:
std::size_t& id() { return mID; }
std::size_t id() const { return mID; }
/// For the determinism of Compact_container iterators
///@{
typedef CGAL::Tag_true Has_timestamp;
std::size_t time_stamp() const {
return time_stamp_;
}
void set_time_stamp(const std::size_t& ts) {
time_stamp_ = ts;
}
///@}
};
template <class Refs, class T_, class Pln_, class Patch_id_>
@ -83,6 +112,8 @@ class Polyhedron_demo_face :
private:
Patch_id_ patch_id_;
std::size_t mID;
std::size_t time_stamp_;
public:
typedef Patch_id_ Patch_id;
@ -100,6 +131,17 @@ public:
std::size_t& id() { return mID; }
std::size_t id() const { return mID; }
/// For the determinism of Compact_container iterators
///@{
typedef CGAL::Tag_true Has_timestamp;
std::size_t time_stamp() const {
return time_stamp_;
}
void set_time_stamp(const std::size_t& ts) {
time_stamp_ = ts;
}
///@}
};
template <typename Patch_id>

View File

@ -1,4 +1,5 @@
// Copyright (c) 2003,2004,2007-2010 INRIA Sophia-Antipolis (France).
// Copyright (c) 2014 GeometryFactory Sarl (France)
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
@ -30,8 +31,8 @@
#include <CGAL/memory.h>
#include <CGAL/iterator.h>
#include <CGAL/Time_stamper.h>
#include <boost/mpl/if.hpp>
// An STL like container with the following properties :
// - to achieve compactness, it requires access to a pointer stored in T,
@ -163,17 +164,27 @@ namespace internal {
class CC_iterator;
}
template < class T, class Allocator_ = Default, class Increment_policy
=Addition_size_policy<CGAL_INIT_COMPACT_CONTAINER_BLOCK_SIZE,
CGAL_INCREMENT_COMPACT_CONTAINER_BLOCK_SIZE> >
template < class T,
class Allocator_ = Default,
class Increment_policy_ = Default,
class TimeStamper_ = Default >
class Compact_container
{
typedef Allocator_ Al;
typedef Increment_policy Incr_policy;
typedef typename Default::Get< Al, CGAL_ALLOCATOR(T) >::type Allocator;
typedef Compact_container <T, Al, Increment_policy> Self;
typedef Increment_policy_ Ip;
typedef typename Default::Get< Ip,
Addition_size_policy<CGAL_INIT_COMPACT_CONTAINER_BLOCK_SIZE,
CGAL_INCREMENT_COMPACT_CONTAINER_BLOCK_SIZE>
>::type Increment_policy;
typedef TimeStamper_ Ts;
typedef Compact_container <T, Al, Ip, Ts> Self;
typedef Compact_container_traits <T> Traits;
public:
typedef typename Default::Get< TimeStamper_,
CGAL::Time_stamper_impl<T> >::type
Time_stamper_impl;
typedef T value_type;
typedef Allocator allocator_type;
typedef typename Allocator::reference reference;
@ -196,6 +207,7 @@ public:
explicit Compact_container(const Allocator &a = Allocator())
: alloc(a)
, time_stamper(new Time_stamper_impl())
{
init();
}
@ -204,6 +216,7 @@ public:
Compact_container(InputIterator first, InputIterator last,
const Allocator & a = Allocator())
: alloc(a)
, time_stamper(new Time_stamper_impl())
{
init();
std::copy(first, last, CGAL::inserter(*this));
@ -212,9 +225,11 @@ public:
// The copy constructor and assignment operator preserve the iterator order
Compact_container(const Compact_container &c)
: alloc(c.get_allocator())
, time_stamper(new Time_stamper_impl())
{
init();
block_size = c.block_size;
*time_stamper = *c.time_stamper;
std::copy(c.begin(), c.end(), CGAL::inserter(*this));
}
@ -230,6 +245,7 @@ public:
~Compact_container()
{
clear();
delete time_stamper;
}
bool is_used(size_type i) const
@ -274,6 +290,7 @@ public:
std::swap(last_item, c.last_item);
std::swap(free_list, c.free_list);
all_items.swap(c.all_items);
std::swap(time_stamper, c.time_stamper);
}
iterator begin() { return iterator(first_item, 0, 0); }
@ -319,6 +336,7 @@ public:
new (ret) value_type(args...);
CGAL_assertion(type(ret) == USED);
++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0);
}
#else
@ -333,6 +351,7 @@ public:
new (ret) value_type();
CGAL_assertion(type(ret) == USED);
++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0);
}
@ -348,6 +367,7 @@ public:
new (ret) value_type(t1);
CGAL_assertion(type(ret) == USED);
++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0);
}
@ -363,6 +383,7 @@ public:
new (ret) value_type(t1, t2);
CGAL_assertion(type(ret) == USED);
++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0);
}
@ -378,6 +399,7 @@ public:
new (ret) value_type(t1, t2, t3);
CGAL_assertion(type(ret) == USED);
++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0);
}
@ -393,6 +415,7 @@ public:
new (ret) value_type(t1, t2, t3, t4);
CGAL_assertion(type(ret) == USED);
++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0);
}
@ -409,6 +432,7 @@ public:
new (ret) value_type(t1, t2, t3, t4, t5);
CGAL_assertion(type(ret) == USED);
++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0);
}
@ -426,6 +450,7 @@ public:
new (ret) value_type(t1, t2, t3, t4, t5, t6);
CGAL_assertion(type(ret) == USED);
++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0);
}
@ -443,6 +468,7 @@ public:
new (ret) value_type(t1, t2, t3, t4, t5, t6, t7);
CGAL_assertion(type(ret) == USED);
++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0);
}
@ -460,6 +486,7 @@ public:
new (ret) value_type(t1, t2, t3, t4, t5, t6, t7, t8);
CGAL_assertion(type(ret) == USED);
++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0);
}
#endif // CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES
@ -474,6 +501,7 @@ public:
alloc.construct(ret, t);
CGAL_assertion(type(ret) == USED);
++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0);
}
@ -693,13 +721,14 @@ private:
void init()
{
block_size = Incr_policy::first_block_size;
block_size = Increment_policy::first_block_size;
capacity_ = 0;
size_ = 0;
free_list = NULL;
first_item = NULL;
last_item = NULL;
all_items = All_items();
time_stamper->reset();
}
allocator_type alloc;
@ -710,10 +739,14 @@ private:
pointer first_item;
pointer last_item;
All_items all_items;
// This is a pointer, so that the definition of Compact_container does
// not require a complete type `T`.
Time_stamper_impl* time_stamper;
};
template < class T, class Allocator, class Increment_policy >
void Compact_container<T, Allocator, Increment_policy>::merge(Self &d)
template < class T, class Allocator, class Increment_policy, class TimeStamper >
void Compact_container<T, Allocator, Increment_policy, TimeStamper>::merge(Self &d)
{
CGAL_precondition(&d != this);
@ -749,8 +782,8 @@ void Compact_container<T, Allocator, Increment_policy>::merge(Self &d)
d.init();
}
template < class T, class Allocator, class Increment_policy >
void Compact_container<T, Allocator, Increment_policy>::clear()
template < class T, class Allocator, class Increment_policy, class TimeStamper >
void Compact_container<T, Allocator, Increment_policy, TimeStamper>::clear()
{
for (typename All_items::iterator it = all_items.begin(), itend = all_items.end();
it != itend; ++it) {
@ -765,8 +798,8 @@ void Compact_container<T, Allocator, Increment_policy>::clear()
init();
}
template < class T, class Allocator, class Increment_policy >
void Compact_container<T, Allocator, Increment_policy>::allocate_new_block()
template < class T, class Allocator, class Increment_policy, class TimeStamper >
void Compact_container<T, Allocator, Increment_policy, TimeStamper>::allocate_new_block()
{
pointer new_block = alloc.allocate(block_size + 2);
all_items.push_back(std::make_pair(new_block, block_size + 2));
@ -794,52 +827,52 @@ void Compact_container<T, Allocator, Increment_policy>::allocate_new_block()
Increment_policy::increase_size(*this);
}
template < class T, class Allocator, class Increment_policy >
template < class T, class Allocator, class Increment_policy, class TimeStamper >
inline
bool operator==(const Compact_container<T, Allocator, Increment_policy> &lhs,
const Compact_container<T, Allocator, Increment_policy> &rhs)
bool operator==(const Compact_container<T, Allocator, Increment_policy, TimeStamper> &lhs,
const Compact_container<T, Allocator, Increment_policy, TimeStamper> &rhs)
{
return lhs.size() == rhs.size() &&
std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
template < class T, class Allocator, class Increment_policy >
template < class T, class Allocator, class Increment_policy, class TimeStamper >
inline
bool operator!=(const Compact_container<T, Allocator, Increment_policy> &lhs,
const Compact_container<T, Allocator, Increment_policy> &rhs)
bool operator!=(const Compact_container<T, Allocator, Increment_policy, TimeStamper> &lhs,
const Compact_container<T, Allocator, Increment_policy, TimeStamper> &rhs)
{
return ! (lhs == rhs);
}
template < class T, class Allocator, class Increment_policy >
template < class T, class Allocator, class Increment_policy, class TimeStamper >
inline
bool operator< (const Compact_container<T, Allocator, Increment_policy> &lhs,
const Compact_container<T, Allocator, Increment_policy> &rhs)
bool operator< (const Compact_container<T, Allocator, Increment_policy, TimeStamper> &lhs,
const Compact_container<T, Allocator, Increment_policy, TimeStamper> &rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end());
}
template < class T, class Allocator, class Increment_policy >
template < class T, class Allocator, class Increment_policy, class TimeStamper >
inline
bool operator> (const Compact_container<T, Allocator, Increment_policy> &lhs,
const Compact_container<T, Allocator, Increment_policy> &rhs)
bool operator> (const Compact_container<T, Allocator, Increment_policy, TimeStamper> &lhs,
const Compact_container<T, Allocator, Increment_policy, TimeStamper> &rhs)
{
return rhs < lhs;
}
template < class T, class Allocator, class Increment_policy >
template < class T, class Allocator, class Increment_policy, class TimeStamper >
inline
bool operator<=(const Compact_container<T, Allocator, Increment_policy> &lhs,
const Compact_container<T, Allocator, Increment_policy> &rhs)
bool operator<=(const Compact_container<T, Allocator, Increment_policy, TimeStamper> &lhs,
const Compact_container<T, Allocator, Increment_policy, TimeStamper> &rhs)
{
return ! (lhs > rhs);
}
template < class T, class Allocator, class Increment_policy >
template < class T, class Allocator, class Increment_policy, class TimeStamper >
inline
bool operator>=(const Compact_container<T, Allocator, Increment_policy> &lhs,
const Compact_container<T, Allocator, Increment_policy> &rhs)
bool operator>=(const Compact_container<T, Allocator, Increment_policy, TimeStamper> &lhs,
const Compact_container<T, Allocator, Increment_policy, TimeStamper> &rhs)
{
return ! (lhs < rhs);
}
@ -890,14 +923,19 @@ namespace internal {
private:
typedef typename DSC::Time_stamper_impl Time_stamper_impl;
union {
pointer p;
void *vp;
} m_ptr;
// Only Compact_container should access these constructors.
friend class Compact_container<value_type, typename DSC::Al,
typename DSC::Incr_policy>;
friend class Compact_container<value_type,
typename DSC::Al,
typename DSC::Ip,
typename DSC::Ts>;
// For begin()
CC_iterator(pointer ptr, int, int)
@ -991,22 +1029,24 @@ namespace internal {
// For std::less...
bool operator<(const CC_iterator& other) const
{
return (m_ptr.p < other.m_ptr.p);
return Time_stamper_impl::less(m_ptr.p, other.m_ptr.p);
}
bool operator>(const CC_iterator& other) const
{
return (m_ptr.p > other.m_ptr.p);
return Time_stamper_impl::less(other.m_ptr.p, m_ptr.p);
}
bool operator<=(const CC_iterator& other) const
{
return (m_ptr.p <= other.m_ptr.p);
return Time_stamper_impl::less(m_ptr.p, other.m_ptr.p)
|| (*this == other);
}
bool operator>=(const CC_iterator& other) const
{
return (m_ptr.p >= other.m_ptr.p);
return Time_stamper_impl::less(other.m_ptr.p, m_ptr.p)
|| (*this == other);
}
// Can itself be used for bit-squatting.

View File

@ -0,0 +1,49 @@
// Copyright (c) 2014 GeometryFactory Sarl (France)
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
//
//
// Author(s) : Jane Tournois
#ifndef CGAL_HAS_TIMESTAMP_H
#define CGAL_HAS_TIMESTAMP_H
#include <boost/mpl/has_xxx.hpp>
#include <CGAL/tags.h>
namespace CGAL {
namespace internal {
BOOST_MPL_HAS_XXX_TRAIT_DEF(Has_timestamp)
// Used by Compact container to make the comparison of iterator
// depending on the insertion order rather than the object address
// when the object class defines a Has_timestamp tag
// This is for example used in to make Mesh_3 deterministic, see
// classes implementing concepts MeshCellBase_3 and MeshVertexBase_3
template <typename T, bool has_ts = has_Has_timestamp<T>::value>
struct Has_timestamp : public T::Has_timestamp
// when T has a Has_timestamp tag
{};
template <typename T>
struct Has_timestamp<T, false> : public Tag_false
// when T does not have a Has_timestamp tag
{};
} // end namespace internal
} // end namespace CGAL
#endif // CGAL_HAS_TIMESTAMP_H

View File

@ -33,6 +33,7 @@
#include <functional>
#include <algorithm>
#include <CGAL/memory.h>
#include <CGAL/Time_stamper.h>
namespace CGAL {
@ -87,10 +88,10 @@ namespace internal {
bool operator==( const Self& x) const { return node == x.node; }
bool operator!=( const Self& x) const { return node != x.node; }
bool operator< ( const Self& x) const { return node< x.node; }
bool operator<=( const Self& x) const { return node<= x.node; }
bool operator> ( const Self& x) const { return node> x.node; }
bool operator>=( const Self& x) const { return node>= x.node; }
bool operator< ( const Self& x) const { return Get_time_stamper<T>::type::less(node, x.node); }
bool operator<=( const Self& x) const { return Get_time_stamper<T>::type::less(node, x.node) || node==x.node; }
bool operator> ( const Self& x) const { return Get_time_stamper<T>::type::less(x.node, node); }
bool operator>=( const Self& x) const { return Get_time_stamper<T>::type::less(x.node, node) || node==x.node; }
T& operator*() const { return *node; }
T* operator->() const { return node; }
Self& operator++() {
@ -138,12 +139,12 @@ namespace internal {
In_place_list_const_iterator( Iterator i) : node(&*i) {}
In_place_list_const_iterator(const T* x) : node(x) {}
bool operator==( const Self& x) const { return node == x.node; }
bool operator!=( const Self& x) const { return node != x.node; }
bool operator< ( const Self& x) const { return node< x.node; }
bool operator<=( const Self& x) const { return node<= x.node; }
bool operator> ( const Self& x) const { return node> x.node; }
bool operator>=( const Self& x) const { return node>= x.node; }
bool operator==( const Self& x) const { return node == x.node; }
bool operator!=( const Self& x) const { return node != x.node; }
bool operator< ( const Self& x) const { return Get_time_stamper<T>::type::less(node, x.node); }
bool operator<=( const Self& x) const { return Get_time_stamper<T>::type::less(node, x.node) || node==x.node; }
bool operator> ( const Self& x) const { return Get_time_stamper<T>::type::less(x.node, node); }
bool operator>=( const Self& x) const { return Get_time_stamper<T>::type::less(x.node, node) || node==x.node; }
const T& operator*() const { return *node; }
const T* operator->() const { return node; }
Self& operator++() {
@ -233,6 +234,7 @@ protected:
pointer node;
size_type length;
Time_stamper_impl<T>* time_stamper_ptr;
// These are the only places where the allocator gets called.
pointer get_node() {
pointer p = allocator.allocate(1);
@ -265,8 +267,10 @@ public:
// CREATION
//
// New creation variable is: `l'
explicit In_place_list() : length(0) {
explicit In_place_list()
: length(0)
, time_stamper_ptr(new Time_stamper_impl<T>())
{
// introduces an empty list.
node = get_node();
(*node).next_link = node;
@ -314,6 +318,7 @@ public:
(*((*position.node).prev_link)).next_link = &x;
(*position.node).prev_link = &x;
++length;
time_stamper_ptr->set_time_stamp(&x);
return &x;
}
iterator insert(T* pos, T& x) {
@ -385,11 +390,17 @@ public:
erase( iterator(first), iterator(last));
}
void clear() { erase( begin(), end()); }
void clear() {
erase( begin(), end());
time_stamper_ptr->reset();
}
// CREATION (Continued)
explicit In_place_list(size_type n, const T& value = T()) : length(0) {
explicit In_place_list(size_type n, const T& value = T())
: length(0)
, time_stamper_ptr(new Time_stamper_impl<T>())
{
// introduces a list with n items, all initialized with copies of
// value.
node = get_node();
@ -399,7 +410,10 @@ public:
}
template <class InputIterator>
In_place_list( InputIterator first, InputIterator last) : length(0) {
In_place_list( InputIterator first, InputIterator last)
: length(0)
, time_stamper_ptr(new Time_stamper_impl<T>())
{
// a list with copies from the range [`first,last').
node = get_node();
(*node).next_link = node;
@ -407,14 +421,21 @@ public:
insert( begin(), first, last);
}
In_place_list(const T* first, const T* last) : length(0) {
In_place_list(const T* first, const T* last)
: length(0)
, time_stamper_ptr(new Time_stamper_impl<T>())
{
// a list with copies from the range [`first,last').
node = get_node();
(*node).next_link = node;
(*node).prev_link = node;
insert(begin(), first, last);
}
In_place_list(const Self& x) : length(0) {
In_place_list(const Self& x)
: length(0)
, time_stamper_ptr(new Time_stamper_impl<T>())
{
// copy constructor. Each item in `l1' is copied.
node = get_node();
(*node).next_link = node;
@ -424,6 +445,7 @@ public:
~In_place_list() {
erase(begin(), end());
put_node(node);
delete time_stamper_ptr;
}
Self& operator=(const Self& x);
@ -486,6 +508,8 @@ protected:
public:
void splice(iterator position, Self& x) {
// make sure splice is not called if time stamps are used
CGAL_static_assertion( !internal::Has_timestamp<T>::value );
// inserts the list x before position `pos' and x becomes empty.
// It takes constant time. Precondition: `&l != &x'.
if (!x.empty()) {
@ -498,6 +522,8 @@ public:
splice( iterator(position), x);
}
void splice( iterator position, Self& x, iterator i) {
// make sure splice is not called if time stamps are used
CGAL_static_assertion( !internal::Has_timestamp<T>::value );
// inserts an element pointed to by i from list x before position
// `pos' and removes the element from x. It takes constant time. i
// is a valid dereferenceable iterator of x. The result is
@ -512,6 +538,8 @@ public:
splice( iterator(position), x, iterator(i));
}
void splice(iterator pos, Self& x, iterator first, iterator last) {
// make sure splice is not called if time stamps are used
CGAL_static_assertion( !internal::Has_timestamp<T>::value );
// inserts elements in the range [`first, last') before position
// `pos' and removes the elements from x. It takes constant time
// if `&x == $l'; otherwise, it takes linear time. [`first,

View File

@ -0,0 +1,90 @@
// Copyright (c) 2014 GeometryFactory Sarl (France)
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
//
//
// Author(s) : Jane Tournois
#include <CGAL/Has_timestamp.h>
#ifndef CGAL_TIME_STAMPER_H
#define CGAL_TIME_STAMPER_H
namespace CGAL {
template <typename T>
struct Time_stamper
{
Time_stamper()
: time_stamp_(0) {}
Time_stamper(const Time_stamper& ts)
: time_stamp_(ts.time_stamp_) {}
void set_time_stamp(T* pt) {
pt->set_time_stamp(time_stamp_++);
}
static bool less(T* p_t1, T* p_t2) {
if(p_t1 == NULL) return (p_t2 != NULL);
else if(p_t2 == NULL) return false;
else return p_t1->time_stamp() < p_t2->time_stamp();
}
void reset() {
time_stamp_ = 0;
}
private:
std::size_t time_stamp_;
}; // end class template Time_stamper<T>
template <typename T>
struct No_time_stamp
{
public:
void set_time_stamp(T*) {}
static bool less(T* p_t1, T* p_t2) {
return p_t1 < p_t2;
}
void reset() {}
}; // end class template No_time_stamp<T>
// That class template is an auxiliary class. It has a
// specialization for the case where `T::Has_timestamp` does not exists.
// The non-specialized template, when `T::Has_timestamp` exists, derives
// from `Time_stamper<T>` or `No_time_stamp<T>` depending on the
// value of the Boolean constant `T::Has_timestamp`.
// The declaration of that class template requires `T` to be a complete type.
template <class T, bool has_timestamp = internal::Has_timestamp<T>::value>
struct Get_time_stamper{
typedef Time_stamper<T> type;
};
// Specialization when `T::Has_timestamp` does not exist, derives from
// `TimeStamper_`, or from `No_time_stamp<T>`.
template <class T>
struct Get_time_stamper<T,false>{
typedef No_time_stamp<T> type;
};
// Implementation of the timestamp policy. It is very important that the
// declaration of that class template does not require `T` to be a complete
// type. That way, the declaration of a pointer of type `Time_stamper_impl<T, Ts>
// in `Compact_container` for example is possible with an incomplete type.
template <class T>
struct Time_stamper_impl : public Get_time_stamper<T>::type {};
} //end of namespace CGAL
#endif // CGAL_TIME_STAMPER_H

View File

@ -9,15 +9,32 @@
#include <CGAL/Random.h>
#include <CGAL/Testsuite/use.h>
#include <CGAL/tags.h>
#include <CGAL/use.h>
#include <CGAL/assertions.h>
#include <boost/type_traits/is_base_of.hpp>
template <typename Has_timestamp_ = CGAL::Tag_true>
struct Node_1
: public CGAL::Compact_container_base
{
bool operator==(const Node_1 &) const { return true; }
bool operator!=(const Node_1 &) const { return false; }
bool operator< (const Node_1 &) const { return false; }
/// For the determinism of Compact_container iterators
///@{
typedef Has_timestamp_ Has_timestamp;
std::size_t time_stamp() const {
return time_stamp_;
}
void set_time_stamp(const std::size_t& ts) {
time_stamp_ = ts;
}
///@}
std::size_t time_stamp_;
};
class Node_2
@ -241,19 +258,62 @@ void test_index(const Cont &C)
}
}
struct Incomplete_struct;
int main()
{
CGAL::Compact_container<Node_1> C1;
CGAL::Compact_container<Node_2> C2;
test(C1);
test(C2);
CGAL::Compact_container<Node_2, CGAL::Default, CGAL::Constant_size_policy<1024> > C3;
CGAL::Compact_container<Node_2, CGAL::Default, CGAL::Addition_size_policy<14,16> > C4;
typedef Node_1<CGAL::Tag_true > T1;
typedef CGAL::Compact_container<T1> C1; // with timestamps
test_index(C3);
test_index(C4);
typedef Node_1<CGAL::Tag_false> T2;
typedef CGAL::Compact_container<T2> C2; // without timestamps
typedef CGAL::Compact_container<T2,
CGAL::Default,
CGAL::Default,
CGAL::Time_stamper<T2> > C4;
// with timestamps
typedef Node_2 T3;
typedef CGAL::Compact_container<T3> C3; // without timestamps
C1 c1; test(c1);
C2 c2; test(c2);
C3 c3; test(c3);
C4 c4; test(c4);
// Check the time stamper policies
if(! boost::is_base_of<CGAL::Time_stamper<T1>,
C1::Time_stamper_impl>::value)
{
std::cerr << "Error timestamper of C1\n"; return 1;
}
if(! boost::is_base_of<CGAL::No_time_stamp<T2>,
C2::Time_stamper_impl>::value)
{
std::cerr << "Error timestamper of C2\n"; return 1;
}
if(! boost::is_base_of<CGAL::No_time_stamp<T3>,
C3::Time_stamper_impl>::value)
{
std::cerr << "Error timestamper of C3\n"; return 1;
}
if(! boost::is_base_of<CGAL::Time_stamper<T2>,
C4::Time_stamper_impl>::value)
{
std::cerr << "Error timestamper of C4\n"; return 1;
}
// Check that Compact_container does not require a complete type.
CGAL_static_assertion(sizeof(CGAL::Compact_container<Incomplete_struct>) > 0);
// Test increment policy
CGAL::Compact_container<Node_2, CGAL::Default, CGAL::Constant_size_policy<1024> > C5;
CGAL::Compact_container<Node_2, CGAL::Default, CGAL::Addition_size_policy<14,16> > C6;
test_index(C5);
test_index(C6);
return 0;
}
// EOF //

View File

@ -3300,11 +3300,11 @@ void
Triangulation_3<Gt,Tds>::
make_canonical(Vertex_triple& t) const
{
int i = (&*(t.first) < &*(t.second))? 0 : 1;
int i = (t.first < t.second) ? 0 : 1;
if(i==0) {
i = (&*(t.first) < &*(t.third))? 0 : 2;
i = (t.first < t.third) ? 0 : 2;
} else {
i = (&*(t.second) < &*(t.third))? 1 : 2;
i = (t.second < t.third) ? 1 : 2;
}
Vertex_handle tmp;
switch(i){