// Copyright (c) 2005 INRIA Sophia-Antipolis (France) // All rights reserved. // // Authors : Monique Teillaud // Sylvain Pion // 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 #include #include 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 OutputIterator object_to_object_variant(const std::vector& res1, OutputIterator res2){ for(std::vector::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 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( &a ) ){ return CircularKernel().in_range_2_object()(*arc1, p); } else { const Arc2* arc2 = boost::get( &a ); return CircularKernel().in_range_2_object()(*arc2, p); } } }; template 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( &a1 ) ){ if ( const Arc1* arc2 = boost::get( &a2 ) ){ return CircularKernel().compare_y_to_right_2_object()(*arc1, *arc2, p); } else { const Arc2* arc2 = boost::get( &a2 ); return CircularKernel().compare_y_to_right_2_object()(*arc1, *arc2, p); } } const Arc2* arc1 = boost::get( &a1 ); if ( const Arc1* arc2 = boost::get( &a2 ) ){ return CircularKernel().compare_y_to_right_2_object()(*arc1, *arc2, p); } const Arc2* arc2 = boost::get( &a2 ); return CircularKernel().compare_y_to_right_2_object()(*arc1, *arc2, p); } }; template class Variant_Equal_2 : public boost::static_visitor { 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 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(), a0, a1 ); } }; template 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( &A1 ) ){ return CircularKernel().compare_y_at_x_2_object()(p, *arc1); } else { const Arc2* arc2 = boost::get( &A1 ); return CircularKernel().compare_y_at_x_2_object()(p, *arc2); } } }; template class Variant_Do_overlap_2 : public boost::static_visitor { 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 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(), A0, A1 ); } }; template 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( &A ) ){ std::vector container; CircularKernel().make_x_monotone_2_object()(*arc1, std::back_inserter(container)); return object_to_object_variant(container, res); } else { const Arc2* arc2 = boost::get( &A ); std::vector container; CircularKernel().make_x_monotone_2_object()(*arc2, std::back_inserter(container)); return object_to_object_variant(container, res); } } }; template 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( &c1 ) ){ if ( const Arc1* arc2 = boost::get( &c2 ) ){ std::vector container; CircularKernel().intersect_2_object()(*arc1,*arc2, std::back_inserter(container)); return object_to_object_variant(container, res); } else if ( const Arc2* arc2 = boost::get( &c2 ) ){ std::vector container; CircularKernel().intersect_2_object()(*arc1,*arc2, std::back_inserter(container)); return object_to_object_variant(container, res); } } else { const Arc2* arc1 = boost::get( &c1 ); if ( const Arc1* arc2 = boost::get( &c2 ) ){ std::vector container; CircularKernel().intersect_2_object()(*arc1,*arc2, std::back_inserter(container)); return object_to_object_variant(container, res); } const Arc2* arc2 = boost::get( &c2 ); std::vector container; CircularKernel().intersect_2_object()(*arc1,*arc2, std::back_inserter(container)); return object_to_object_variant(container, res); } abort(); return res;//for no warning } }; template 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( &A ) ){ Arc1 carc1; Arc1 carc2; CircularKernel().split_2_object()(*arc1, p, carc1, carc2); ca1 = carc1; ca2 = carc2; return ; } else{ const Arc2* arc2 = boost::get( &A ); Arc2 cline1; Arc2 cline2; CircularKernel().split_2_object()(*arc2, p, cline1, cline2); ca1 = cline1; ca2 = cline2; return ; } } }; template class Variant_Construct_min_vertex_2 : public boost::static_visitor { 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::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 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::type result_type operator() (const boost::variant< Arc1, Arc2 > & cv) const { return boost::apply_visitor( Variant_Construct_min_vertex_2(), cv ); } }; template class Variant_Construct_max_vertex_2 : public boost::static_visitor { 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::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 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::type result_type operator() (const boost::variant< Arc1, Arc2 > & cv) const { return boost::apply_visitor( Variant_Construct_max_vertex_2(), cv ); } }; template class Variant_Is_vertical_2 : public boost::static_visitor { public : template < typename T > bool operator()(const T &a) const { return CircularKernel().is_vertical_2_object()(a); } }; template 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(), 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 Construct_min_vertex_2; typedef VariantFunctors::Construct_max_vertex_2 Construct_max_vertex_2; typedef VariantFunctors::Is_vertical_2 Is_vertical_2; typedef VariantFunctors::Compare_y_at_x_2 Compare_y_at_x_2; typedef VariantFunctors::Compare_y_to_right_2 Compare_y_at_x_right_2; typedef VariantFunctors::Equal_2 Equal_2; typedef VariantFunctors::Make_x_monotone_2 Make_x_monotone_2; typedef VariantFunctors::Split_2 Split_2; typedef VariantFunctors::Intersect_2 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