mirror of https://github.com/CGAL/cgal
506 lines
15 KiB
C++
506 lines
15 KiB
C++
// Copyright (c) 2005 INRIA Sophia-Antipolis (France)
|
|
// All rights reserved.
|
|
//
|
|
// Authors : Monique Teillaud <Monique.Teillaud@sophia.inria.fr>
|
|
// Sylvain Pion <Sylvain.Pion@sophia.inria.fr>
|
|
// Julien Hazebrouck
|
|
//
|
|
// Partially supported by the IST Programme of the EU as a Shared-cost
|
|
// RTD (FET Open) Project under Contract No IST-2000-26473
|
|
// (ECG - Effective Computational Geometry for Curves and Surfaces)
|
|
// and a STREP (FET Open) Project under Contract No IST-006413
|
|
// (ACS -- Algorithms for Complex Shapes)
|
|
|
|
// file : include/CGAL/Line_arc_traits.h
|
|
|
|
#ifndef CGAL_VARIANT_TRAITS_H
|
|
#define CGAL_VARIANT_TRAITS_H
|
|
|
|
#include <CGAL/basic.h>
|
|
#include <cassert>
|
|
#include <boost/variant.hpp>
|
|
|
|
namespace CGAL {
|
|
namespace VariantFunctors{
|
|
|
|
// Takes an iterator range of Object(Line/Circular_arc),
|
|
// returns an Object(Variant(Line/Circular_arc)).
|
|
// Do nothing for Object(Endpoint).
|
|
template <class CK, class Arc1, class Arc2, class OutputIterator>
|
|
OutputIterator object_to_object_variant(const std::vector<CGAL::Object>& res1, OutputIterator res2){
|
|
|
|
for(std::vector<CGAL::Object>::const_iterator it = res1.begin();
|
|
it != res1.end(); ++it ){
|
|
if(const Arc1 *arc = CGAL::object_cast< Arc1 >(&*it)){
|
|
boost::variant< Arc1, Arc2 > v = *arc;
|
|
*res2++ = make_object(v);
|
|
}
|
|
else if (const Arc2 *line = CGAL::object_cast< Arc2 >(&*it)){
|
|
boost::variant< Arc1, Arc2 > v = *line;
|
|
*res2++ = make_object(v);
|
|
}
|
|
else{
|
|
*res2++ = *it;
|
|
}
|
|
}
|
|
return res2;
|
|
}
|
|
|
|
|
|
template <class CircularKernel, class Arc1, class Arc2>
|
|
class In_range_2
|
|
{
|
|
public:
|
|
typedef typename CircularKernel::Circular_arc_point_2 Circular_arc_point_2;
|
|
typedef bool result_type;
|
|
|
|
result_type
|
|
operator()(const boost::variant< Arc1, Arc2 > &a,
|
|
const Circular_arc_point_2 &p) const
|
|
{
|
|
if ( const Arc1* arc1 = boost::get<Arc1>( &a ) ){
|
|
return CircularKernel().in_range_2_object()(*arc1, p);
|
|
}
|
|
else {
|
|
const Arc2* arc2 = boost::get<Arc2>( &a );
|
|
return CircularKernel().in_range_2_object()(*arc2, p);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
template <class CircularKernel, class Arc1, class Arc2>
|
|
class Compare_y_to_right_2
|
|
{
|
|
public:
|
|
typedef CGAL::Comparison_result result_type;
|
|
typedef typename CircularKernel::Circular_arc_point_2 Circular_arc_point_2;
|
|
|
|
result_type
|
|
operator()(const boost::variant< Arc1, Arc2 > &a1,
|
|
const boost::variant< Arc1, Arc2 > &a2,
|
|
const Circular_arc_point_2 &p) const
|
|
{
|
|
if ( const Arc1* arc1 = boost::get<Arc1>( &a1 ) ){
|
|
if ( const Arc1* arc2 = boost::get<Arc1>( &a2 ) ){
|
|
return CircularKernel().compare_y_to_right_2_object()(*arc1, *arc2, p);
|
|
}
|
|
else {
|
|
const Arc2* arc2 = boost::get<Arc2>( &a2 );
|
|
return CircularKernel().compare_y_to_right_2_object()(*arc1, *arc2, p);
|
|
}
|
|
}
|
|
const Arc2* arc1 = boost::get<Arc2>( &a1 );
|
|
if ( const Arc1* arc2 = boost::get<Arc1>( &a2 ) ){
|
|
return CircularKernel().compare_y_to_right_2_object()(*arc1, *arc2, p);
|
|
}
|
|
const Arc2* arc2 = boost::get<Arc2>( &a2 );
|
|
return CircularKernel().compare_y_to_right_2_object()(*arc1, *arc2, p);
|
|
|
|
}
|
|
};
|
|
|
|
|
|
template <class CircularKernel>
|
|
class Variant_Equal_2
|
|
: public boost::static_visitor<bool>
|
|
{
|
|
public :
|
|
|
|
template < typename T >
|
|
bool
|
|
operator()(const T &a0, const T &a1) const
|
|
{
|
|
return CircularKernel().equal_2_object()(a0,a1);
|
|
}
|
|
|
|
template < typename T1, typename T2 >
|
|
bool
|
|
operator()(const T1 &, const T2 &) const
|
|
{
|
|
return false;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
template <class CircularKernel, class Arc1, class Arc2>
|
|
class Equal_2
|
|
: public
|
|
CircularKernel::Equal_2
|
|
{
|
|
public:
|
|
typedef boost::variant< Arc1, Arc2 > Curve_2;
|
|
typedef bool result_type;
|
|
|
|
using CircularKernel::Equal_2::operator();
|
|
|
|
result_type
|
|
operator()(const Curve_2 &a0, const Curve_2 &a1) const
|
|
{
|
|
return boost::apply_visitor( Variant_Equal_2<CircularKernel>(), a0, a1 );
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <class CircularKernel, class Arc1, class Arc2>
|
|
class Compare_y_at_x_2
|
|
{
|
|
public:
|
|
typedef typename CircularKernel::Circular_arc_point_2 Circular_arc_point_2;
|
|
typedef CGAL::Comparison_result result_type;
|
|
|
|
result_type
|
|
operator() (const Circular_arc_point_2 &p,
|
|
const boost::variant< Arc1, Arc2 > &A1) const
|
|
{
|
|
if ( const Arc1* arc1 = boost::get<Arc1>( &A1 ) ){
|
|
return CircularKernel().compare_y_at_x_2_object()(p, *arc1);
|
|
}
|
|
else {
|
|
const Arc2* arc2 = boost::get<Arc2>( &A1 );
|
|
return CircularKernel().compare_y_at_x_2_object()(p, *arc2);
|
|
}
|
|
}
|
|
};
|
|
|
|
template <class CircularKernel>
|
|
class Variant_Do_overlap_2
|
|
: public boost::static_visitor<bool>
|
|
{
|
|
public :
|
|
|
|
template < typename T >
|
|
bool
|
|
operator()(const T &a0, const T &a1) const
|
|
{
|
|
return CircularKernel().do_overlap_2_object()(a0, a1);
|
|
}
|
|
|
|
template < typename T1, typename T2 >
|
|
bool
|
|
operator()(const T1 &, const T2 &) const
|
|
{
|
|
return false;
|
|
}
|
|
};
|
|
|
|
|
|
template <class CircularKernel, class Arc1, class Arc2>
|
|
class Do_overlap_2
|
|
{
|
|
public:
|
|
typedef typename CircularKernel::Circular_arc_point_2 Circular_arc_point_2;
|
|
typedef bool result_type;
|
|
|
|
result_type
|
|
operator()(const boost::variant< Arc1, Arc2 > &A0,
|
|
const boost::variant< Arc1, Arc2 > &A1) const
|
|
{
|
|
return boost::apply_visitor( Variant_Do_overlap_2<CircularKernel>(), A0, A1 );
|
|
}
|
|
};
|
|
|
|
|
|
template <class CircularKernel, class Arc1, class Arc2>
|
|
class Make_x_monotone_2
|
|
{
|
|
public:
|
|
typedef typename CircularKernel::Circular_arc_point_2 Circular_arc_point_2;
|
|
|
|
template < class OutputIterator >
|
|
OutputIterator
|
|
operator()(const boost::variant< Arc1, Arc2 > &A, OutputIterator res)
|
|
{ if ( const Arc1* arc1 = boost::get<Arc1>( &A ) ){
|
|
std::vector<CGAL::Object> container;
|
|
CircularKernel().make_x_monotone_2_object()(*arc1, std::back_inserter(container));
|
|
return object_to_object_variant<CircularKernel, Arc1, Arc2>(container, res);
|
|
}
|
|
else {
|
|
const Arc2* arc2 = boost::get<Arc2>( &A );
|
|
std::vector<CGAL::Object> container;
|
|
CircularKernel().make_x_monotone_2_object()(*arc2, std::back_inserter(container));
|
|
return object_to_object_variant<CircularKernel, Arc1, Arc2>(container, res);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
|
|
template <class CircularKernel, class Arc1, class Arc2>
|
|
class Intersect_2
|
|
{
|
|
public:
|
|
typedef typename CircularKernel::Circular_arc_point_2 Circular_arc_point_2;
|
|
|
|
template < class OutputIterator >
|
|
OutputIterator
|
|
operator()(const boost::variant< Arc1, Arc2 > &c1,
|
|
const boost::variant< Arc1, Arc2 > &c2,
|
|
OutputIterator res) const
|
|
{
|
|
if ( const Arc1* arc1 = boost::get<Arc1>( &c1 ) ){
|
|
if ( const Arc1* arc2 = boost::get<Arc1>( &c2 ) ){
|
|
std::vector<CGAL::Object> container;
|
|
CircularKernel().intersect_2_object()(*arc1,*arc2, std::back_inserter(container));
|
|
return object_to_object_variant<CircularKernel, Arc1, Arc2>(container, res);
|
|
}
|
|
else if ( const Arc2* arc2 = boost::get<Arc2>( &c2 ) ){
|
|
std::vector<CGAL::Object> container;
|
|
CircularKernel().intersect_2_object()(*arc1,*arc2, std::back_inserter(container));
|
|
return object_to_object_variant<CircularKernel, Arc1, Arc2>(container, res);
|
|
}
|
|
}
|
|
else {
|
|
const Arc2* arc1 = boost::get<Arc2>( &c1 );
|
|
if ( const Arc1* arc2 = boost::get<Arc1>( &c2 ) ){
|
|
std::vector<CGAL::Object> container;
|
|
CircularKernel().intersect_2_object()(*arc1,*arc2, std::back_inserter(container));
|
|
return object_to_object_variant<CircularKernel, Arc1, Arc2>(container, res);
|
|
}
|
|
const Arc2* arc2 = boost::get<Arc2>( &c2 );
|
|
std::vector<CGAL::Object> container;
|
|
CircularKernel().intersect_2_object()(*arc1,*arc2, std::back_inserter(container));
|
|
return object_to_object_variant<CircularKernel, Arc1, Arc2>(container, res);
|
|
}
|
|
abort();
|
|
return res;//for no warning
|
|
}
|
|
|
|
};
|
|
|
|
|
|
template <class CircularKernel, class Arc1, class Arc2>
|
|
class Split_2
|
|
{
|
|
|
|
public:
|
|
typedef typename CircularKernel::Circular_arc_point_2 Circular_arc_point_2;
|
|
typedef void result_type;
|
|
result_type
|
|
operator()(const boost::variant< Arc1, Arc2 > &A,
|
|
const Circular_arc_point_2 &p,
|
|
boost::variant< Arc1, Arc2 > &ca1,
|
|
boost::variant< Arc1, Arc2 > &ca2) const
|
|
{
|
|
// TODO : optimize by extracting the references from the variants ?
|
|
if ( const Arc1* arc1 = boost::get<Arc1>( &A ) ){
|
|
Arc1 carc1;
|
|
Arc1 carc2;
|
|
CircularKernel().split_2_object()(*arc1, p, carc1, carc2);
|
|
ca1 = carc1;
|
|
ca2 = carc2;
|
|
return ;
|
|
|
|
}
|
|
else{
|
|
const Arc2* arc2 = boost::get<Arc2>( &A );
|
|
Arc2 cline1;
|
|
Arc2 cline2;
|
|
CircularKernel().split_2_object()(*arc2, p, cline1, cline2);
|
|
ca1 = cline1;
|
|
ca2 = cline2;
|
|
return ;
|
|
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
template <class CircularKernel>
|
|
class Variant_Construct_min_vertex_2
|
|
: public boost::static_visitor<const typename CircularKernel::Circular_arc_point_2&>
|
|
{
|
|
typedef typename CircularKernel::Circular_arc_point_2 Circular_arc_point_2;
|
|
|
|
public :
|
|
|
|
typedef Circular_arc_point_2 result_type;
|
|
//typedef const result_type& qualified_result_type;
|
|
|
|
template < typename T >
|
|
//typename boost::remove_reference<qualified_result_type>::type
|
|
Circular_arc_point_2
|
|
operator()(const T &a) const
|
|
{
|
|
//CGAL_kernel_precondition(CircularKernel().compare_xy_2_object()(a.left(), a.right())==CGAL::SMALLER);
|
|
return CircularKernel().construct_circular_min_vertex_2_object()(a);
|
|
}
|
|
};
|
|
|
|
template <class CircularKernel, class Arc1, class Arc2>
|
|
class Construct_min_vertex_2//: public Has_qrt
|
|
{
|
|
typedef typename CircularKernel::Circular_arc_point_2 Point_2;
|
|
public:
|
|
|
|
typedef Point_2 result_type;
|
|
//typedef const result_type& qualified_result_type;
|
|
|
|
//typename boost::remove_reference<qualified_result_type>::type
|
|
result_type
|
|
operator() (const boost::variant< Arc1, Arc2 > & cv) const
|
|
{
|
|
return boost::apply_visitor( Variant_Construct_min_vertex_2<CircularKernel>(), cv );
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <class CircularKernel>
|
|
class Variant_Construct_max_vertex_2
|
|
: public boost::static_visitor<const typename CircularKernel::Circular_arc_point_2&>
|
|
{
|
|
typedef typename CircularKernel::Circular_arc_point_2 Circular_arc_point_2;
|
|
|
|
public :
|
|
|
|
typedef Circular_arc_point_2 result_type;
|
|
//typedef const result_type& qualified_result_type;
|
|
|
|
template < typename T >
|
|
//typename boost::remove_reference<qualified_result_type>::type
|
|
Circular_arc_point_2
|
|
operator()(const T &a) const
|
|
{
|
|
//CGAL_kernel_precondition(CircularKernel().compare_xy_2_object()(a.left(), a.right())==CGAL::SMALLER);
|
|
return (CircularKernel().construct_circular_max_vertex_2_object()(a));
|
|
}
|
|
};
|
|
|
|
|
|
|
|
template <class CircularKernel, class Arc1, class Arc2>
|
|
class Construct_max_vertex_2//: public Has_qrt
|
|
{
|
|
typedef typename CircularKernel::Circular_arc_point_2 Point_2;
|
|
public:
|
|
/*!
|
|
* Get the right endpoint of the x-monotone curve (segment).
|
|
* \param cv The curve.
|
|
* \return The right endpoint.
|
|
*/
|
|
typedef Point_2 result_type;
|
|
//typedef const result_type& qualified_result_type;
|
|
|
|
//typename boost::remove_reference<qualified_result_type>::type
|
|
result_type
|
|
operator() (const boost::variant< Arc1, Arc2 > & cv) const
|
|
{
|
|
return boost::apply_visitor( Variant_Construct_max_vertex_2<CircularKernel>(), cv );
|
|
}
|
|
};
|
|
|
|
template <class CircularKernel>
|
|
class Variant_Is_vertical_2
|
|
: public boost::static_visitor<bool>
|
|
{
|
|
public :
|
|
|
|
template < typename T >
|
|
bool
|
|
operator()(const T &a) const
|
|
{
|
|
return CircularKernel().is_vertical_2_object()(a);
|
|
}
|
|
};
|
|
|
|
template <class CircularKernel, class Arc1, class Arc2>
|
|
class Is_vertical_2
|
|
{
|
|
public:
|
|
typedef bool result_type;
|
|
|
|
bool operator() (const boost::variant< Arc1, Arc2 >& cv) const
|
|
{
|
|
return boost::apply_visitor( Variant_Is_vertical_2<CircularKernel>(), cv );
|
|
}
|
|
};
|
|
|
|
}
|
|
/// Traits class for CGAL::Arrangement_2 (and similar) based on a CircularKernel.
|
|
|
|
template < typename CircularKernel, typename Arc1, typename Arc2>
|
|
class Variant_traits {
|
|
|
|
typedef Variant_traits< CircularKernel, Arc1, Arc2 > Self;
|
|
|
|
public:
|
|
|
|
typedef CircularKernel Kernel;
|
|
typedef typename CircularKernel::Circular_arc_point_2 Circular_arc_point_2;
|
|
|
|
typedef typename CircularKernel::Circular_arc_point_2 Point;
|
|
typedef typename CircularKernel::Circular_arc_point_2 Point_2;
|
|
|
|
typedef CGAL::Tag_false Has_left_category;
|
|
typedef CGAL::Tag_false Has_merge_category;
|
|
|
|
typedef boost::variant< Arc1, Arc2 > Curve_2;
|
|
typedef boost::variant< Arc1, Arc2 > X_monotone_curve_2;
|
|
|
|
private:
|
|
CircularKernel ck;
|
|
public:
|
|
|
|
Variant_traits(const CircularKernel &k = CircularKernel())
|
|
: ck(k) {}
|
|
|
|
typedef typename CircularKernel::Compare_x_2 Compare_x_2;
|
|
typedef typename CircularKernel::Compare_xy_2 Compare_xy_2;
|
|
typedef typename VariantFunctors::Construct_min_vertex_2<CircularKernel, Arc1, Arc2> Construct_min_vertex_2;
|
|
typedef VariantFunctors::Construct_max_vertex_2<CircularKernel, Arc1, Arc2> Construct_max_vertex_2;
|
|
typedef VariantFunctors::Is_vertical_2<CircularKernel, Arc1, Arc2> Is_vertical_2;
|
|
typedef VariantFunctors::Compare_y_at_x_2<CircularKernel, Arc1, Arc2> Compare_y_at_x_2;
|
|
typedef VariantFunctors::Compare_y_to_right_2<CircularKernel, Arc1, Arc2> Compare_y_at_x_right_2;
|
|
typedef VariantFunctors::Equal_2<CircularKernel, Arc1, Arc2> Equal_2;
|
|
typedef VariantFunctors::Make_x_monotone_2<CircularKernel, Arc1, Arc2> Make_x_monotone_2;
|
|
typedef VariantFunctors::Split_2<CircularKernel, Arc1, Arc2> Split_2;
|
|
typedef VariantFunctors::Intersect_2<CircularKernel, Arc1, Arc2> Intersect_2;
|
|
|
|
|
|
Compare_x_2 compare_x_2_object() const
|
|
{ return ck.compare_x_2_object(); }
|
|
|
|
Compare_xy_2 compare_xy_2_object() const
|
|
{ return ck.compare_xy_2_object(); }
|
|
|
|
Compare_y_at_x_2 compare_y_at_x_2_object() const
|
|
{ return Compare_y_at_x_2(); }
|
|
|
|
Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const
|
|
{ return Compare_y_at_x_right_2(); }
|
|
|
|
Equal_2 equal_2_object() const
|
|
{ return Equal_2(); }
|
|
|
|
Make_x_monotone_2 make_x_monotone_2_object() const
|
|
{ return Make_x_monotone_2(); }
|
|
|
|
Split_2 split_2_object() const
|
|
{ return Split_2(); }
|
|
|
|
Intersect_2 intersect_2_object() const
|
|
{ return Intersect_2(); }
|
|
|
|
Construct_min_vertex_2 construct_min_vertex_2_object() const
|
|
{ return Construct_min_vertex_2(); }
|
|
|
|
Construct_max_vertex_2 construct_max_vertex_2_object() const
|
|
{ return Construct_max_vertex_2(); }
|
|
|
|
Is_vertical_2 is_vertical_2_object() const
|
|
{ return Is_vertical_2();}
|
|
|
|
|
|
};
|
|
|
|
} // namespace CGAL
|
|
|
|
#endif // CGAL_VARIANT_TRAITS_H
|