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/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Mesh_triangulation_3.h> #include <CGAL/Mesh_triangulation_3.h>

View File

@ -31,7 +31,8 @@ FT sphere_function (const Point& p)
int main() int main()
{ {
// Domain (Warning: Sphere_3 constructor uses squared radius !) // 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
Mesh_criteria criteria(facet_angle=30, facet_size=0.1, facet_distance=0.025, 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() int main()
{ {
// Domain (Warning: Sphere_3 constructor uses squared radius !) // 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
Spherical_sizing_field size; Spherical_sizing_field size;

View File

@ -53,7 +53,8 @@ FT sphere_function (const Point& p)
int main() int main()
{ {
// Domain (Warning: Sphere_3 constructor uses squared radius !) // 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
Mesh_criteria criteria(edge_size = 0.15, Mesh_criteria criteria(edge_size = 0.15,

View File

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

View File

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

View File

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

View File

@ -55,8 +55,8 @@ public:
typedef typename Polyhedron::Facet Facet; typedef typename Polyhedron::Facet Facet;
typedef typename Facet::Patch_id Patch_id; typedef typename Facet::Patch_id Patch_id;
typedef std::set<Facet*> Facet_handle_set; typedef std::set<Facet_handle> Facet_handle_set;
typedef std::set<Halfedge*> He_handle_set; typedef std::set<Halfedge_handle> He_handle_set;
public: public:
Detect_features_in_polyhedra() : current_surface_index_(1) {} Detect_features_in_polyhedra() : current_surface_index_(1) {}
@ -69,7 +69,7 @@ public:
private: private:
Vector_3 facet_normal(const Facet_handle& f) const; Vector_3 facet_normal(const Facet_handle& f) const;
bool is_sharp(const Halfedge_handle& he, FT cos_angle) 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; Facet_handle_set& unsorted_faces) const;
template <typename Int> template <typename Int>
@ -143,18 +143,19 @@ detect_surface_patches(Polyhedron& polyhedron)
for ( typename Polyhedron::Facet_iterator fit = polyhedron.facets_begin(), for ( typename Polyhedron::Facet_iterator fit = polyhedron.facets_begin(),
end = polyhedron.facets_end() ; fit != end ; ++fit ) end = polyhedron.facets_end() ; fit != end ; ++fit )
{ {
unsorted_faces.insert(&*fit); Facet_handle fh = fit;
unsorted_faces.insert(fh);
} }
// Flood // Flood
while ( ! unsorted_faces.empty() ) while ( ! unsorted_faces.empty() )
{ {
Facet& f = **(unsorted_faces.begin()); Facet_handle f = *(unsorted_faces.begin());
unsorted_faces.erase(unsorted_faces.begin()); unsorted_faces.erase(unsorted_faces.begin());
const Patch_id patch_id = generate_patch_id(Patch_id(), const Patch_id patch_id = generate_patch_id(Patch_id(),
current_surface_index_); current_surface_index_);
f.set_patch_id(patch_id); f->set_patch_id(patch_id);
flood(f,patch_id,unsorted_faces); flood(f,patch_id,unsorted_faces);
++current_surface_index_; ++current_surface_index_;
} }
@ -245,52 +246,52 @@ is_sharp(const Halfedge_handle& he, FT cos_angle) const
template <typename P_> template <typename P_>
void void
Detect_features_in_polyhedra<P_>:: 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; 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; Facet_he_circ done = begin;
// Initialize he_to_explore with halfedges of the starting facet // Initialize he_to_explore with halfedges of the starting facet
He_handle_set he_to_explore; He_handle_set he_to_explore;
CGAL_For_all(begin,done) CGAL_For_all(begin,done)
{ {
he_to_explore.insert(&*(begin->opposite())); he_to_explore.insert(begin->opposite());
} }
// While there is something to explore // While there is something to explore
while ( ! he_to_explore.empty() ) while ( ! he_to_explore.empty() )
{ {
// Get next halfedge to explore // 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()); he_to_explore.erase(he_to_explore.begin());
// If we don't go through a border of the patch // 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 // Mark facet and delete it from unsorted
explored_facet.set_patch_id(patch_id); explored_facet->set_patch_id(patch_id);
unsorted_faces.erase(&explored_facet); unsorted_faces.erase(explored_facet);
// Add/Remove facet's halfedge to/from explore list // 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; Facet_he_circ he_done = he_begin;
CGAL_For_all(he_begin,he_done) CGAL_For_all(he_begin,he_done)
{ {
Halfedge& current_he = *he_begin; Halfedge_handle current_he = he_begin;
// do not explore heh again // 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 // 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) // (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 #define CGAL_MESH_3_DETECT_POLYLINES_IN_POLYHEDRA_H
#include <CGAL/Mesh_3/Detect_polylines_in_polyhedra_fwd.h> #include <CGAL/Mesh_3/Detect_polylines_in_polyhedra_fwd.h>
#include <CGAL/Has_timestamp.h>
#include <CGAL/Default.h>
#include <algorithm> #include <algorithm>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/mpl/if.hpp>
namespace CGAL { namespace Mesh_3 { namespace CGAL { namespace Mesh_3 {
struct Detect_polyline_less { template <typename Handle>
template <typename Handle> struct CGAL_with_time_stamp
bool operator()(const Handle& va, const Handle& vb) const { {
return &*va < &*vb; 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 <boost/optional.hpp>
#include <CGAL/tuple.h> #include <CGAL/tuple.h>
#include <CGAL/Origin.h> #include <CGAL/Origin.h>
#include <CGAL/Random.h>
namespace CGAL { namespace CGAL {
@ -55,7 +56,8 @@ namespace Mesh_3 {
* tags of it's incident subdomain. * tags of it's incident subdomain.
* Thus, a boundary facet of the domain is labelled <0,b>, where b!=0. * 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 class Labeled_mesh_domain_3
{ {
public: public:
@ -94,14 +96,20 @@ public:
*/ */
Labeled_mesh_domain_3(const Function& f, Labeled_mesh_domain_3(const Function& f,
const Sphere_3& bounding_sphere, 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, Labeled_mesh_domain_3(const Function& f,
const Bbox_3& bbox, const Bbox_3& bbox,
const FT& error_bound = FT(1e-3)); const FT& error_bound = FT(1e-3),
CGAL::Random* p_rng = NULL);
/// Destructor /// 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 * Constructs a set of \ccc{n} points on the surface, and output them to
@ -461,6 +469,9 @@ private:
const Function function_; const Function function_;
/// The bounding box /// The bounding box
const Iso_cuboid_3 bbox_; 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 /// Error bound relative to sphere radius
FT squared_error_bound_; FT squared_error_bound_;
@ -483,24 +494,40 @@ template<class F, class BGT>
Labeled_mesh_domain_3<F,BGT>::Labeled_mesh_domain_3( Labeled_mesh_domain_3<F,BGT>::Labeled_mesh_domain_3(
const F& f, const F& f,
const Sphere_3& bounding_sphere, const Sphere_3& bounding_sphere,
const FT& error_bound ) const FT& error_bound,
CGAL::Random* p_rng)
: function_(f) : function_(f)
, bbox_(iso_cuboid(bounding_sphere.bbox())) , bbox_(iso_cuboid(bounding_sphere.bbox()))
, p_rng_(p_rng)
, delete_rng_(false)
, squared_error_bound_(squared_error_bound(bounding_sphere,error_bound)) , squared_error_bound_(squared_error_bound(bounding_sphere,error_bound))
{ {
// TODO : CGAL_ASSERT(0 < f(bounding_sphere.get_center()) ) ? // 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> template<class F, class BGT>
Labeled_mesh_domain_3<F,BGT>::Labeled_mesh_domain_3( Labeled_mesh_domain_3<F,BGT>::Labeled_mesh_domain_3(
const F& f, const F& f,
const Bbox_3& bbox, const Bbox_3& bbox,
const FT& error_bound ) const FT& error_bound,
CGAL::Random* p_rng)
: function_(f) : function_(f)
, bbox_(iso_cuboid(bbox)) , bbox_(iso_cuboid(bbox))
, p_rng_(p_rng)
, delete_rng_(false)
, squared_error_bound_(squared_error_bound(bbox_,error_bound)) , squared_error_bound_(squared_error_bound(bbox_,error_bound))
{ {
// TODO : CGAL_ASSERT(0 < f(bounding_sphere.get_center()) ) ? // 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)); const double radius = std::sqrt(CGAL::to_double(squared_radius));
Random_points_on_sphere_3 random_point_on_sphere(radius); CGAL::Random& rng = *(r_domain_.p_rng_);
Random_points_in_sphere_3 random_point_in_sphere(radius); 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 // Get some functors
typename BGT::Construct_segment_3 segment_3 = typename BGT::Construct_segment_3 segment_3 =

View File

@ -231,7 +231,7 @@ public:
Index index(const Vertex_handle& v) const { return v->index(); } Index index(const Vertex_handle& v) const { return v->index(); }
/// Outputs the mesh to medit /// Outputs the mesh to medit
void output_to_medit(std::ofstream& os, void output_to_medit(std::ostream& os,
bool rebind = true, bool rebind = true,
bool show_patches = false) const 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: " std::cerr << "Number of to-be-inserted balls is: "
<< n << "\n between points (" << n << "\n between points ("
<< vp->point() << ") and (" << vq->point() << vp->point() << ") and (" << vq->point()
<< ") (geodesic distance: "
<< domain_.geodesic_distance(vp->point(), vq->point(),
curve_index)
<< ")\n"; << ")\n";
#endif #endif
const Bare_point new_point = const Bare_point new_point =

View File

@ -46,6 +46,7 @@
#include <CGAL/Timer.h> #include <CGAL/Timer.h>
#include <CGAL/Mesh_3/Null_perturber_visitor.h> #include <CGAL/Mesh_3/Null_perturber_visitor.h>
#include <CGAL/Mesh_3/sliver_criteria.h> #include <CGAL/Mesh_3/sliver_criteria.h>
#include <CGAL/Has_timestamp.h>
#include <boost/format.hpp> #include <boost/format.hpp>
#ifdef CGAL_MESH_3_USE_RELAXED_HEAP #ifdef CGAL_MESH_3_USE_RELAXED_HEAP
@ -61,6 +62,29 @@
namespace CGAL { 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 { namespace Mesh_3 {
template < typename C3T3, template < typename C3T3,
@ -250,14 +274,6 @@ public:
private: private:
struct VHash
{
std::size_t operator()(Vertex_handle vh) const
{
return boost::hash_value(&*vh);
}
};
// ----------------------------------- // -----------------------------------
// Private methods // Private methods
// ----------------------------------- // -----------------------------------
@ -651,7 +667,12 @@ build_priority_queue(const FT& sliver_bound, PQueue& pqueue) const
int pqueue_size = 0; 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; M vpm;
for ( typename Tr::Finite_cells_iterator cit = tr_.finite_cells_begin(); for ( typename Tr::Finite_cells_iterator cit = tr_.finite_cells_begin();
cit != tr_.finite_cells_end() ; cit != tr_.finite_cells_end() ;

View File

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

View File

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

View File

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

View File

@ -30,9 +30,10 @@
#define CGAL_COMPACT_MESH_VERTEX_BASE_3_H #define CGAL_COMPACT_MESH_VERTEX_BASE_3_H
#include <CGAL/Triangulation_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/internal/Mesh_3/get_index.h>
#include <CGAL/Mesh_3/io_signature.h> #include <CGAL/Mesh_3/io_signature.h>
#include <CGAL/Has_timestamp.h>
#include <CGAL/tags.h>
namespace CGAL { namespace CGAL {
@ -74,6 +75,7 @@ public:
, next_intrusive_() , next_intrusive_()
, previous_intrusive_() , previous_intrusive_()
#endif //CGAL_INTRUSIVE_LIST #endif //CGAL_INTRUSIVE_LIST
, time_stamp_(-1)
{} {}
// Default copy constructor and assignment operator are ok // Default copy constructor and assignment operator are ok
@ -124,6 +126,18 @@ public:
} }
#endif #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 { bool is_c2t3_cache_valid() const {
return cache_validity; return cache_validity;
} }
@ -179,12 +193,9 @@ private:
Vertex_handle next_intrusive_; Vertex_handle next_intrusive_;
Vertex_handle previous_intrusive_; Vertex_handle previous_intrusive_;
#endif #endif
}; // end class Mesh_vertex_base_3 std::size_t time_stamp_;
namespace internal { }; // end class Mesh_vertex_base_3
namespace Mesh_3 {
} // end namespace internal::Mesh_3
} // end namespace internal
template<class GT, template<class GT,
class MD, class MD,

View File

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

View File

@ -28,11 +28,11 @@
#include <CGAL/Mesh_3/config.h> #include <CGAL/Mesh_3/config.h>
#include <CGAL/Random.h>
#include <CGAL/Polyhedral_mesh_domain_3.h> #include <CGAL/Polyhedral_mesh_domain_3.h>
#include <CGAL/Mesh_domain_with_polyline_features_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_polyhedron_3.h>
#include <CGAL/Mesh_3/Detect_polylines_in_polyhedra.h> #include <CGAL/Mesh_3/Detect_polylines_in_polyhedra.h>
#include <CGAL/Mesh_3/Polyline_with_context.h> #include <CGAL/Mesh_3/Polyline_with_context.h>
#include <CGAL/Mesh_3/Detect_features_in_polyhedra.h> #include <CGAL/Mesh_3/Detect_features_in_polyhedra.h>
@ -94,11 +94,10 @@ public:
typedef CGAL::Tag_true Has_features; typedef CGAL::Tag_true Has_features;
/// Constructors /// Constructors
Polyhedral_mesh_domain_with_features_3(const Polyhedron& p); Polyhedral_mesh_domain_with_features_3(const Polyhedron& p,
Polyhedral_mesh_domain_with_features_3(const std::string& filename); CGAL::Random* p_rng = NULL);
Polyhedral_mesh_domain_with_features_3(const std::string& filename,
template <typename T1, typename T2> CGAL::Random* p_rng = NULL);
Polyhedral_mesh_domain_with_features_3(const T1& a, const T2& b) : Base(a, b) {}
template <typename T1, typename T2, typename T3> template <typename T1, typename T2, typename T3>
Polyhedral_mesh_domain_with_features_3(const T1& a, const T2& b, const T3& c) 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() {} ~Polyhedral_mesh_domain_with_features_3() {}
/// Detect features /// Detect features
void initialize_ts(Polyhedron& p);
void detect_features(FT angle_in_degree, 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_); } 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_, template < typename GT_, typename P_, typename TA_,
typename Tag_, typename E_tag_> typename Tag_, typename E_tag_>
Polyhedral_mesh_domain_with_features_3<GT_,P_,TA_,Tag_,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() : Base()
, polyhedron_(p) , polyhedron_(p)
{ {
this->add_primitives(polyhedron_); this->add_primitives(polyhedron_);
this->set_random_generator(p_rng);
} }
template < typename GT_, typename P_, typename TA_, template < typename GT_, typename P_, typename TA_,
typename Tag_, typename E_tag_> typename Tag_, typename E_tag_>
Polyhedral_mesh_domain_with_features_3<GT_,P_,TA_,Tag_,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() : Base()
, polyhedron_() , polyhedron_()
{ {
@ -144,6 +148,32 @@ Polyhedral_mesh_domain_with_features_3(const std::string& filename)
std::ifstream input(filename.c_str()); std::ifstream input(filename.c_str());
input >> polyhedron_; input >> polyhedron_;
this->add_primitives(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_>:: Polyhedral_mesh_domain_with_features_3<GT_,P_,TA_,Tag_,E_tag_>::
detect_features(FT angle_in_degree, Polyhedron& p) detect_features(FT angle_in_degree, Polyhedron& p)
{ {
initialize_ts(p);
// Get sharp features // Get sharp features
Mesh_3::detect_features(p,angle_in_degree); 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_polyhedron_with_features.cpp" )
create_single_source_cgal_program( "test_meshing_unit_tetrahedron.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_robust_weighted_circumcenter.cpp" )
create_single_source_cgal_program( "test_meshing_determinism.cpp" )
else() else()

View File

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

View File

@ -50,7 +50,10 @@ public:
//------------------------------------------------------- //-------------------------------------------------------
Image image; Image image;
image.read("data/liver.inr.gz"); 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 // Set mesh criteria
Facet_criteria facet_criteria(25, 20*image.vx(), 5*image.vx()); 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 // Data generation
//------------------------------------------------------- //-------------------------------------------------------
std::cout << "\tSeed is\t"
<< CGAL::default_random.get_seed() << std::endl;
Mesh_domain domain(Implicit_tester<K>::sphere_function, 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 // Set mesh criteria
Facet_criteria facet_criteria(0, 0, 0.3); Facet_criteria facet_criteria(0, 0, 0.3);

View File

@ -52,7 +52,9 @@ struct Polyhedron_tester : public Tester<K>
input >> polyhedron; input >> polyhedron;
input.close(); 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 // Set mesh criteria
Facet_criteria facet_criteria(30, 0.2, 0.02); 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 // 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(); domain.detect_features();
// Set mesh criteria // Set mesh criteria

View File

@ -46,7 +46,9 @@ int main(int argc, char** argv)
Point(0, 1, 0), Point(0, 1, 0),
Point(0, 0, 1)); 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<K::Point_3> Polyline;
typedef std::vector<Polyline> Polylines; typedef std::vector<Polyline> Polylines;

View File

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

View File

@ -1,4 +1,5 @@
// Copyright (c) 2003,2004,2007-2010 INRIA Sophia-Antipolis (France). // Copyright (c) 2003,2004,2007-2010 INRIA Sophia-Antipolis (France).
// Copyright (c) 2014 GeometryFactory Sarl (France)
// All rights reserved. // All rights reserved.
// //
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or // 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/memory.h>
#include <CGAL/iterator.h> #include <CGAL/iterator.h>
#include <CGAL/Time_stamper.h>
#include <boost/mpl/if.hpp>
// An STL like container with the following properties : // An STL like container with the following properties :
// - to achieve compactness, it requires access to a pointer stored in T, // - to achieve compactness, it requires access to a pointer stored in T,
@ -163,17 +164,27 @@ namespace internal {
class CC_iterator; class CC_iterator;
} }
template < class T, class Allocator_ = Default, class Increment_policy template < class T,
=Addition_size_policy<CGAL_INIT_COMPACT_CONTAINER_BLOCK_SIZE, class Allocator_ = Default,
CGAL_INCREMENT_COMPACT_CONTAINER_BLOCK_SIZE> > class Increment_policy_ = Default,
class TimeStamper_ = Default >
class Compact_container class Compact_container
{ {
typedef Allocator_ Al; typedef Allocator_ Al;
typedef Increment_policy Incr_policy;
typedef typename Default::Get< Al, CGAL_ALLOCATOR(T) >::type Allocator; 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; typedef Compact_container_traits <T> Traits;
public: public:
typedef typename Default::Get< TimeStamper_,
CGAL::Time_stamper_impl<T> >::type
Time_stamper_impl;
typedef T value_type; typedef T value_type;
typedef Allocator allocator_type; typedef Allocator allocator_type;
typedef typename Allocator::reference reference; typedef typename Allocator::reference reference;
@ -196,6 +207,7 @@ public:
explicit Compact_container(const Allocator &a = Allocator()) explicit Compact_container(const Allocator &a = Allocator())
: alloc(a) : alloc(a)
, time_stamper(new Time_stamper_impl())
{ {
init(); init();
} }
@ -204,6 +216,7 @@ public:
Compact_container(InputIterator first, InputIterator last, Compact_container(InputIterator first, InputIterator last,
const Allocator & a = Allocator()) const Allocator & a = Allocator())
: alloc(a) : alloc(a)
, time_stamper(new Time_stamper_impl())
{ {
init(); init();
std::copy(first, last, CGAL::inserter(*this)); std::copy(first, last, CGAL::inserter(*this));
@ -212,9 +225,11 @@ public:
// The copy constructor and assignment operator preserve the iterator order // The copy constructor and assignment operator preserve the iterator order
Compact_container(const Compact_container &c) Compact_container(const Compact_container &c)
: alloc(c.get_allocator()) : alloc(c.get_allocator())
, time_stamper(new Time_stamper_impl())
{ {
init(); init();
block_size = c.block_size; block_size = c.block_size;
*time_stamper = *c.time_stamper;
std::copy(c.begin(), c.end(), CGAL::inserter(*this)); std::copy(c.begin(), c.end(), CGAL::inserter(*this));
} }
@ -230,6 +245,7 @@ public:
~Compact_container() ~Compact_container()
{ {
clear(); clear();
delete time_stamper;
} }
bool is_used(size_type i) const bool is_used(size_type i) const
@ -274,6 +290,7 @@ public:
std::swap(last_item, c.last_item); std::swap(last_item, c.last_item);
std::swap(free_list, c.free_list); std::swap(free_list, c.free_list);
all_items.swap(c.all_items); all_items.swap(c.all_items);
std::swap(time_stamper, c.time_stamper);
} }
iterator begin() { return iterator(first_item, 0, 0); } iterator begin() { return iterator(first_item, 0, 0); }
@ -319,6 +336,7 @@ public:
new (ret) value_type(args...); new (ret) value_type(args...);
CGAL_assertion(type(ret) == USED); CGAL_assertion(type(ret) == USED);
++size_; ++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0); return iterator(ret, 0);
} }
#else #else
@ -333,6 +351,7 @@ public:
new (ret) value_type(); new (ret) value_type();
CGAL_assertion(type(ret) == USED); CGAL_assertion(type(ret) == USED);
++size_; ++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0); return iterator(ret, 0);
} }
@ -348,6 +367,7 @@ public:
new (ret) value_type(t1); new (ret) value_type(t1);
CGAL_assertion(type(ret) == USED); CGAL_assertion(type(ret) == USED);
++size_; ++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0); return iterator(ret, 0);
} }
@ -363,6 +383,7 @@ public:
new (ret) value_type(t1, t2); new (ret) value_type(t1, t2);
CGAL_assertion(type(ret) == USED); CGAL_assertion(type(ret) == USED);
++size_; ++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0); return iterator(ret, 0);
} }
@ -378,6 +399,7 @@ public:
new (ret) value_type(t1, t2, t3); new (ret) value_type(t1, t2, t3);
CGAL_assertion(type(ret) == USED); CGAL_assertion(type(ret) == USED);
++size_; ++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0); return iterator(ret, 0);
} }
@ -393,6 +415,7 @@ public:
new (ret) value_type(t1, t2, t3, t4); new (ret) value_type(t1, t2, t3, t4);
CGAL_assertion(type(ret) == USED); CGAL_assertion(type(ret) == USED);
++size_; ++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0); return iterator(ret, 0);
} }
@ -409,6 +432,7 @@ public:
new (ret) value_type(t1, t2, t3, t4, t5); new (ret) value_type(t1, t2, t3, t4, t5);
CGAL_assertion(type(ret) == USED); CGAL_assertion(type(ret) == USED);
++size_; ++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0); return iterator(ret, 0);
} }
@ -426,6 +450,7 @@ public:
new (ret) value_type(t1, t2, t3, t4, t5, t6); new (ret) value_type(t1, t2, t3, t4, t5, t6);
CGAL_assertion(type(ret) == USED); CGAL_assertion(type(ret) == USED);
++size_; ++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0); return iterator(ret, 0);
} }
@ -443,6 +468,7 @@ public:
new (ret) value_type(t1, t2, t3, t4, t5, t6, t7); new (ret) value_type(t1, t2, t3, t4, t5, t6, t7);
CGAL_assertion(type(ret) == USED); CGAL_assertion(type(ret) == USED);
++size_; ++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0); return iterator(ret, 0);
} }
@ -460,6 +486,7 @@ public:
new (ret) value_type(t1, t2, t3, t4, t5, t6, t7, t8); new (ret) value_type(t1, t2, t3, t4, t5, t6, t7, t8);
CGAL_assertion(type(ret) == USED); CGAL_assertion(type(ret) == USED);
++size_; ++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0); return iterator(ret, 0);
} }
#endif // CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES #endif // CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES
@ -474,6 +501,7 @@ public:
alloc.construct(ret, t); alloc.construct(ret, t);
CGAL_assertion(type(ret) == USED); CGAL_assertion(type(ret) == USED);
++size_; ++size_;
time_stamper->set_time_stamp(ret);
return iterator(ret, 0); return iterator(ret, 0);
} }
@ -693,13 +721,14 @@ private:
void init() void init()
{ {
block_size = Incr_policy::first_block_size; block_size = Increment_policy::first_block_size;
capacity_ = 0; capacity_ = 0;
size_ = 0; size_ = 0;
free_list = NULL; free_list = NULL;
first_item = NULL; first_item = NULL;
last_item = NULL; last_item = NULL;
all_items = All_items(); all_items = All_items();
time_stamper->reset();
} }
allocator_type alloc; allocator_type alloc;
@ -710,10 +739,14 @@ private:
pointer first_item; pointer first_item;
pointer last_item; pointer last_item;
All_items all_items; 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 > template < class T, class Allocator, class Increment_policy, class TimeStamper >
void Compact_container<T, Allocator, Increment_policy>::merge(Self &d) void Compact_container<T, Allocator, Increment_policy, TimeStamper>::merge(Self &d)
{ {
CGAL_precondition(&d != this); CGAL_precondition(&d != this);
@ -749,8 +782,8 @@ void Compact_container<T, Allocator, Increment_policy>::merge(Self &d)
d.init(); d.init();
} }
template < class T, class Allocator, class Increment_policy > template < class T, class Allocator, class Increment_policy, class TimeStamper >
void Compact_container<T, Allocator, Increment_policy>::clear() void Compact_container<T, Allocator, Increment_policy, TimeStamper>::clear()
{ {
for (typename All_items::iterator it = all_items.begin(), itend = all_items.end(); for (typename All_items::iterator it = all_items.begin(), itend = all_items.end();
it != itend; ++it) { it != itend; ++it) {
@ -765,8 +798,8 @@ void Compact_container<T, Allocator, Increment_policy>::clear()
init(); init();
} }
template < class T, class Allocator, class Increment_policy > template < class T, class Allocator, class Increment_policy, class TimeStamper >
void Compact_container<T, Allocator, Increment_policy>::allocate_new_block() void Compact_container<T, Allocator, Increment_policy, TimeStamper>::allocate_new_block()
{ {
pointer new_block = alloc.allocate(block_size + 2); pointer new_block = alloc.allocate(block_size + 2);
all_items.push_back(std::make_pair(new_block, 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); Increment_policy::increase_size(*this);
} }
template < class T, class Allocator, class Increment_policy > template < class T, class Allocator, class Increment_policy, class TimeStamper >
inline inline
bool operator==(const Compact_container<T, Allocator, Increment_policy> &lhs, bool operator==(const Compact_container<T, Allocator, Increment_policy, TimeStamper> &lhs,
const Compact_container<T, Allocator, Increment_policy> &rhs) const Compact_container<T, Allocator, Increment_policy, TimeStamper> &rhs)
{ {
return lhs.size() == rhs.size() && return lhs.size() == rhs.size() &&
std::equal(lhs.begin(), lhs.end(), rhs.begin()); 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 inline
bool operator!=(const Compact_container<T, Allocator, Increment_policy> &lhs, bool operator!=(const Compact_container<T, Allocator, Increment_policy, TimeStamper> &lhs,
const Compact_container<T, Allocator, Increment_policy> &rhs) const Compact_container<T, Allocator, Increment_policy, TimeStamper> &rhs)
{ {
return ! (lhs == rhs); return ! (lhs == rhs);
} }
template < class T, class Allocator, class Increment_policy > template < class T, class Allocator, class Increment_policy, class TimeStamper >
inline inline
bool operator< (const Compact_container<T, Allocator, Increment_policy> &lhs, bool operator< (const Compact_container<T, Allocator, Increment_policy, TimeStamper> &lhs,
const Compact_container<T, Allocator, Increment_policy> &rhs) const Compact_container<T, Allocator, Increment_policy, TimeStamper> &rhs)
{ {
return std::lexicographical_compare(lhs.begin(), lhs.end(), return std::lexicographical_compare(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end()); rhs.begin(), rhs.end());
} }
template < class T, class Allocator, class Increment_policy > template < class T, class Allocator, class Increment_policy, class TimeStamper >
inline inline
bool operator> (const Compact_container<T, Allocator, Increment_policy> &lhs, bool operator> (const Compact_container<T, Allocator, Increment_policy, TimeStamper> &lhs,
const Compact_container<T, Allocator, Increment_policy> &rhs) const Compact_container<T, Allocator, Increment_policy, TimeStamper> &rhs)
{ {
return rhs < lhs; return rhs < lhs;
} }
template < class T, class Allocator, class Increment_policy > template < class T, class Allocator, class Increment_policy, class TimeStamper >
inline inline
bool operator<=(const Compact_container<T, Allocator, Increment_policy> &lhs, bool operator<=(const Compact_container<T, Allocator, Increment_policy, TimeStamper> &lhs,
const Compact_container<T, Allocator, Increment_policy> &rhs) const Compact_container<T, Allocator, Increment_policy, TimeStamper> &rhs)
{ {
return ! (lhs > rhs); return ! (lhs > rhs);
} }
template < class T, class Allocator, class Increment_policy > template < class T, class Allocator, class Increment_policy, class TimeStamper >
inline inline
bool operator>=(const Compact_container<T, Allocator, Increment_policy> &lhs, bool operator>=(const Compact_container<T, Allocator, Increment_policy, TimeStamper> &lhs,
const Compact_container<T, Allocator, Increment_policy> &rhs) const Compact_container<T, Allocator, Increment_policy, TimeStamper> &rhs)
{ {
return ! (lhs < rhs); return ! (lhs < rhs);
} }
@ -890,14 +923,19 @@ namespace internal {
private: private:
typedef typename DSC::Time_stamper_impl Time_stamper_impl;
union { union {
pointer p; pointer p;
void *vp; void *vp;
} m_ptr; } m_ptr;
// Only Compact_container should access these constructors. // Only Compact_container should access these constructors.
friend class Compact_container<value_type, typename DSC::Al, friend class Compact_container<value_type,
typename DSC::Incr_policy>; typename DSC::Al,
typename DSC::Ip,
typename DSC::Ts>;
// For begin() // For begin()
CC_iterator(pointer ptr, int, int) CC_iterator(pointer ptr, int, int)
@ -991,22 +1029,24 @@ namespace internal {
// For std::less... // For std::less...
bool operator<(const CC_iterator& other) const 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 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 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 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. // 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 <functional>
#include <algorithm> #include <algorithm>
#include <CGAL/memory.h> #include <CGAL/memory.h>
#include <CGAL/Time_stamper.h>
namespace CGAL { 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 Get_time_stamper<T>::type::less(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) || 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(x.node, node); }
bool operator>=( const Self& x) const { return node>= x.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; }
T* operator->() const { return node; } T* operator->() const { return node; }
Self& operator++() { Self& operator++() {
@ -138,12 +139,12 @@ namespace internal {
In_place_list_const_iterator( Iterator i) : node(&*i) {} In_place_list_const_iterator( Iterator i) : node(&*i) {}
In_place_list_const_iterator(const T* x) : node(x) {} 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 Get_time_stamper<T>::type::less(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) || 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(x.node, node); }
bool operator>=( const Self& x) const { return node>= x.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; }
const T* operator->() const { return node; } const T* operator->() const { return node; }
Self& operator++() { Self& operator++() {
@ -233,6 +234,7 @@ protected:
pointer node; pointer node;
size_type length; size_type length;
Time_stamper_impl<T>* time_stamper_ptr;
// These are the only places where the allocator gets called. // These are the only places where the allocator gets called.
pointer get_node() { pointer get_node() {
pointer p = allocator.allocate(1); pointer p = allocator.allocate(1);
@ -265,8 +267,10 @@ public:
// CREATION // CREATION
// //
// New creation variable is: `l' // New creation variable is: `l'
explicit In_place_list()
explicit In_place_list() : length(0) { : length(0)
, time_stamper_ptr(new Time_stamper_impl<T>())
{
// introduces an empty list. // introduces an empty list.
node = get_node(); node = get_node();
(*node).next_link = node; (*node).next_link = node;
@ -314,6 +318,7 @@ public:
(*((*position.node).prev_link)).next_link = &x; (*((*position.node).prev_link)).next_link = &x;
(*position.node).prev_link = &x; (*position.node).prev_link = &x;
++length; ++length;
time_stamper_ptr->set_time_stamp(&x);
return &x; return &x;
} }
iterator insert(T* pos, T& x) { iterator insert(T* pos, T& x) {
@ -385,11 +390,17 @@ public:
erase( iterator(first), iterator(last)); erase( iterator(first), iterator(last));
} }
void clear() { erase( begin(), end()); } void clear() {
erase( begin(), end());
time_stamper_ptr->reset();
}
// CREATION (Continued) // 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 // introduces a list with n items, all initialized with copies of
// value. // value.
node = get_node(); node = get_node();
@ -399,7 +410,10 @@ public:
} }
template <class InputIterator> 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'). // a list with copies from the range [`first,last').
node = get_node(); node = get_node();
(*node).next_link = node; (*node).next_link = node;
@ -407,14 +421,21 @@ public:
insert( begin(), first, last); 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'). // a list with copies from the range [`first,last').
node = get_node(); node = get_node();
(*node).next_link = node; (*node).next_link = node;
(*node).prev_link = node; (*node).prev_link = node;
insert(begin(), first, last); 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. // copy constructor. Each item in `l1' is copied.
node = get_node(); node = get_node();
(*node).next_link = node; (*node).next_link = node;
@ -424,6 +445,7 @@ public:
~In_place_list() { ~In_place_list() {
erase(begin(), end()); erase(begin(), end());
put_node(node); put_node(node);
delete time_stamper_ptr;
} }
Self& operator=(const Self& x); Self& operator=(const Self& x);
@ -486,6 +508,8 @@ protected:
public: public:
void splice(iterator position, Self& x) { 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. // inserts the list x before position `pos' and x becomes empty.
// It takes constant time. Precondition: `&l != &x'. // It takes constant time. Precondition: `&l != &x'.
if (!x.empty()) { if (!x.empty()) {
@ -498,6 +522,8 @@ public:
splice( iterator(position), x); splice( iterator(position), x);
} }
void splice( iterator position, Self& x, iterator i) { 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 // inserts an element pointed to by i from list x before position
// `pos' and removes the element from x. It takes constant time. i // `pos' and removes the element from x. It takes constant time. i
// is a valid dereferenceable iterator of x. The result is // is a valid dereferenceable iterator of x. The result is
@ -512,6 +538,8 @@ public:
splice( iterator(position), x, iterator(i)); splice( iterator(position), x, iterator(i));
} }
void splice(iterator pos, Self& x, iterator first, iterator last) { 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 // inserts elements in the range [`first, last') before position
// `pos' and removes the elements from x. It takes constant time // `pos' and removes the elements from x. It takes constant time
// if `&x == $l'; otherwise, it takes linear time. [`first, // 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/Random.h>
#include <CGAL/Testsuite/use.h> #include <CGAL/Testsuite/use.h>
#include <CGAL/tags.h>
#include <CGAL/use.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 struct Node_1
: public CGAL::Compact_container_base : public CGAL::Compact_container_base
{ {
bool operator==(const Node_1 &) const { return true; } bool operator==(const Node_1 &) const { return true; }
bool operator!=(const Node_1 &) const { return false; } bool operator!=(const Node_1 &) const { return false; }
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 class Node_2
@ -241,19 +258,62 @@ void test_index(const Cont &C)
} }
} }
struct Incomplete_struct;
int main() 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; typedef Node_1<CGAL::Tag_true > T1;
CGAL::Compact_container<Node_2, CGAL::Default, CGAL::Addition_size_policy<14,16> > C4; typedef CGAL::Compact_container<T1> C1; // with timestamps
test_index(C3); typedef Node_1<CGAL::Tag_false> T2;
test_index(C4); 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; return 0;
} }
// EOF // // EOF //

View File

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