diff --git a/Mesh_3/examples/Mesh_3/mesh_3D_image_variable_size.cpp b/Mesh_3/examples/Mesh_3/mesh_3D_image_variable_size.cpp index 0acdfdf5157..68bbb6010ea 100644 --- a/Mesh_3/examples/Mesh_3/mesh_3D_image_variable_size.cpp +++ b/Mesh_3/examples/Mesh_3/mesh_3D_image_variable_size.cpp @@ -1,3 +1,5 @@ +#define CGAL_MESH_3_VERBOSE + #include #include diff --git a/Mesh_3/examples/Mesh_3/mesh_implicit_sphere.cpp b/Mesh_3/examples/Mesh_3/mesh_implicit_sphere.cpp index 55a9350f40b..867a5395bc8 100644 --- a/Mesh_3/examples/Mesh_3/mesh_implicit_sphere.cpp +++ b/Mesh_3/examples/Mesh_3/mesh_implicit_sphere.cpp @@ -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, diff --git a/Mesh_3/examples/Mesh_3/mesh_implicit_sphere_variable_size.cpp b/Mesh_3/examples/Mesh_3/mesh_implicit_sphere_variable_size.cpp index acf57d24fa6..9650cb5c730 100644 --- a/Mesh_3/examples/Mesh_3/mesh_implicit_sphere_variable_size.cpp +++ b/Mesh_3/examples/Mesh_3/mesh_implicit_sphere_variable_size.cpp @@ -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; diff --git a/Mesh_3/examples/Mesh_3/mesh_two_implicit_spheres_with_balls.cpp b/Mesh_3/examples/Mesh_3/mesh_two_implicit_spheres_with_balls.cpp index c2ede3260ba..beb20cdb6f8 100644 --- a/Mesh_3/examples/Mesh_3/mesh_two_implicit_spheres_with_balls.cpp +++ b/Mesh_3/examples/Mesh_3/mesh_two_implicit_spheres_with_balls.cpp @@ -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, diff --git a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h index 114469e3d87..a8519fffd01 100644 --- a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h +++ b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include @@ -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 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, diff --git a/Mesh_3/include/CGAL/Implicit_mesh_domain_3.h b/Mesh_3/include/CGAL/Implicit_mesh_domain_3.h index 16238012a35..ab672b652f2 100644 --- a/Mesh_3/include/CGAL/Implicit_mesh_domain_3.h +++ b/Mesh_3/include/CGAL/Implicit_mesh_domain_3.h @@ -31,6 +31,7 @@ # pragma warning(disable:4180) // qualifier applied to function type has no meaning; ignored #endif +#include #include #include @@ -47,7 +48,7 @@ template > class Implicit_mesh_domain_3 - : public Mesh_3::Labeled_mesh_domain_3 + : public Mesh_3::Labeled_mesh_domain_3 { 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() {} diff --git a/Mesh_3/include/CGAL/Labeled_image_mesh_domain_3.h b/Mesh_3/include/CGAL/Labeled_image_mesh_domain_3.h index 74fba59dfd7..4a27f055b2b 100644 --- a/Mesh_3/include/CGAL/Labeled_image_mesh_domain_3.h +++ b/Mesh_3/include/CGAL/Labeled_image_mesh_domain_3.h @@ -27,7 +27,7 @@ #ifndef CGAL_LABELED_IMAGE_MESH_DOMAIN_3_H #define CGAL_LABELED_IMAGE_MESH_DOMAIN_3_H - +#include #include #include @@ -41,6 +41,7 @@ namespace CGAL { */ template > class Labeled_image_mesh_domain_3 : public Mesh_3::Labeled_mesh_domain_3 @@ -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 diff --git a/Mesh_3/include/CGAL/Mesh_3/Detect_features_in_polyhedra.h b/Mesh_3/include/CGAL/Mesh_3/Detect_features_in_polyhedra.h index e6d0ee85429..801d31b02f7 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Detect_features_in_polyhedra.h +++ b/Mesh_3/include/CGAL/Mesh_3/Detect_features_in_polyhedra.h @@ -55,8 +55,8 @@ public: typedef typename Polyhedron::Facet Facet; typedef typename Facet::Patch_id Patch_id; - typedef std::set Facet_handle_set; - typedef std::set He_handle_set; + typedef std::set Facet_handle_set; + typedef std::set 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 @@ -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 void Detect_features_in_polyhedra:: -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 ( ¤t_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(¤t_he) == 0 ) + if ( he_to_explore.erase(current_he) == 0 ) { - he_to_explore.insert(&*(current_he.opposite())); + he_to_explore.insert(current_he->opposite()); } } } diff --git a/Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra.h b/Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra.h index dac41b320b7..975cc4318bb 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra.h +++ b/Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra.h @@ -23,15 +23,46 @@ #define CGAL_MESH_3_DETECT_POLYLINES_IN_POLYHEDRA_H #include +#include +#include + #include #include +#include namespace CGAL { namespace Mesh_3 { -struct Detect_polyline_less { - template - bool operator()(const Handle& va, const Handle& vb) const { - return &*va < &*vb; +template +struct CGAL_with_time_stamp +{ +public: + static bool less(Handle h1, Handle h2) + { + return h1->time_stamp() < h2->time_stamp(); + } +}; + +template +struct CGAL_no_time_stamp +{ +public: + static bool less(Handle h1, Handle h2) + { + return &*h1 < &*h2; + } +}; + +struct Detect_polyline_less +{ + template + bool operator()(const Handle& h1, const Handle& h2) const + { + typedef typename std::iterator_traits::value_type Type; + typedef typename boost::mpl::if_c< + CGAL::internal::Has_timestamp::value, + CGAL_with_time_stamp, + CGAL_no_time_stamp >::type Comparator; + return Comparator::less(h1, h2); } }; diff --git a/Mesh_3/include/CGAL/Mesh_3/Labeled_mesh_domain_3.h b/Mesh_3/include/CGAL/Mesh_3/Labeled_mesh_domain_3.h index 92062a7c1c7..aa2bbde9ac0 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Labeled_mesh_domain_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Labeled_mesh_domain_3.h @@ -38,6 +38,7 @@ #include #include #include +#include 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 +template 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 Labeled_mesh_domain_3::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 Labeled_mesh_domain_3::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::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 = diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesh_complex_3_in_triangulation_3_base.h b/Mesh_3/include/CGAL/Mesh_3/Mesh_complex_3_in_triangulation_3_base.h index 47a4260e1b0..39e10b06da3 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesh_complex_3_in_triangulation_3_base.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesh_complex_3_in_triangulation_3_base.h @@ -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 { diff --git a/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h b/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h index 2c2e0e5efd8..f133491b31a 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h +++ b/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h @@ -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 = diff --git a/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h b/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h index b50c7e67d76..eea76ad1eb0 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h +++ b/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h @@ -46,6 +46,7 @@ #include #include #include +#include #include #ifdef CGAL_MESH_3_USE_RELAXED_HEAP @@ -61,8 +62,31 @@ namespace CGAL { +namespace internal { namespace Mesh_3 { + + // Hash function for boost::unordered_map + template + struct VHash + { + typedef typename Tr::Vertex_handle Vertex_handle; + std::size_t operator()(Vertex_handle vh) const + { + return vh->time_stamp(); + } + }; + template + struct VHash + { + 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, typename MeshDomain, typename SliverCriterion = Mesh_3::Min_dihedral_angle_criterion @@ -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 M; + typedef typename std::iterator_traits::value_type Vertex; + typedef CGAL::internal::Has_timestamp Vertex_has_timestamp; + using CGAL::internal::Mesh_3::VHash; + typedef VHash Hash_fct; + typedef boost::unordered_map M; + M vpm; for ( typename Tr::Finite_cells_iterator cit = tr_.finite_cells_begin(); cit != tr_.finite_cells_end() ; diff --git a/Mesh_3/include/CGAL/Mesh_cell_base_3.h b/Mesh_3/include/CGAL/Mesh_cell_base_3.h index 40178ede670..36a48f7a775 100644 --- a/Mesh_3/include/CGAL/Mesh_cell_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_cell_base_3.h @@ -33,6 +33,7 @@ #include #include #include +#include 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 @@ -157,7 +161,19 @@ public: previous_intrusive_ = c; } #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, diff --git a/Mesh_3/include/CGAL/Mesh_domain_with_polyline_features_3.h b/Mesh_3/include/CGAL/Mesh_domain_with_polyline_features_3.h index dc9fad52fa3..ff796c1f7b9 100644 --- a/Mesh_3/include/CGAL/Mesh_domain_with_polyline_features_3.h +++ b/Mesh_3/include/CGAL/Mesh_domain_with_polyline_features_3.h @@ -54,13 +54,13 @@ class Polyline typedef typename Kernel::FT FT; typedef std::vector Data; - + public: typedef typename Data::const_iterator const_iterator; - + Polyline() {} ~Polyline() {} - + /// Add a point at the end of the polyline void add_point(const Point_3& p) { @@ -68,33 +68,33 @@ public: points_.push_back(p); } } - + /// Returns the starting point of the polyline const Point_3& start_point() const { CGAL_assertion( ! points_.empty() ); return points_.front(); } - + /// Returns the ending point of the polyline const Point_3& end_point() const { CGAL_assertion( ! points_.empty() ); - return points_.back(); + return points_.back(); } - + /// Returns true if the polyline is not degenerated bool is_valid() const { return points_.size() > 1; } - + /// Returns true if polyline is a cycle bool is_cycle() const { return start_point() == end_point(); } - + /// Returns the length of the polyline FT length() const { @@ -102,29 +102,29 @@ public: FT result (0); const_iterator it = points_.begin(); const_iterator previous = it++; - + for ( const_iterator end = points_.end() ; it != end ; ++it, ++previous ) { result += distance(*previous,*it); } - + return result; } - + /// Returns signed geodesic distance between \c p and \c q FT geodesic_distance(const Point_3& p, const Point_3& q, bool /*treat_cycle*/=true) const { CGAL_precondition(is_valid()); - + // Locate p & q on polyline const_iterator pit = locate(p); const_iterator qit = locate(q,false); - + // Compute geodesic distance FT result = (pit <= qit) ? geodesic_distance(p,q,pit,qit) : -geodesic_distance(q,p,qit,pit); - + // Treat cycles: return a positive value if ( is_cycle() && (p==q || result < FT(0)) ) { @@ -133,8 +133,8 @@ public: return result; } - - + + /// Returns a point at geodesic distance \c distance from p along the /// polyline. The polyline is oriented from starting point to end point. /// The distance could be negative. @@ -142,108 +142,108 @@ public: { // use first point of the polyline instead of p distance += geodesic_distance(start_point(),p,false); - + // If polyline is a cycle, ensure that distance is given from start_point() if ( is_cycle() ) { if ( distance < FT(0) ) { distance += length(); } 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(); const_iterator previous = pit++; - + // Iterate to find which segment contains the point we want to construct FT segment_length = this->distance(*previous,*pit); while ( distance > segment_length ) { distance -= segment_length; - + // Increment iterators and update length ++previous; ++pit; CGAL_assertion(pit != points_.end()); - + segment_length = this->distance(*previous,*pit); } - + // return point at distance from current segment source typedef typename Kernel::Vector_3 Vector_3; Vector_3 v (*previous, *pit); - + return (*previous) + (distance / CGAL::sqrt(v.squared_length())) * v; } - + bool are_ordered_along(const Point_3& p, const Point_3& q) const { CGAL_precondition(!is_cycle()); - + // Locate p & q on polyline const_iterator pit = locate(p); const_iterator qit = locate(q,true); - + // Points are not located on the same segment if ( pit != qit ) { return (pit <= qit); } - + // pit == qit, then we have to sort p&q along (pit,pit+1) return ( compare_distance(*pit,p,q) != CGAL::LARGER ); } - + private: const_iterator first_segment_source() const { CGAL_precondition(is_valid()); return points_.begin(); } - + const_iterator last_segment_source() const { CGAL_precondition(is_valid()); return (points_.end() - 2); } - + FT geodesic_distance(const Point_3& p, const Point_3& q, const_iterator pit, const_iterator qit) const { CGAL_precondition(std::distance(pit,qit) >= 0); - + // If p and q are in the same segment of the polyline if ( pit == qit ) { FT result = distance(p,q); - + // Find the closest point to *pit if ( compare_distance(*pit,p,q) != CGAL::LARGER ) { return result; } else { return -result; } } - + // p is inside [pit,pit+1], pit+1 != qit, q is inside [qit,qit+1] FT result = distance(p,*(pit+1)); result += distance(*qit,q); - + // Add segments between pit+1 and qit to result for ( const_iterator it = (pit+1) ; it != qit ; ++it ) { result += distance(*it,*(it+1)); } - + return result; } - /// Returns an iterator on the starting point of the segment of the + /// Returns an iterator on the starting point of the segment of the /// polyline which contains p /// if end_point_first is true, then --end is returned instead of begin /// if p is the starting point of a cycle. const_iterator locate(const Point_3& p, bool end_point_first=false) const { CGAL_precondition(is_valid()); - + // First look if p is one of the points of the polyline const_iterator result = std::find(points_.begin(), points_.end(), p); if ( result != points_.end() ) @@ -251,7 +251,7 @@ private: if ( result != points_.begin() ) { return --result; } else - { + { // Treat cycles if ( end_point_first && p == end_point() ) { return last_segment_source(); } @@ -269,7 +269,7 @@ private: const_iterator nearest_vertex = it; result = nearest_vertex; bool nearest_is_a_segment = false; - + while ( ++it != points_.end() ) { Segment_3 seg (*previous, *it); @@ -311,27 +311,27 @@ private: return result; } } - + // FT squared_distance(const Point_3& p, const Point_3& q) const // { // typename Kernel::Compute_squared_distance_3 sq_distance = // Kernel().compute_squared_distance_3_object(); // return sq_distance(p,q); // } - + FT distance(const Point_3& p, const Point_3& q) const { return CGAL::sqrt(squared_distance(p, q)); } - Angle angle(const Point_3& p, + Angle angle(const Point_3& p, const Point_3& angle_vertex_point, - const Point_3& q) const + const Point_3& q) const { typename Kernel::Angle_3 compute_angle = Kernel().angle_3_object(); return compute_angle(p,angle_vertex_point,q); } - + template CGAL::Sign compare_distance(const Point_3& p, const T1& obj1, @@ -345,7 +345,7 @@ private: public: Data points_; }; // end class Polyline - + template struct Mesh_domain_segment_of_curve_primitive{ @@ -353,7 +353,7 @@ struct Mesh_domain_segment_of_curve_primitive{ typedef typename Map_value_type::first_type Curve_id; typedef typename Map_value_type::second_type Polyline; - typedef std::pair Id; typedef typename std::iterator_traits< @@ -362,7 +362,7 @@ struct Mesh_domain_segment_of_curve_primitive{ typedef typename Gt::Segment_3 Datum; Id id_; - + Mesh_domain_segment_of_curve_primitive(Id id) : id_(id) {} const Id& id() const { return id_; } @@ -427,7 +427,7 @@ public: // Index types typedef typename Base::Index Index; - typedef typename Base::Surface_patch_index + typedef typename Base::Surface_patch_index Surface_patch_index; typedef int Curve_segment_index; @@ -437,10 +437,10 @@ public: typedef Gt R; typedef typename Base::Point_3 Point_3; typedef typename Gt::FT FT; - + typedef CGAL::Tag_true Has_features; - + #ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES template Mesh_domain_with_polyline_features_3(const T& ...t) @@ -472,11 +472,11 @@ public: , curves_aabb_tree_is_built(false) {} template - Mesh_domain_with_polyline_features_3(const T1& o1, const T2& o2, + Mesh_domain_with_polyline_features_3(const T1& o1, const T2& o2, const T3& o3) : Base(o1, o2, o3) , current_corner_index_(1) - , current_curve_index_(1) + , current_curve_index_(1) , curves_aabb_tree_is_built(false) {} #endif @@ -486,13 +486,13 @@ public: /// OutputIterator value type is std::pair template OutputIterator get_corners(OutputIterator out) const; - + /// OutputIterator value type is CGAL::cpp11::tuple, std::pair > template OutputIterator get_curve_segments(OutputIterator out) const; - /// Returns the geodesic distance between points p and q of curve + /// Returns the geodesic distance between points p and q of curve /// \c curve_index FT geodesic_distance(const Point_3& p, const Point_3& q, const Curve_segment_index& curve_index) const; @@ -503,17 +503,17 @@ public: construct_point_on_curve_segment(const Point_3& starting_point, const Curve_segment_index& curve_index, FT distance) const; - + /// Returns the sign of the orientation of p,q,r along curve segment /// of index \c index CGAL::Sign distance_sign_along_cycle(const Point_3& p, const Point_3& q, const Point_3& r, const Curve_segment_index& index) const; - + /// Returns true if curve \c curve_index is a cycle bool is_cycle(const Point_3&, const Curve_segment_index& index) const; - + /// Returns an Index from a Curve_segment_index Index index_from_curve_segment_index(const Curve_segment_index& index) const { return Index(index); } @@ -521,11 +521,11 @@ public: /// Returns an Curve_segment_index from an Index Curve_segment_index curve_segment_index(const Index& index) const { return boost::get(index); } - + /// Returns an Index from a Corner_index Index index_from_corner_index(const Corner_index& index) const { return Index(index); } - + /// Returns an Corner_index from an Index Corner_index corner_index(const Index& index) const { return boost::get(index); } @@ -549,20 +549,20 @@ public: template IndicesOutputIterator get_incidences(Curve_segment_index id, IndicesOutputIterator out) const; - + template IndicesOutputIterator get_corner_incidences(Curve_segment_index id, IndicesOutputIterator out) const; typedef std::set Surface_patch_index_set; - const Surface_patch_index_set& + const Surface_patch_index_set& get_incidences(Curve_segment_index id) const; void display_corner_incidences(std::ostream& os, Corner_index id); template - void + void add_features(InputIterator first, InputIterator last) { add_features(first, last, CGAL::Emptyset_iterator()); } @@ -578,8 +578,8 @@ private: /// Returns the sign of the geodesic distance between \c p and \c q /// Precondition: index is not a cycle CGAL::Sign distance_sign(const Point_3& p, const Point_3& q, - const Curve_segment_index& index) const; - + const Curve_segment_index& index) const; + /// Returns Index associated to p (p must be the coordinates of a corner /// point) Index point_corner_index(const Point_3& p) const; @@ -597,7 +597,7 @@ private: Gt, typename Edges::const_iterator> Curves_primitives; - typedef CGAL::AABB_traits AABB_curves_traits; Corners corners_; @@ -621,17 +621,17 @@ public: if(!curves_aabb_tree_is_built) build_curves_aabb_tree(); return curves_aabb_tree_; } - + void build_curves_aabb_tree() const { std::cerr << "Building curves AABB tree...\n"; curves_aabb_tree_.clear(); - for(typename Edges::const_iterator + for(typename Edges::const_iterator edges_it = edges_.begin(), edges_end = edges_.end(); edges_it != edges_end; ++edges_it) { const Polyline& polyline = edges_it->second; - for(typename Polyline::const_iterator + for(typename Polyline::const_iterator pit = polyline.points_.begin(), end = polyline.points_.end() - 1; pit != end; ++pit) @@ -664,7 +664,7 @@ get_corners(OutputIterator out) const { *out++ = std::make_pair(cit->second,cit->first); } - + return out; } @@ -678,10 +678,10 @@ get_curve_segments(OutputIterator out) const eit = edges_.begin(), end = edges_.end() ; eit != end ; ++eit ) { CGAL_assertion( eit->second.is_valid() ); - + const Point_3& p = eit->second.start_point(); const Point_3& q = eit->second.end_point(); - + Index p_index, q_index; if ( ! eit->second.is_cycle() ) { @@ -693,15 +693,15 @@ get_curve_segments(OutputIterator out) const p_index = index_from_curve_segment_index(eit->first); q_index = p_index; } - + *out++ = CGAL::cpp11::make_tuple(eit->first, std::make_pair(p,p_index), std::make_pair(q,q_index)); } - + return out; } - + template typename Mesh_domain_with_polyline_features_3::Index @@ -714,7 +714,7 @@ point_corner_index(const Point_3& p) const CGAL_assertion(false); return Index(); } - + return p_index_it->second; } @@ -728,7 +728,7 @@ geodesic_distance(const Point_3& p, const Point_3& q, // Get corresponding polyline typename Edges::const_iterator eit = edges_.find(curve_index); CGAL_assertion(eit != edges_.end()); - + // Compute geodesic_distance return eit->second.geodesic_distance(p,q); } @@ -744,7 +744,7 @@ construct_point_on_curve_segment(const Point_3& starting_point, // Get corresponding polyline typename Edges::const_iterator eit = edges_.find(curve_index); CGAL_assertion(eit != edges_.end()); - + // Return point at geodesic_distance distance from starting_point return eit->second.point_at(starting_point,distance); } @@ -778,7 +778,7 @@ add_features_with_context(InputIterator first, InputIterator last, // Insert one edge for each element for( ; first != last ; ++first ) { - Curve_segment_index curve_id = + Curve_segment_index curve_id = insert_edge(first->polyline_content.begin(), first->polyline_content.end()); edges_incidences_[curve_id] = first->context.adjacent_patches_ids; *indices_out++ = curve_id; @@ -900,7 +900,7 @@ void Mesh_domain_with_polyline_features_3:: compute_corners_incidences() { - for(typename Corners::iterator + for(typename Corners::iterator cit = corners_.begin(), end = corners_.end(); cit != end; /* the loop variable is incremented in the body */) { @@ -925,7 +925,7 @@ compute_corners_incidences() BOOST_FOREACH(Curve_segment_index curve_index, corner_tmp_incidences) { - get_incidences(curve_index, + get_incidences(curve_index, std::inserter(incidences, incidences.begin())); } @@ -939,7 +939,7 @@ compute_corners_incidences() } template -const typename Mesh_domain_with_polyline_features_3::Surface_patch_index_set& +const typename Mesh_domain_with_polyline_features_3::Surface_patch_index_set& Mesh_domain_with_polyline_features_3:: get_incidences(Curve_segment_index id) const { @@ -952,7 +952,7 @@ void Mesh_domain_with_polyline_features_3:: register_corner(const Point_3& p, const Curve_segment_index& curve_index) { - + typename Corners::iterator cit = corners_.lower_bound(p); // If the corner already exists, returns... @@ -977,9 +977,9 @@ Mesh_domain_with_polyline_features_3:: insert_edge(InputIterator first, InputIterator last) { CGAL_assertion(std::distance(first,last) > 1); - + const Curve_segment_index curve_index = current_curve_index_++; - + // Fill corners // // For a cycle, the "first" point of the cycle is registered as a @@ -991,11 +991,11 @@ insert_edge(InputIterator first, InputIterator last) { register_corner(*boost::prior(last), curve_index); } - + // Create a new polyline std::pair insertion = edges_.insert(std::make_pair(curve_index,Polyline())); - + // Fill polyline with data while ( first != last ) { @@ -1014,7 +1014,7 @@ distance_sign(const Point_3& p, const Point_3& q, typename Edges::const_iterator eit = edges_.find(index); CGAL_assertion(eit != edges_.end()); CGAL_precondition( ! eit->second.is_cycle() ); - + if ( p == q ) return CGAL::ZERO; else if ( eit->second.are_ordered_along(p,q) ) @@ -1034,17 +1034,17 @@ distance_sign_along_cycle(const Point_3& p, // Find edge typename Edges::const_iterator eit = edges_.find(index); CGAL_assertion(eit != edges_.end()); - + // If eit is not a cycle, then the orientation corresponds to the sign // of the distance if ( ! eit->second.is_cycle() ) { return distance_sign(p,r,index); } - + // If p and r are the same point, it correspond to a complete loop on a cycle if ( p == r ) { return CGAL::POSITIVE; } - + // We are on a cycle without any clue (p==q). Return the shortest path as // orientation. if ( p == q ) @@ -1054,15 +1054,15 @@ distance_sign_along_cycle(const Point_3& p, if ( pr < rp ) { return CGAL::POSITIVE; } else { return CGAL::NEGATIVE; } } - + // If pq or pr is negative, edge is not a cycle, thus geodesic_distance // gives the answer. FT pq = eit->second.geodesic_distance(p,q); FT pr = eit->second.geodesic_distance(p,r); CGAL_assertion(pq > FT(0)); CGAL_assertion(pr > FT(0)); - - // Compare pq and pr + + // Compare pq and pr if ( pq <= pr ) { return CGAL::POSITIVE; } else { return CGAL::NEGATIVE; } } @@ -1075,7 +1075,7 @@ is_cycle(const Point_3&, const Curve_segment_index& index) const // Find edge typename Edges::const_iterator eit = edges_.find(index); CGAL_assertion(eit != edges_.end()); - + return eit->second.is_cycle(); } diff --git a/Mesh_3/include/CGAL/Mesh_polyhedron_3.h b/Mesh_3/include/CGAL/Mesh_polyhedron_3.h index 91f2840328d..8c5e75c86a5 100644 --- a/Mesh_3/include/CGAL/Mesh_polyhedron_3.h +++ b/Mesh_3/include/CGAL/Mesh_polyhedron_3.h @@ -27,6 +27,8 @@ #include #include +#include +#include #include @@ -44,6 +46,8 @@ private: typedef CGAL::HalfedgeDS_vertex_base Pdv_base; Set_of_indices indices; + std::size_t time_stamp_; + public: int nb_of_feature_edges; @@ -58,6 +62,18 @@ public: void add_incident_patch(const Patch_id 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& incident_patches_ids_set() const { @@ -74,6 +90,8 @@ public CGAL::HalfedgeDS_halfedge_base { 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 @@ -108,6 +138,8 @@ public CGAL::HalfedgeDS_face_base { 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 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 diff --git a/Mesh_3/include/CGAL/Mesh_vertex_base_3.h b/Mesh_3/include/CGAL/Mesh_vertex_base_3.h index c802d377811..2a2629aa9bb 100644 --- a/Mesh_3/include/CGAL/Mesh_vertex_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_vertex_base_3.h @@ -30,9 +30,10 @@ #define CGAL_COMPACT_MESH_VERTEX_BASE_3_H #include -#include #include #include +#include +#include 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 #include +#include #include #include #include @@ -63,8 +64,8 @@ max_length(const Bbox_3& b) return (std::max)(b.xmax()-b.xmin(), (std::max)(b.ymax()-b.ymin(),b.zmax()-b.zmin()) ); } - - + + // ----------------------------------- // Surface_patch_index_generator // To use patch_id enclosed in AABB_primitives or not @@ -74,12 +75,12 @@ struct Surface_patch_index_generator { typedef std::pair Surface_patch_index; typedef Surface_patch_index type; - + template < typename Primitive_id > Surface_patch_index operator()(const Primitive_id&) { return Surface_patch_index(0,1); } }; - + template < typename Subdomain_index, typename Polyhedron > struct Surface_patch_index_generator { @@ -113,10 +114,10 @@ struct Index_generator // ----------------------------------- // Geometric traits generator // ----------------------------------- -template < typename Gt, +template < typename Gt, typename Use_exact_intersection_construction_tag > struct IGT_generator {}; - + template < typename Gt > struct IGT_generator { @@ -127,14 +128,14 @@ struct IGT_generator #endif // NOT CGAL_MESH_3_NEW_ROBUST_INTERSECTION_TRAITS typedef type Type; }; - + template < typename Gt > struct IGT_generator { typedef Gt type; typedef type Type; }; - + } // end namespace details } // end namespace Mesh_3 @@ -154,7 +155,7 @@ class Polyhedral_mesh_domain_3 { typedef typename Mesh_3::details::IGT_generator< IGT_,Use_exact_intersection_construction_tag>::type IGT; - + public: /// Geometric object types typedef typename IGT::Point_3 Point_3; @@ -196,46 +197,67 @@ private: typedef typename AABB_tree_::Primitive_id AABB_primitive_id; typedef typename AABB_tree_::Primitive Primitive; typedef typename AABB_traits::Bounding_box Bounding_box; - + public: /// Default constructor Polyhedral_mesh_domain_3() : tree_() - , bounding_tree_(&tree_) - , has_cache(false) {} - + , bounding_tree_(&tree_) + , 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; + } } - - /** + + /** * Constructor. * * Constructor from a sequence of polyhedral surfaces, and a bounding @@ -249,10 +271,13 @@ public: template Polyhedral_mesh_domain_3(InputPolyhedraPtrIterator begin, InputPolyhedraPtrIterator end, - const Polyhedron& bounding_polyhedron) - : has_cache(false) + const Polyhedron& bounding_polyhedron, + CGAL::Random* p_rng = NULL) + : has_cache(false) + , p_rng_(p_rng) + , delete_rng_(false) { - if(begin != end) { + if(begin != end) { for(; begin != end; ++begin) { tree_.insert(TriangleAccessor().triangles_begin(**begin), TriangleAccessor().triangles_end(**begin)); @@ -260,7 +285,7 @@ public: tree_.insert(TriangleAccessor().triangles_begin(bounding_polyhedron), TriangleAccessor().triangles_end(bounding_polyhedron)); tree_.build(); - bounding_tree_ = + bounding_tree_ = new AABB_tree_(TriangleAccessor().triangles_begin(bounding_polyhedron), TriangleAccessor().triangles_end(bounding_polyhedron)); bounding_tree_->build(); @@ -270,9 +295,14 @@ public: TriangleAccessor().triangles_end(bounding_polyhedron)); bounding_tree_ = &tree_; } + if(!p_rng_) + { + p_rng_ = new CGAL::Random(0); + delete_rng_ = true; + } } - /** + /** * Constructor. * * Constructor from a sequence of polyhedral surfaces, without bounding @@ -284,8 +314,11 @@ public: */ template Polyhedral_mesh_domain_3(InputPolyhedraPtrIterator begin, - InputPolyhedraPtrIterator end) - : has_cache(false) + 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,13 +328,20 @@ public: tree_.build(); } bounding_tree_ = 0; + if(!p_rng_) + { + p_rng_ = new CGAL::Random(0); + delete_rng_ = true; + } } /// Destructor - ~Polyhedral_mesh_domain_3() { + ~Polyhedral_mesh_domain_3() { if(bounding_tree_ != 0 && bounding_tree_ != &tree_) { - delete bounding_tree_; + delete bounding_tree_; } + if(delete_rng_) + delete p_rng_; } /** @@ -348,7 +388,7 @@ public: { return tree_.closest_point(p); } - + /// Allowed query types typedef boost::mpl::vector Allowed_query_types; @@ -376,10 +416,10 @@ public: boost::optional primitive_id = r_domain_.tree_.any_intersected_primitive(q); if ( primitive_id ) - { + { r_domain_.cache_primitive(q, *primitive_id); return Surface_patch(r_domain_.make_surface_index(*primitive_id)); - } else { + } else { return Surface_patch(); } } @@ -430,7 +470,7 @@ public: intersection = o ? Intersection_and_primitive_id(*o, primitive_id) : AABB_intersection(); - } else + } else #endif // not CGAL_MESH_3_NO_LONGER_CALLS_DO_INTERSECT_3 { #ifndef CGAL_MESH_3_NO_LONGER_CALLS_DO_INTERSECT_3 @@ -443,7 +483,7 @@ public: { // Get primitive AABB_primitive_id primitive_id = intersection->second; - + // intersection may be either a point or a segment #if CGAL_INTERSECTION_VERSION > 1 if ( const Bare_point* p_intersect_pt = @@ -478,10 +518,10 @@ public: std::stringstream stream; stream.precision(17); set_pretty_mode(stream); - stream << + stream << "Mesh_3 error : AABB_tree any_intersection result is " "not a point nor a segment\n"; - if(intersection->first.empty()) { + if(intersection->first.empty()) { stream << "The intersection is empty!"; } else { stream << "The intersection typeinfo name is "; @@ -492,7 +532,7 @@ public: stream << "The intersecting primitive in the AABB tree was: " << AABB_primitive(intersection->second).datum() << std::endl; CGAL_error_msg(stream.str().c_str()); -#endif // not CGAL_MESH_3_NO_LONGER_CALLS_DO_INTERSECT_3 +#endif // not CGAL_MESH_3_NO_LONGER_CALLS_DO_INTERSECT_3 } } @@ -509,8 +549,8 @@ public: { return Construct_intersection(*this); } - - + + /** * Returns the index to be stored in a vertex lying on the surface identified * by \c index. @@ -538,16 +578,16 @@ public: */ Subdomain_index subdomain_index(const Index& index) const { return boost::get(index); } - + // ----------------------------------- // Backward Compatibility // ----------------------------------- #ifndef CGAL_MESH_3_NO_DEPRECATED_SURFACE_INDEX typedef Surface_patch_index Surface_index; - + Index index_from_surface_index(const Surface_index& index) const { return index_from_surface_patch_index(index); } - + Surface_index surface_index(const Index& index) const { return surface_patch_index(index); } #endif // CGAL_MESH_3_NO_DEPRECATED_SURFACE_INDEX @@ -579,10 +619,10 @@ protected: { tree_.insert(TriangleAccessor().triangles_begin(p), TriangleAccessor().triangles_end(p)); - + tree_.build(); } - + private: /// The AABB tree: intersection detection and more AABB_tree_ tree_; @@ -595,10 +635,14 @@ 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 - void cache_primitive(const Query& q, + void cache_primitive(const Query& q, const AABB_primitive_id id) const { cached_query = Cached_query(q); @@ -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 +template template OutputIterator Polyhedral_mesh_domain_3:: @@ -632,13 +691,14 @@ Construct_initial_points::operator()(OutputIterator pts, { typename IGT::Construct_ray_3 ray = IGT().construct_ray_3_object(); typename IGT::Construct_vector_3 vector = IGT().construct_vector_3_object(); - + const Bounding_box bbox = r_domain_.tree_.bbox(); const Point_3 center( FT( (bbox.xmin() + bbox.xmax()) / 2), FT( (bbox.ymin() + bbox.ymax()) / 2), FT( (bbox.zmin() + bbox.zmax()) / 2) ); - - Random_points_on_sphere_3 random_point(1.); + + CGAL::Random& rng = *(r_domain_.p_rng_); + Random_points_on_sphere_3 random_point(1., rng); int i = n; #ifdef CGAL_MESH_3_VERBOSE @@ -658,9 +718,9 @@ Construct_initial_points::operator()(OutputIterator pts, #endif *pts++ = std::make_pair(CGAL::cpp0x::get<0>(intersection), CGAL::cpp0x::get<1>(intersection)); - + --i; - + #ifdef CGAL_MESH_3_VERBOSE std::cerr << boost::format("\r \r" "%1%/%2% initial point(s) found...") @@ -670,7 +730,7 @@ Construct_initial_points::operator()(OutputIterator pts, } ++random_point; } - + #ifdef CGAL_MESH_3_VERBOSE std::cerr << std::endl; #endif @@ -678,7 +738,8 @@ Construct_initial_points::operator()(OutputIterator pts, } -template +template typename Polyhedral_mesh_domain_3::Subdomain Polyhedral_mesh_domain_3:: Is_in_domain::operator()(const Point_3& p) const diff --git a/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h b/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h index 65ebf82fa4a..0cd77eef14c 100644 --- a/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h +++ b/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h @@ -28,11 +28,11 @@ #include +#include #include #include #include -#include #include #include #include @@ -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 - 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 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:: -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:: -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:: +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:: detect_features(FT angle_in_degree, Polyhedron& p) { + initialize_ts(p); // Get sharp features Mesh_3::detect_features(p,angle_in_degree); diff --git a/Mesh_3/test/Mesh_3/CMakeLists.txt b/Mesh_3/test/Mesh_3/CMakeLists.txt index 547412ea87f..813c224ed6e 100644 --- a/Mesh_3/test/Mesh_3/CMakeLists.txt +++ b/Mesh_3/test/Mesh_3/CMakeLists.txt @@ -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() diff --git a/Mesh_3/test/Mesh_3/test_c3t3_io.cpp b/Mesh_3/test/Mesh_3/test_c3t3_io.cpp index e67994131ba..8b7e214e9b3 100644 --- a/Mesh_3/test/Mesh_3/test_c3t3_io.cpp +++ b/Mesh_3/test/Mesh_3/test_c3t3_io.cpp @@ -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); } diff --git a/Mesh_3/test/Mesh_3/test_meshing_3D_image.cpp b/Mesh_3/test/Mesh_3/test_meshing_3D_image.cpp index 1728422ba5a..0940e512f16 100644 --- a/Mesh_3/test/Mesh_3/test_meshing_3D_image.cpp +++ b/Mesh_3/test/Mesh_3/test_meshing_3D_image.cpp @@ -19,7 +19,7 @@ // Author(s) : Stephane Tayeb // //****************************************************************************** -// File Description : +// File Description : //****************************************************************************** #include "test_meshing_utilities.h" @@ -35,33 +35,36 @@ public: { typedef CGAL::Image_3 Image; typedef CGAL::Labeled_image_mesh_domain_3 Mesh_domain; - + typedef typename CGAL::Mesh_triangulation_3::type Tr; typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; - + typedef CGAL::Mesh_criteria_3 Mesh_criteria; typedef typename Mesh_criteria::Facet_criteria Facet_criteria; typedef typename Mesh_criteria::Cell_criteria Cell_criteria; - + CGAL_USE_TYPE(typename Mesh_domain::Surface_patch_index); - + //------------------------------------------------------- // Data generation //------------------------------------------------------- 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()); Cell_criteria cell_criteria(4, 25*image.vx()); Mesh_criteria criteria(facet_criteria, cell_criteria); - + // Mesh generation C3t3 c3t3 = CGAL::make_mesh_3(domain, criteria, CGAL::parameters::no_exude(), CGAL::parameters::no_perturb()); - + // Verify this->verify_c3t3_volume(c3t3, 1772330*0.95, 1772330*1.05); this->verify(c3t3,domain,criteria, Bissection_tag()); @@ -76,6 +79,6 @@ int main() Image_tester test_epic; std::cerr << "Mesh generation from a 3D image:\n"; test_epic.image(); - - return EXIT_SUCCESS; + + return EXIT_SUCCESS; } diff --git a/Mesh_3/test/Mesh_3/test_meshing_determinism.cpp b/Mesh_3/test/Mesh_3/test_meshing_determinism.cpp new file mode 100644 index 00000000000..8fc3feab82f --- /dev/null +++ b/Mesh_3/test/Mesh_3/test_meshing_determinism.cpp @@ -0,0 +1,108 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +// Domain +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Polyhedral_mesh_domain_with_features_3 Mesh_domain; + +// Triangulation +typedef CGAL::Mesh_triangulation_3::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 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 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(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; +} diff --git a/Mesh_3/test/Mesh_3/test_meshing_implicit_function.cpp b/Mesh_3/test/Mesh_3/test_meshing_implicit_function.cpp index 68737e1ae46..362cc8b053e 100644 --- a/Mesh_3/test/Mesh_3/test_meshing_implicit_function.cpp +++ b/Mesh_3/test/Mesh_3/test_meshing_implicit_function.cpp @@ -57,8 +57,12 @@ struct Implicit_tester : public Tester //------------------------------------------------------- // Data generation //------------------------------------------------------- + std::cout << "\tSeed is\t" + << CGAL::default_random.get_seed() << std::endl; Mesh_domain domain(Implicit_tester::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); diff --git a/Mesh_3/test/Mesh_3/test_meshing_polyhedron.cpp b/Mesh_3/test/Mesh_3/test_meshing_polyhedron.cpp index b49ee30ea83..cd868d7a98d 100644 --- a/Mesh_3/test/Mesh_3/test_meshing_polyhedron.cpp +++ b/Mesh_3/test/Mesh_3/test_meshing_polyhedron.cpp @@ -19,7 +19,7 @@ // Author(s) : Stephane Tayeb // //****************************************************************************** -// File Description : +// File Description : //****************************************************************************** #include "test_meshing_utilities.h" @@ -34,16 +34,16 @@ struct Polyhedron_tester : public Tester typedef K Gt; typedef CGAL::Polyhedron_3 Polyhedron; typedef CGAL::Polyhedral_mesh_domain_3 Mesh_domain; - + typedef typename CGAL::Mesh_triangulation_3::type Tr; typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; - + typedef CGAL::Mesh_criteria_3 Mesh_criteria; typedef typename Mesh_criteria::Facet_criteria Facet_criteria; typedef typename Mesh_criteria::Cell_criteria Cell_criteria; - + typedef typename Mesh_domain::Surface_patch_index Surface_patch_index; - + //------------------------------------------------------- // Data generation //------------------------------------------------------- @@ -51,28 +51,30 @@ struct Polyhedron_tester : public Tester std::ifstream input("data/sphere.off"); 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); Cell_criteria cell_criteria(2, 0.2); Mesh_criteria criteria(facet_criteria, cell_criteria); - + // Mesh generation C3t3 c3t3; typename Polyhedron::Point_iterator end = polyhedron.points_begin(); int i=0; while ( i++ < 4 ) { ++end; } - + c3t3.insert_surface_points(polyhedron.points_begin(), end, domain.index_from_surface_patch_index(Surface_patch_index(0,1))); - + CGAL::refine_mesh_3(c3t3, domain, criteria, CGAL::parameters::no_exude(), CGAL::parameters::no_perturb()); - + // Verify double vol = 0.479171765761454; this->verify_c3t3_volume(c3t3, vol*0.95, vol*1.05); @@ -85,6 +87,6 @@ int main() Polyhedron_tester test_epic; std::cerr << "Mesh generation from a polyhedron:\n"; test_epic.polyhedron(); - + return EXIT_SUCCESS; } diff --git a/Mesh_3/test/Mesh_3/test_meshing_polyhedron_with_features.cpp b/Mesh_3/test/Mesh_3/test_meshing_polyhedron_with_features.cpp index 2d35bd2907c..4fee0e62f97 100644 --- a/Mesh_3/test/Mesh_3/test_meshing_polyhedron_with_features.cpp +++ b/Mesh_3/test/Mesh_3/test_meshing_polyhedron_with_features.cpp @@ -19,7 +19,7 @@ // Author(s) : Stephane Tayeb // //****************************************************************************** -// File Description : +// File Description : //****************************************************************************** #include "test_meshing_utilities.h" @@ -36,24 +36,26 @@ struct Polyhedron_with_features_tester : public Tester { typedef CGAL::Mesh_3::Robust_intersection_traits_3 Gt; typedef CGAL::Polyhedral_mesh_domain_with_features_3 Mesh_domain; - + typedef typename CGAL::Mesh_triangulation_3::type Tr; typedef CGAL::Mesh_complex_3_in_triangulation_3 < Tr, typename Mesh_domain::Corner_index, typename Mesh_domain::Curve_segment_index > C3t3; - + typedef CGAL::Mesh_criteria_3 Mesh_criteria; typedef typename Mesh_criteria::Edge_criteria Edge_criteria; typedef typename Mesh_criteria::Facet_criteria Facet_criteria; typedef typename Mesh_criteria::Cell_criteria Cell_criteria; - + //------------------------------------------------------- // 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 Edge_criteria edge_criteria(0.2); Facet_criteria facet_criteria(30, 0.2, 0.02); @@ -64,7 +66,7 @@ struct Polyhedron_with_features_tester : public Tester C3t3 c3t3 = CGAL::make_mesh_3(domain, criteria, CGAL::parameters::no_exude(), CGAL::parameters::no_perturb()); - + // Verify this->verify(c3t3,domain,criteria, Polyhedral_tag()); //, 1099, 1099, 1158, 1158, 4902, 4902); @@ -81,7 +83,7 @@ struct Polyhedron_with_features_tester : public Tester std::ios_base::in|std::ios_base::binary); CGAL::Mesh_3::load_binary_file(in_binary, c3t3_bis); assert(c3t3_bis.triangulation() == c3t3.triangulation()); - + } }; diff --git a/Mesh_3/test/Mesh_3/test_meshing_polylines_only.cpp b/Mesh_3/test/Mesh_3/test_meshing_polylines_only.cpp index 9a9603ff04a..d3989fd88b7 100644 --- a/Mesh_3/test/Mesh_3/test_meshing_polylines_only.cpp +++ b/Mesh_3/test/Mesh_3/test_meshing_polylines_only.cpp @@ -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 Polyline; typedef std::vector Polylines; diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_type.h b/Polyhedron/demo/Polyhedron/Polyhedron_type.h index c67d6ff227c..2dc7a449c69 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_type.h +++ b/Polyhedron/demo/Polyhedron/Polyhedron_type.h @@ -8,6 +8,8 @@ // surface mesh #include #include +#include +#include #include @@ -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 @@ -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 diff --git a/STL_Extension/include/CGAL/Compact_container.h b/STL_Extension/include/CGAL/Compact_container.h index cf198f53d24..714e2b2fd1a 100644 --- a/STL_Extension/include/CGAL/Compact_container.h +++ b/STL_Extension/include/CGAL/Compact_container.h @@ -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 #include +#include -#include // 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 > +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 Self; + typedef Increment_policy_ Ip; + typedef typename Default::Get< Ip, + Addition_size_policy + >::type Increment_policy; + typedef TimeStamper_ Ts; + typedef Compact_container Self; typedef Compact_container_traits Traits; public: + typedef typename Default::Get< TimeStamper_, + CGAL::Time_stamper_impl >::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); } @@ -581,7 +609,7 @@ public: /** Reserve method to ensure that the capacity of the Compact_container be * greater or equal than a given value n. - */ + */ void reserve(size_type n) { if ( capacity_>=n ) return; @@ -626,7 +654,7 @@ public: } while ( curblock>lastblock ); } - + private: void allocate_new_block(); @@ -678,7 +706,7 @@ private: { // This out of range compare is always true and causes lots of // unnecessary warnings. - // CGAL_precondition(0 <= t && t < 4); + // CGAL_precondition(0 <= t && t < 4); Traits::pointer(*ptr) = (void *) ((clean_pointer((char *) p)) + (int) t); } @@ -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::merge(Self &d) +template < class T, class Allocator, class Increment_policy, class TimeStamper > +void Compact_container::merge(Self &d) { CGAL_precondition(&d != this); @@ -749,8 +782,8 @@ void Compact_container::merge(Self &d) d.init(); } -template < class T, class Allocator, class Increment_policy > -void Compact_container::clear() +template < class T, class Allocator, class Increment_policy, class TimeStamper > +void Compact_container::clear() { for (typename All_items::iterator it = all_items.begin(), itend = all_items.end(); it != itend; ++it) { @@ -765,8 +798,8 @@ void Compact_container::clear() init(); } -template < class T, class Allocator, class Increment_policy > -void Compact_container::allocate_new_block() +template < class T, class Allocator, class Increment_policy, class TimeStamper > +void Compact_container::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::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 &lhs, - const Compact_container &rhs) +bool operator==(const Compact_container &lhs, + const Compact_container &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 &lhs, - const Compact_container &rhs) +bool operator!=(const Compact_container &lhs, + const Compact_container &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 &lhs, - const Compact_container &rhs) +bool operator< (const Compact_container &lhs, + const Compact_container &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 &lhs, - const Compact_container &rhs) +bool operator> (const Compact_container &lhs, + const Compact_container &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 &lhs, - const Compact_container &rhs) +bool operator<=(const Compact_container &lhs, + const Compact_container &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 &lhs, - const Compact_container &rhs) +bool operator>=(const Compact_container &lhs, + const Compact_container &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; + friend class Compact_container; + // 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. diff --git a/STL_Extension/include/CGAL/Has_timestamp.h b/STL_Extension/include/CGAL/Has_timestamp.h new file mode 100644 index 00000000000..c731c5cd533 --- /dev/null +++ b/STL_Extension/include/CGAL/Has_timestamp.h @@ -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 +#include + +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 ::value> + struct Has_timestamp : public T::Has_timestamp + // when T has a Has_timestamp tag + {}; + + template + struct Has_timestamp : public Tag_false + // when T does not have a Has_timestamp tag + {}; + +} // end namespace internal +} // end namespace CGAL + +#endif // CGAL_HAS_TIMESTAMP_H diff --git a/STL_Extension/include/CGAL/In_place_list.h b/STL_Extension/include/CGAL/In_place_list.h index ecdf77e06b9..23f3b1d768c 100644 --- a/STL_Extension/include/CGAL/In_place_list.h +++ b/STL_Extension/include/CGAL/In_place_list.h @@ -33,6 +33,7 @@ #include #include #include +#include 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::type::less(node, x.node); } + bool operator<=( const Self& x) const { return Get_time_stamper::type::less(node, x.node) || node==x.node; } + bool operator> ( const Self& x) const { return Get_time_stamper::type::less(x.node, node); } + bool operator>=( const Self& x) const { return Get_time_stamper::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::type::less(node, x.node); } + bool operator<=( const Self& x) const { return Get_time_stamper::type::less(node, x.node) || node==x.node; } + bool operator> ( const Self& x) const { return Get_time_stamper::type::less(x.node, node); } + bool operator>=( const Self& x) const { return Get_time_stamper::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* 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()) + { // 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()) + { // introduces a list with n items, all initialized with copies of // value. node = get_node(); @@ -399,7 +410,10 @@ public: } template - 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()) + { // 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()) + { // 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()) + { // 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::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::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::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, diff --git a/STL_Extension/include/CGAL/Time_stamper.h b/STL_Extension/include/CGAL/Time_stamper.h new file mode 100644 index 00000000000..19a23e8e7d0 --- /dev/null +++ b/STL_Extension/include/CGAL/Time_stamper.h @@ -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 + +#ifndef CGAL_TIME_STAMPER_H +#define CGAL_TIME_STAMPER_H + +namespace CGAL { + +template +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 + +template +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 + +// 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` or `No_time_stamp` 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 ::value> +struct Get_time_stamper{ + typedef Time_stamper type; +}; + +// Specialization when `T::Has_timestamp` does not exist, derives from +// `TimeStamper_`, or from `No_time_stamp`. +template +struct Get_time_stamper{ + typedef No_time_stamp 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 +// in `Compact_container` for example is possible with an incomplete type. +template +struct Time_stamper_impl : public Get_time_stamper::type {}; + +} //end of namespace CGAL + +#endif // CGAL_TIME_STAMPER_H diff --git a/STL_Extension/test/STL_Extension/test_Compact_container.cpp b/STL_Extension/test/STL_Extension/test_Compact_container.cpp index fa31d3c3f71..ad7d028cdc5 100644 --- a/STL_Extension/test/STL_Extension/test_Compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Compact_container.cpp @@ -9,15 +9,32 @@ #include #include +#include #include +#include +#include +template 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 C1; - CGAL::Compact_container C2; - test(C1); - test(C2); - CGAL::Compact_container > C3; - CGAL::Compact_container > C4; + typedef Node_1 T1; + typedef CGAL::Compact_container C1; // with timestamps - test_index(C3); - test_index(C4); + typedef Node_1 T2; + typedef CGAL::Compact_container C2; // without timestamps + typedef CGAL::Compact_container > C4; + // with timestamps + + typedef Node_2 T3; + typedef CGAL::Compact_container 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, + C1::Time_stamper_impl>::value) + { + std::cerr << "Error timestamper of C1\n"; return 1; + } + if(! boost::is_base_of, + C2::Time_stamper_impl>::value) + { + std::cerr << "Error timestamper of C2\n"; return 1; + } + if(! boost::is_base_of, + C3::Time_stamper_impl>::value) + { + std::cerr << "Error timestamper of C3\n"; return 1; + } + if(! boost::is_base_of, + 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) > 0); + + // Test increment policy + CGAL::Compact_container > C5; + CGAL::Compact_container > C6; + + test_index(C5); + test_index(C6); return 0; } // EOF // diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 4f25a549d69..9518ff61968 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -3300,11 +3300,11 @@ void Triangulation_3:: 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){