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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -46,6 +46,7 @@
#include <CGAL/Timer.h>
#include <CGAL/Mesh_3/Null_perturber_visitor.h>
#include <CGAL/Mesh_3/sliver_criteria.h>
#include <CGAL/Has_timestamp.h>
#include <boost/format.hpp>
#ifdef CGAL_MESH_3_USE_RELAXED_HEAP
@ -61,8 +62,31 @@
namespace CGAL {
namespace internal { namespace Mesh_3 {
// Hash function for boost::unordered_map<Vertex_handle,...>
template <typename Tr, bool HasTimestamp>
struct VHash
{
typedef typename Tr::Vertex_handle Vertex_handle;
std::size_t operator()(Vertex_handle vh) const
{
return vh->time_stamp();
}
};
template <typename Tr>
struct VHash<Tr, false>
{
typedef typename Tr::Vertex_handle Vertex_handle;
std::size_t operator()(Vertex_handle vh) const
{
return boost::hash_value(&*vh);
}
};
}} // end internal::Mesh_3
namespace Mesh_3 {
template < typename C3T3,
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<Vertex_handle,PVertex,VHash> M;
typedef typename std::iterator_traits<Vertex_handle>::value_type Vertex;
typedef CGAL::internal::Has_timestamp<Vertex> Vertex_has_timestamp;
using CGAL::internal::Mesh_3::VHash;
typedef VHash<Tr, Vertex_has_timestamp::value> Hash_fct;
typedef boost::unordered_map<Vertex_handle,PVertex,Hash_fct> M;
M vpm;
for ( typename Tr::Finite_cells_iterator cit = tr_.finite_cells_begin();
cit != tr_.finite_cells_end() ;

View File

@ -33,6 +33,7 @@
#include <CGAL/Regular_triangulation_cell_base_with_weighted_circumcenter_3.h>
#include <CGAL/Mesh_3/Mesh_surface_cell_base_3.h>
#include <CGAL/Mesh_3/io_signature.h>
#include <CGAL/tags.h>
namespace CGAL {
@ -83,6 +84,7 @@ public:
, next_intrusive_()
, previous_intrusive_()
#endif
, time_stamp_(-1)
{}
Mesh_cell_base_3 (Vertex_handle v0,
@ -97,6 +99,7 @@ public:
, next_intrusive_()
, previous_intrusive_()
#endif
, time_stamp_(-1)
{}
Mesh_cell_base_3 (Vertex_handle v0,
@ -115,6 +118,7 @@ public:
, next_intrusive_()
, previous_intrusive_()
#endif
, time_stamp_(-1)
{}
// Default copy constructor and assignment operator are ok
@ -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,

View File

@ -54,13 +54,13 @@ class Polyline
typedef typename Kernel::FT FT;
typedef std::vector<Point_3> 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 <typename T1, typename T2>
CGAL::Sign compare_distance(const Point_3& p,
const T1& obj1,
@ -345,7 +345,7 @@ private:
public:
Data points_;
}; // end class Polyline
template <typename Gt, typename MapIterator>
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<MapIterator,
typedef std::pair<MapIterator,
typename Polyline::const_iterator> 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 <typename ... T>
Mesh_domain_with_polyline_features_3(const T& ...t)
@ -472,11 +472,11 @@ public:
, curves_aabb_tree_is_built(false) {}
template <typename T1, typename T2, typename T3>
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<Corner_index, Point_3>
template <typename OutputIterator>
OutputIterator get_corners(OutputIterator out) const;
/// OutputIterator value type is CGAL::cpp11::tuple<Curve_segment_index,
/// std::pair<Point_3,Index>, std::pair<Point_3,Index> >
template <typename OutputIterator>
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<Curve_segment_index>(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<Corner_index>(index); }
@ -549,20 +549,20 @@ public:
template <typename IndicesOutputIterator>
IndicesOutputIterator
get_incidences(Curve_segment_index id, IndicesOutputIterator out) const;
template <typename IndicesOutputIterator>
IndicesOutputIterator
get_corner_incidences(Curve_segment_index id, IndicesOutputIterator out) const;
typedef std::set<Surface_patch_index> 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 <typename InputIterator>
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<Gt,
typedef CGAL::AABB_traits<Gt,
Curves_primitives> 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 <class MD_>
typename Mesh_domain_with_polyline_features_3<MD_>::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<MD_>::
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 <class MD_>
const typename Mesh_domain_with_polyline_features_3<MD_>::Surface_patch_index_set&
const typename Mesh_domain_with_polyline_features_3<MD_>::Surface_patch_index_set&
Mesh_domain_with_polyline_features_3<MD_>::
get_incidences(Curve_segment_index id) const
{
@ -952,7 +952,7 @@ void
Mesh_domain_with_polyline_features_3<MD_>::
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<MD_>::
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<typename Edges::iterator,bool> 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();
}

View File

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

View File

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

View File

@ -36,6 +36,7 @@
#include <CGAL/AABB_traits.h>
#include <sstream>
#include <CGAL/Random.h>
#include <CGAL/point_generators_3.h>
#include <CGAL/Mesh_3/Creator_weighted_point_3.h>
#include <CGAL/Mesh_3/Profile_counter.h>
@ -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<Subdomain_index,Subdomain_index> 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<Subdomain_index, Polyhedron, CGAL::Tag_true>
{
@ -113,10 +114,10 @@ struct Index_generator<T, T>
// -----------------------------------
// Geometric traits generator
// -----------------------------------
template < typename Gt,
template < typename Gt,
typename Use_exact_intersection_construction_tag >
struct IGT_generator {};
template < typename Gt >
struct IGT_generator<Gt,CGAL::Tag_true>
{
@ -127,14 +128,14 @@ struct IGT_generator<Gt,CGAL::Tag_true>
#endif // NOT CGAL_MESH_3_NEW_ROBUST_INTERSECTION_TRAITS
typedef type Type;
};
template < typename Gt >
struct IGT_generator<Gt,CGAL::Tag_false>
{
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 <typename InputPolyhedraPtrIterator>
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 <typename InputPolyhedraPtrIterator>
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<Segment_3, Ray_3, Line_3> Allowed_query_types;
@ -376,10 +416,10 @@ public:
boost::optional<AABB_primitive_id> 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<Subdomain_index>(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 <typename Query>
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<typename P_, typename IGT_, typename TA, typename Tag, typename E_tag_>
template<typename P_, typename IGT_, typename TA,
typename Tag, typename E_tag_>
template<class OutputIterator>
OutputIterator
Polyhedral_mesh_domain_3<P_,IGT_,TA,Tag,E_tag_>::
@ -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<Point_3> random_point(1.);
CGAL::Random& rng = *(r_domain_.p_rng_);
Random_points_on_sphere_3<Point_3> random_point(1., rng);
int i = n;
#ifdef CGAL_MESH_3_VERBOSE
@ -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<typename P_, typename IGT_, typename TA, typename Tag, typename E_tag_>
template<typename P_, typename IGT_, typename TA,
typename Tag, typename E_tag_>
typename Polyhedral_mesh_domain_3<P_,IGT_,TA,Tag,E_tag_>::Subdomain
Polyhedral_mesh_domain_3<P_,IGT_,TA,Tag,E_tag_>::
Is_in_domain::operator()(const Point_3& p) const

View File

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

View File

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

View File

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

View File

@ -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<Image, K> Mesh_domain;
typedef typename CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
typedef CGAL::Mesh_criteria_3<Tr> 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<C3t3>(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<K_e_i> test_epic;
std::cerr << "Mesh generation from a 3D image:\n";
test_epic.image();
return EXIT_SUCCESS;
return EXIT_SUCCESS;
}

View File

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

View File

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

View File

@ -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<K>
typedef K Gt;
typedef CGAL::Polyhedron_3<Gt> Polyhedron;
typedef CGAL::Polyhedral_mesh_domain_3<Polyhedron, Gt> Mesh_domain;
typedef typename CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
typedef CGAL::Mesh_criteria_3<Tr> 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<K>
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<K_e_i> test_epic;
std::cerr << "Mesh generation from a polyhedron:\n";
test_epic.polyhedron();
return EXIT_SUCCESS;
}

View File

@ -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<K>
{
typedef CGAL::Mesh_3::Robust_intersection_traits_3<K> Gt;
typedef CGAL::Polyhedral_mesh_domain_with_features_3<Gt> Mesh_domain;
typedef typename CGAL::Mesh_triangulation_3<Mesh_domain>::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<Tr> 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<K>
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(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<K>
std::ios_base::in|std::ios_base::binary);
CGAL::Mesh_3::load_binary_file(in_binary, c3t3_bis);
assert(c3t3_bis.triangulation() == c3t3.triangulation());
}
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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