diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/Circular_arc_2.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/Circular_arc_2.h new file mode 100644 index 00000000000..ee6a23ed59f --- /dev/null +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/Circular_arc_2.h @@ -0,0 +1,726 @@ +// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// 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. +// +// $URL$ +// $Id$ +// +// Author(s) : Monique Teillaud, Sylvain Pion + +// 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) +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE +#define CGAL_USEFUL_MAPS_FOR_THE_CIRCULAR_KERNEL +#endif + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES +#define CGAL_USEFUL_MAPS_FOR_THE_CIRCULAR_KERNEL +#endif + +#ifndef CGAL_CIRCULAR_KERNEL_CIRCULAR_ARC_2_H +#define CGAL_CIRCULAR_KERNEL_CIRCULAR_ARC_2_H + +#include +#include // temporarily + +#ifdef CGAL_USEFUL_MAPS_FOR_THE_CIRCULAR_KERNEL +#include +#endif + +#include + +namespace CGAL { +namespace CGALi { + + template + class Circular_arc_2 + { + typedef typename CK::FT FT; + typedef typename CK::RT RT; + typedef typename CK::Point_2 Point_2; + typedef typename CK::Line_2 Line_2; + typedef typename CK::Circle_2 Circle_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Root_of_2 Root_of_2; + typedef struct bit_field { + unsigned short int is_full:2; + unsigned short int is_x_monotonic:2; + unsigned short int is_y_monotonic:2; + unsigned short int two_end_points_on_upper_part:2; + unsigned short int two_end_points_on_left_part:2; + unsigned short int is_complementary_x_monotone:1; + unsigned short int is_complementary_y_monotone:1; + } bit_field; + +#ifdef CGAL_USEFUL_MAPS_FOR_THE_CIRCULAR_KERNEL + public: + typedef CGALi::Intersection_line_2_circle_2_map Table; +#endif + + private: + + // set flags to 0 + // when 1 bit -> 0 = false, 1 = true + // when 2 bits -> 0 = don_know, 1 = false + // 2 = true + void reset_flags() const { + flags.is_full = 0; + flags.is_x_monotonic = 0; + flags.is_y_monotonic = 0; + flags.two_end_points_on_upper_part = 0; + flags.two_end_points_on_left_part = 0; + flags.is_complementary_x_monotone = 0; + flags.is_complementary_y_monotone = 0; + } + + public: + + Circular_arc_2() +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + : id_of_my_supporting_circle(0) +#endif + { + reset_flags(); // example + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + _get_id_number(); +#endif + + } + + Circular_arc_2(const Circle_2 &c) + : _support(c) +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + , id_of_my_supporting_circle(0) +#endif + { + reset_flags(); // example + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + _get_id_number(); +#endif + + flags.is_full = 2; // is_full = true + _begin = _end = + CircularFunctors::x_extremal_point(supporting_circle(),true); + } + + Circular_arc_2(const Circle_2 &support, + const Line_2 &l1, bool b1, + const Line_2 &l2, bool b2) + { + Point_2 center1 (support.center().x() + l1.a()/2, + support.center().y() + l1.b()/2); + + FT sqr1 = support.squared_radius() + l1.c() + - CGAL::square(support.center().x()) + - CGAL::square(support.center().y()) + + CGAL::square(center1.x()) + + CGAL::square(center1.y()); + + Circle_2 c1 (center1, sqr1); + + Point_2 center2 (support.center().x() + l2.a()/2, + support.center().y() + l2.b()/2); + + FT sqr2 = support.squared_radius() + l2.c() + - CGAL::square(support.center().x()) + - CGAL::square(support.center().y()) + + CGAL::square(center2.x()) + + CGAL::square(center2.y()); + + Circle_2 c2 (center2, sqr2); + + *this = Circular_arc_2(support, c1, b1, c2, b2); + + CGAL_kernel_assertion(do_intersect(support, c1)); + CGAL_kernel_assertion(do_intersect(support, c2)); + } + + + Circular_arc_2(const Circle_2 &c, + const Circle_2 &c1, const bool b_1, + const Circle_2 &c2, const bool b_2) + : _support(c) +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + , id_of_my_supporting_circle(0) +#endif + { + reset_flags(); + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + _get_id_number(); +#endif + + if (c1 != c2) { + _begin = CGAL::circle_intersect(c, c1, b_1); + _end = CGAL::circle_intersect(c, c2, b_2); + } + else{ + typedef std::vector solutions_container; + + solutions_container solutions; + CGAL::intersect_2( c, c1, std::back_inserter(solutions) ); + typename solutions_container::iterator it = solutions.begin(); + + CGAL_kernel_precondition( it != solutions.end() ); + // the circles intersect + + const std::pair *result; + result = CGAL::object_cast< + std::pair > (&(*it)); + if ( result->second == 2 ){ // double solution + _begin = result->first; + _end = result->first; + } + else{ + if (b_1) + _begin = result->first; + if (b_2) + _end = result->first; + if (!(b_1 & b_2)) { + ++it; + result = CGAL::object_cast< + std::pair >(&(*it)); + if (!b_1) + _begin = result->first; + if (!b_2) + _end = result->first; + } + } + } + } + + // IS THIS CONSTRUCTOR USED ? + // constructs a circular arc that is the arc included in A + // having same (b) endpoint as A (true == _begin, false == _end) + // but whose (!b) endpoint is the intersection of A with ccut given + // by b_cut + Circular_arc_2(const Circular_arc_2 &A, const bool b, + const Circle_2 &ccut, const bool b_cut) + : _support(A.supporting_circle()) +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + , id_of_my_supporting_circle(0) +#endif + { + reset_flags(); + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + _get_id_number(); +#endif + + CGAL_kernel_precondition(A.is_x_monotone()); + CGAL_kernel_precondition(do_intersect(A.supporting_circle(), ccut)); + + Circular_arc_point_2 new_p = + CGAL::circle_intersect(A.supporting_circle(), ccut, b_cut); + + // CGAL_kernel_assertion(point_in_range(A, new_p)); + CGAL_kernel_assertion + (A.on_upper_part() == (CGAL::compare(new_p.y(), A.center().y()) >= 0)); + + if (b) { + _begin = A._begin; + _end = new_p; + } + else { + _begin = new_p; + _end = A._end; + } + } + + // Constructs an arc supported by Circle_2(begin, middle, end), + // with _begin == begin, _end == end. + // (middle is not necessarily on the arc) + Circular_arc_2(const Point_2 &begin, + const Point_2 &middle, + const Point_2 &end) + : _begin(begin), _end(end) +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + , id_of_my_supporting_circle(0) +#endif + { + reset_flags(); + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + _get_id_number(); +#endif + + CGAL_kernel_precondition(!CGAL::collinear(begin, middle, end)); + _support = Circle_2(begin, middle, end); + /* + * Circle_2 c = Circle_2(begin, middle, end); + * Line_2 l1 (begin, middle); + Line_2 l2 (middle, end); + *this = Circular_arc_2(c, + l1, compare_xy(begin, middle) < 0, + l2, compare_xy(end, middle) < 0);*/ + //std::cout << source() << std::endl; + //std::cout << target() << std::endl; + } + + Circular_arc_2(const Circle_2 &support, + const Circular_arc_point_2 &source, + const Circular_arc_point_2 &target) + : _begin(source), _end(target), _support(support) +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + , id_of_my_supporting_circle(0) +#endif + { + reset_flags(); + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + _get_id_number(); +#endif + + // We cannot enable these preconditions for now, since the + // Lazy_circular_kernel_2 + // calls it on the Interval kernel without try/catch protection + // through the Circular_kernel_converter. + // CGAL_kernel_exactness_precondition(CK().has_on_2_object()(support, source)); + // CGAL_kernel_exactness_precondition(CK().has_on_2_object()(support, target)); + } + + Circular_arc_2(const Point_2 &begin, + const Point_2 &end, + const FT &bulge) + : _begin(begin), _end(end) +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + , id_of_my_supporting_circle(0) +#endif + { + reset_flags(); + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + _get_id_number(); +#endif + + const FT sqr_bulge = CGAL::square(bulge); + const FT common = (FT(1) - sqr_bulge) / (FT(4)*bulge); + const FT x_coord = (begin.x() + end.x())/FT(2) + + common*(begin.y() - end.y()); + const FT y_coord = (begin.y() + end.y())/FT(2) + + common*(end.x() - begin.x()); + + const FT sqr_rad = squared_distance(begin, end) + * (FT(1)/sqr_bulge + FT(2) + sqr_bulge) / FT(16); + + _support = Circle_2(Point_2(x_coord, y_coord), sqr_rad); + } + + private: + // The arc goes from _begin to _end in the positive order + // If _begin == _end, then it's the full circle + Circular_arc_point_2 _begin, _end; + Circle_2 _support; + mutable bit_field flags; +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + unsigned int my_id; // the id of the arc + // to optimize make_x_monotone and splits + // so we have not echec de filtre for intersection + static Table table; +#endif + + public: + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + template < class T > + static bool find_intersection(const Circular_arc_2& c1, + const Circular_arc_2& c2, + T& res) { + return table.find(c1.my_id, c2.my_id, res); + } + + template < class T > + static void put_intersection(const Circular_arc_2& c1, + const Circular_arc_2& c2, + const T& res) { + table.put(c1.my_id, c2.my_id, res); + } +#endif + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + static Table circle_table; + mutable unsigned int id_of_my_supporting_circle; + + template < class T > + static bool find_intersection_circle_circle( + const Circular_arc_2& c1, + const Circular_arc_2& c2, + T& res) { + if(c1.id_of_my_supporting_circle == 0) return false; + if(c2.id_of_my_supporting_circle == 0) return false; + return circle_table.find(c1.id_of_my_supporting_circle, + c2.id_of_my_supporting_circle, + res); + } + + template < class T > + static void put_intersection_circle_circle(const Circular_arc_2& c1, + const Circular_arc_2& c2, + const T& res) { + circle_table.put(c1.circle_number(), + c2.circle_number(), + res); + } +#endif + + // to remember if the arc was constructed from a full circle + const Circular_arc_point_2 & left() const + { + CGAL_kernel_precondition(is_x_monotone()); + CGAL_kernel_precondition(on_upper_part() ? compare_xy(_end,_begin)<0 + : compare_xy(_begin,_end)<0); + if (on_upper_part()) return _end; + return _begin; + } + + const Circular_arc_point_2 & right() const + { + CGAL_kernel_precondition(is_x_monotone()); + CGAL_kernel_precondition(on_upper_part() ? compare_xy(_end,_begin)<0 + : compare_xy(_begin,_end)<0); + if (on_upper_part()) return _begin; + return _end; + } + + const Circular_arc_point_2 & source() const + { + return _begin; + } + + const Circular_arc_point_2 & target() const + { + return _end; + } + + inline const bool is_full() const { + return flags.is_full == 2; + } + +private: + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + void _get_id_number() { + my_id = table.get_new_id(); + } +#endif + + bool _is_x_monotone() const { + if (is_full()) return false; + + int cmp_begin = CGAL::compare(_begin.y(), center().y()); + int cmp_end = CGAL::compare(_end.y(), center().y()); + + // XXX : be careful, this may be surprising if the return value + // is not -1/1 but some random int... + + if (cmp_begin == opposite(cmp_end) && cmp_begin != 0) + return false; + + // Maybe the complementar is x_monotone + // but we have to go further to know + // see is_x_monotone() + flags.is_complementary_x_monotone = 1; + + int cmp_x = compare_x(_begin, _end); + + // Is the arc on the upper part ? + if (cmp_begin > 0 || cmp_end > 0) + return cmp_x > 0; + + // Is the arc on the lower part ? + if (cmp_begin < 0 || cmp_end < 0) + return cmp_x < 0; + + // There remains the case : + CGAL_kernel_assertion(cmp_begin == 0 && cmp_end == 0); + + return cmp_x != 0; // full circle or half circle. + } + + bool _is_y_monotone() const { + if (is_full()) return false; + + int cmp_begin = CGAL::compare(_begin.x(), center().x()); + int cmp_end = CGAL::compare(_end.x(), center().x()); + + // XXX : be careful, this may be surprising if the return value + // is not -1/1 but some random int... + if (cmp_begin == opposite(cmp_end) && cmp_begin != 0) + return false; + + // Maybe the complementar is y_monotone + // but we have to go further to know + // see is_y_monotone() + flags.is_complementary_y_monotone = 1; + + int cmp_y = compare_y(_begin, _end); + + // Is the arc on the right part ? + if (cmp_begin > 0 || cmp_end > 0) + return cmp_y < 0; + + // Is the arc on the left part ? + if (cmp_begin < 0 || cmp_end < 0) + return cmp_y > 0; + + // There remains the case : + assert(cmp_begin == 0 && cmp_end == 0); + + return cmp_y != 0; // full circle or half circle. + } + + // if the 2 points are on x-extremals + // true if the arc is on upper-part + bool _two_end_points_on_upper_part() const { + int c1y = CGAL::compare(_begin.y(), + supporting_circle().center().y()); + if(c1y > 0) return true; + if(c1y < 0) return false; + int c2y = CGAL::compare(_end.y(), + supporting_circle().center().y()); + if(c2y > 0) return true; + if(c2y < 0) return false; + return compare_x(_begin, _end) > 0; + } + + // if the 2 points are on y-extremals + // true if the arc is on left-part + bool _two_end_points_on_left_part() const + { + int c1x = CGAL::compare(_begin.x(), + supporting_circle().center().x()); + if(c1x < 0) return true; + if(c1x > 0) return false; + int c2x = CGAL::compare(_end.x(), + supporting_circle().center().x()); + if(c2x < 0) return true; + if(c2x > 0) return false; + return compare_y(_begin, _end) > 0; + } + +public: + + bool is_x_monotone() const { + if(flags.is_x_monotonic == 0) { + bool b = _is_x_monotone(); + if(b) { + flags.is_x_monotonic = 2; + flags.is_complementary_x_monotone = 0; + } else flags.is_x_monotonic = 1; + return b; + } else { + return (flags.is_x_monotonic == 1) ? false : true; + } + } + + // Returns true if the complementary arc is x_monotone() + // note: if semi-cercle -> false + bool is_complementary_x_monotone() const { + // is_x_monotone calculates also if + // the complementary is x-monotone if needed + is_x_monotone(); + return (flags.is_complementary_x_monotone == 0) ? false : true; + } + + bool is_y_monotone() const { + if(flags.is_y_monotonic == 0) { + bool b = _is_y_monotone(); + if(b) { + flags.is_y_monotonic = 2; + flags.is_complementary_y_monotone = 0; + } else flags.is_y_monotonic = 1; + return b; + } else { + return (flags.is_y_monotonic == 1) ? false : true; + } + } + + // Returns true if the complementary arc is y_monotone() + // note: if semi-cercle -> false + bool is_complementary_y_monotone() const { + // is_y_monotone calculates also if + // the complementary is y-monotone if needed + is_y_monotone(); + return (flags.is_complementary_y_monotone == 0) ? false : true; + } + + // check whether 2 endpoints are at upper or not from the center + bool two_end_points_on_upper_part() const { + if(flags.two_end_points_on_upper_part == 0) { + bool b = _two_end_points_on_upper_part(); + if(b) flags.two_end_points_on_upper_part = 2; + else flags.two_end_points_on_upper_part = 1; + return b; + } else { + return (flags.two_end_points_on_upper_part == 1) ? false : true; + } + } + + // check whether the arc is at upper or not from the center + bool on_upper_part() const { + CGAL_kernel_precondition(is_x_monotone()); + return two_end_points_on_upper_part(); + } + + // Returns true if the complementary arc is on_upper_part() + bool complementary_on_upper_part() const { + if(is_x_monotone()) return false; + return two_end_points_on_upper_part(); + } + + // check whether the 2 endpoints are at left or right from the center + bool two_end_points_on_left_part() const { + if(flags.two_end_points_on_left_part == 0) { + bool b = _two_end_points_on_left_part(); + if(b) flags.two_end_points_on_left_part = 2; + else flags.two_end_points_on_left_part = 1; + return b; + } else { + return (flags.two_end_points_on_left_part == 1) ? false : true; + } + } + + // check whether the arc is at left or right from the center + bool on_left_part() const { + CGAL_kernel_precondition(is_y_monotone()); + return two_end_points_on_left_part(); + } + + // Returns true if the complementary arc is on_left_part() + bool complementary_on_left_part() const { + if(is_y_monotone()) return false; + return two_end_points_on_left_part(); + } + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + unsigned int number() const { + return my_id; + } +#endif + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + unsigned int circle_number() const { + if(!id_of_my_supporting_circle) + id_of_my_supporting_circle = circle_table.get_new_id(); + return id_of_my_supporting_circle; + } + + void set_circle_number(unsigned int i) const { + id_of_my_supporting_circle = i; + } +#endif + + const Circle_2 & supporting_circle() const + { + return _support; + } + + const Point_2 & center() const + { + return supporting_circle().center(); + } + + const FT & squared_radius() const + { + return supporting_circle().squared_radius(); + } + + Bbox_2 bbox() const + { + return CGAL::CircularFunctors::circular_arc_bbox(*this); + } + + // Dont use this function, it is only for internal use + void _setx_info(unsigned short int v_is_x_monotone, + unsigned short int v_two_end_points_on_upper_part, + unsigned short int v_is_complementary_x_monotone) const { + flags.is_x_monotonic = v_is_x_monotone; + flags.two_end_points_on_upper_part = v_two_end_points_on_upper_part; + flags.is_complementary_x_monotone = v_is_complementary_x_monotone; + } + + }; + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + template < typename CK > + CGALi::Intersection_line_2_circle_2_map Circular_arc_2< CK >::table = + CGALi::Intersection_line_2_circle_2_map(); +#endif + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + template < typename CK > + CGALi::Intersection_line_2_circle_2_map Circular_arc_2< CK >::circle_table = + CGALi::Intersection_line_2_circle_2_map(); +#endif + + template < typename CK > + std::ostream & + operator<<(std::ostream & os, const Circular_arc_2 &a) + { + // The output format is : + // - supporting circle + // - circle c1 + // - bool b1 + // - circle c2 + // - bool b2 + return os << a.supporting_circle() << " " + << a.source() << " " + << a.target() << " "; + } + + template < typename CK > + std::istream & + operator>>(std::istream & is, Circular_arc_2 &a) + { + typename CK::Circle_2 s; + typename CK::Circular_arc_point_2 p1; + typename CK::Circular_arc_point_2 p2; + is >> s >> p1 >> p2 ; + if (is) + a = Circular_arc_2(s, p1, p2); + return is; + } + + template < typename CK > + std::ostream & + print(std::ostream & os, const Circular_arc_2 &a) + { + if(a.is_x_monotone()) { + return os << "Circular_arc_2( " << std::endl + << "left : " << a.left() << " , " << std::endl + << "right : " << a.right() << " , " << std::endl + << "upper part : " << a.on_upper_part() << std::endl + << " [[ approximate circle is (x,y,r) : " + << CGAL::to_double(a.supporting_circle().center().x()) << "" + << CGAL::to_double(a.supporting_circle().center().y()) << "" + << std::sqrt(CGAL::to_double(a.supporting_circle().squared_radius())) + << " ]])" << std::endl; + } else { + return os << "Circular_arc_2( " << std::endl + << " [[ approximate circle is (x,y,r) : " + << CGAL::to_double(a.supporting_circle().center().x()) << "" + << CGAL::to_double(a.supporting_circle().center().y()) << "" + << std::sqrt(CGAL::to_double(a.supporting_circle().squared_radius())) + << " ]])" << std::endl; + } + } + +} // namespace CGALi +} // namespace CGAL + +#undef CGAL_USEFUL_MAPS_FOR_THE_CIRCULAR_KERNEL +#endif // CGAL_CIRCULAR_KERNEL_CIRCULAR_ARC_2_H diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/Circular_arc_point_2.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/Circular_arc_point_2.h new file mode 100644 index 00000000000..cc797add6c9 --- /dev/null +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/Circular_arc_point_2.h @@ -0,0 +1,95 @@ +// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// 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. +// +// $URL$ +// $Id$ +// +// Author(s) : Monique Teillaud, Sylvain Pion + +// 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) + +#ifndef CGAL_CIRCULAR_KERNEL_CIRCULAR_ARC_POINT_2_H +#define CGAL_CIRCULAR_KERNEL_CIRCULAR_ARC_POINT_2_H + +#include +#include + +#include +#include +#include +#include + +namespace CGAL { +namespace CGALi { + + template + class Circular_arc_point_2 + { + typedef typename CK::FT FT; + typedef typename CK::Root_of_2 Root_of_2; + typedef typename CK::Point_2 Point_2; + + public: // fixme ? + typedef typename CK::Root_for_circles_2_2 Root_for_circles_2_2; + typedef typename CK::template Handle::type Base; + + Circular_arc_point_2() + {} + + Circular_arc_point_2(const Root_for_circles_2_2 & np) + : _p(np) + {} + + Circular_arc_point_2(const Point_2 & p) + : _p(p.x(),p.y()/*,1,1,-p.x()-p.y()*/) + {} + + const Root_of_2 & x() const + { return get(_p).x(); } + + const Root_of_2 & y() const + { return get(_p).y(); } + + CGAL::Bbox_2 bbox() const + { + return get(_p).bbox(); + } + + const Root_for_circles_2_2 & coordinates() const + { return get(_p); } + + bool equal_ref(const Circular_arc_point_2 &p) const + { + return CGAL::identical(_p, p._p); + } + + private: + Base _p; + }; + + template < typename CK > + std::ostream & + print(std::ostream & os, const Circular_arc_point_2 &p) + { + return os << "CirclArcEndPoint_2(" << std::endl + << p.x() << ", " << p.y() << ')'; + } + +} // namespace CGALi +} // namespace CGAL + +#endif // CGAL_CIRCULAR_KERNEL_CIRCULAR_ARC_POINT_2_H diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/Line_arc_2.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/Line_arc_2.h new file mode 100644 index 00000000000..cbb659222c3 --- /dev/null +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/Line_arc_2.h @@ -0,0 +1,297 @@ +// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// 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. +// +// $URL$ +// $Id$ +// +// Author(s) : Monique Teillaud, Sylvain Pion + +// 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) + +#ifndef CGAL_CIRCULAR_KERNEL_LINE_ARC_2_H +#define CGAL_CIRCULAR_KERNEL_LINE_ARC_2_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace CGAL { +namespace CGALi { + + template + class Line_arc_2 + { + typedef typename CK::FT FT; + typedef typename CK::RT RT; + typedef typename CK::Point_2 Point_2; + typedef typename CK::Line_2 Line_2; + typedef typename CK::Circle_2 Circle_2; + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Root_of_2 Root_of_2; + typedef typename CK::Segment_2 Segment_2; + typedef struct bit_field { + unsigned char begin_less_xy_than_end:2; + } bit_field; + + private: + // set flags to 0 + // when 1 bit -> 0 = false, 1 = true + // when 2 bits -> 0 = don_know, 1 = false + // 2 = true + void reset_flags() const { + flags.begin_less_xy_than_end = 0; + } + + public: + //typedef typename CGAL::Simple_cartesian::Point_2 + // Numeric_point_2; + typedef typename CK::Root_for_circles_2_2 + Root_for_circles_2_2; + + static + Circular_arc_point_2 + intersect(const Line_2 & l, const Circle_2 & c, const bool b) + { + + typedef std::vector + solutions_container; + + solutions_container solutions; + CGAL::LinearFunctors::intersect_2 + ( l, c, std::back_inserter(solutions) ); + typename solutions_container::iterator it = solutions.begin(); + + CGAL_kernel_precondition( it != solutions.end() ); + // the circles intersect + + const std::pair *result; + result = CGAL::object_cast< + std::pair >(&(*it)); + if ( result->second == 2 ) // double solution + return result->first; + if (b) return result->first; + ++it; + result = CGAL::object_cast< + std::pair >(&(*it)); + return result->first; + } + + + public: + Line_arc_2() +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + : id_of_my_supporting_line(Circular_arc_2::circle_table.get_new_id()) +#endif + {} + + Line_arc_2(const Line_2 &support, + const Circle_2 &c1,const bool b1, + const Circle_2 &c2,const bool b2) + :_support(support) +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + ,id_of_my_supporting_line(Circular_arc_2::circle_table.get_new_id()) +#endif + { + _begin = intersect(support, c1, b1); + _end = intersect(support, c2, b2); + reset_flags(); + } + + + Line_arc_2(const Line_2 &support, + const Line_2 &l1, + const Line_2 &l2) + :_support(support) +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + ,id_of_my_supporting_line(Circular_arc_2::circle_table.get_new_id()) +#endif + { + CGAL_kernel_precondition(do_intersect(support, l1)); + CGAL_kernel_precondition(do_intersect(support, l2)); + //typedef typename Root_of_2::RT RT_2; + //Voir pour mettre une assertion au assign + Object obj = intersection(support, l1); + const Point_2 *pt = CGAL::object_cast(&obj); + _begin = Circular_arc_point_2(*pt); + obj = intersection(support, l2); + const Point_2 *pt2 = CGAL::object_cast(&obj); + _end = Circular_arc_point_2(*pt2); + reset_flags(); + } + + Line_arc_2(const Line_2 &support, + const Circular_arc_point_2 &p1, + const Circular_arc_point_2 &p2) + :_support(support) +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + ,id_of_my_supporting_line(Circular_arc_2::circle_table.get_new_id()) +#endif + { + //Verifier si p1 et p2 sont sur la line + _begin = p1; + _end = p2; + reset_flags(); + } + + Line_arc_2(const Segment_2 &s) + :_support(s.supporting_line()) +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + ,id_of_my_supporting_line(Circular_arc_2::circle_table.get_new_id()) +#endif + { + _begin = Circular_arc_point_2(s.source()); + _end = Circular_arc_point_2(s.target()); + reset_flags(); + } + + + Line_arc_2(const Point_2 &p1, + const Point_2 &p2) +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + : id_of_my_supporting_line(Circular_arc_2::circle_table.get_new_id()) +#endif + { + _support = Line_2(p1, p2); + _begin = Circular_arc_point_2(p1); + _end = Circular_arc_point_2(p2); + reset_flags(); + } + + private: + + Line_2 _support; + Circular_arc_point_2 _begin, _end; + mutable bit_field flags; + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + mutable unsigned int id_of_my_supporting_line; + + unsigned int line_number() const { + return id_of_my_supporting_line; + } + + void set_line_number(unsigned int i) const { + id_of_my_supporting_line = i; + } +#endif + + private: //(some useful functions) + + bool begin_less_xy_than_end() const { + if(flags.begin_less_xy_than_end == 0) { + if(compare_xy(_begin, _end) < 0) + flags.begin_less_xy_than_end = 2; + else flags.begin_less_xy_than_end = 1; + } return flags.begin_less_xy_than_end == 2; + } + + public : + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + template < class T > + static bool find_intersection_circle_line( + const Circular_arc_2& c, + const Line_arc_2& l, + T& res) { + if(c.id_of_my_supporting_circle == 0) return false; + return Circular_arc_2::circle_table.template find(c.id_of_my_supporting_circle, + l.id_of_my_supporting_line, + res); + } + + template < class T > + static void put_intersection_circle_line(const Circular_arc_2& c, + const Line_arc_2& l, + const T& res) { + Circular_arc_2::circle_table.template put(c.circle_number(), + l.line_number(), + res); + } +#endif + + const Line_2 & supporting_line() const + { + return _support; + } + + const Circular_arc_point_2 & left() const + { + return begin_less_xy_than_end() ? _begin : _end; + } + + const Circular_arc_point_2 & right() const + { + return begin_less_xy_than_end() ? _end : _begin; + } + + const Circular_arc_point_2 & source() const + { + return _begin; + } + + const Circular_arc_point_2 & target() const + { + return _end; + } + + bool is_vertical() const + { + return supporting_line().is_vertical(); + } + + CGAL::Bbox_2 bbox() const + { + return _begin.bbox() + _end.bbox(); + } + + }; + + /* template < typename CK > */ +/* std::ostream & */ +/* operator<<(std::ostream & os, const Line_arc_2 &a) */ +/* { */ + +/* return os << a.supporting_line() << " " */ +/* << a.source() << " " */ +/* << a.target() << " "; */ +/* } */ + +/* template < typename CK > */ +/* std::istream & */ +/* operator>>(std::istream & is, Line_arc_2 &a) */ +/* { */ +/* typename CK::Line_2 l; */ +/* typename CK::Circular_arc_point_2 p1; */ +/* typename CK::Circular_arc_point_2 p2; */ +/* is >> l >> p1 >> p2 ; */ +/* if (is) */ +/* a = Line_arc_2(l, p1, p2); */ +/* return is; */ +/* } */ + + + } // namespace CGALi +} // namespace CGAL + +#endif // CGAL_CIRCULAR_KERNEL_LINE_ARC_2_H diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/function_objects_on_circle_2.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/function_objects_on_circle_2.h new file mode 100644 index 00000000000..602e6799f0b --- /dev/null +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/function_objects_on_circle_2.h @@ -0,0 +1,73 @@ +// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// 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. +// +// $URL$ +// $Id$ +// +// Author(s) : Monique Teillaud, Sylvain Pion + +// 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) + +#ifndef CGAL_CIRCULAR_KERNEL_FUNCTION_OBJECTS_ON_CIRCLE_2_H +#define CGAL_CIRCULAR_KERNEL_FUNCTION_OBJECTS_ON_CIRCLE_2_H + +#include + +#include +// to be removed when CGAL::Kernel has a Get_equation + +namespace CGAL { +namespace CircularFunctors { + + template < class CK > + class Construct_circle_2 : public CK::Linear_kernel::Construct_circle_2 + { + public: + + typedef typename CK::Circle_2 result_type; + typedef Arity_tag<1> Arity; + + using CK::Linear_kernel::Construct_circle_2::operator(); + + result_type + operator() ( const typename CK::Polynomial_for_circles_2_2 &eq ) + { + return construct_circle_2(eq); + } + }; + + template < class CK > + class Get_equation : public LinearFunctors::Get_equation + { + public: + + typedef typename CK::Polynomial_for_circles_2_2 result_type; + typedef Arity_tag<1> Arity; + + using LinearFunctors::Get_equation::operator(); + + result_type + operator() ( const typename CK::Circle_2 & c ) + { + return CircularFunctors::get_equation(c); + } + }; + +} // namespace CircularFunctors +} // namespace CGAL + +#endif // CGAL_CIRCULAR_KERNEL_FUNCTION_OBJECTS_ON_CIRCLE_2_H diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/function_objects_on_line_2.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/function_objects_on_line_2.h new file mode 100644 index 00000000000..2612827058a --- /dev/null +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/function_objects_on_line_2.h @@ -0,0 +1,66 @@ +// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// 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. +// +// $URL$ +// $Id$ +// +// Author(s) : Monique Teillaud, Sylvain Pion + +// 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) + +#ifndef CGAL_CIRCULAR_KERNEL_FUNCTION_OBJECTS_ON_LINE_2_H +#define CGAL_CIRCULAR_KERNEL_FUNCTION_OBJECTS_ON_LINE_2_H + +#include + +namespace CGAL { +namespace LinearFunctors { + + template < class CK > + class Construct_line_2 : public CK::Linear_kernel::Construct_line_2 + { + public: + + typedef typename CK::Line_2 result_type; + typedef Arity_tag<1> Arity; + + result_type + operator() ( const typename CK::Polynomial_1_2 &eq ) + { + return construct_line_2(eq); + } + }; + + template < class CK > + class Get_equation + { + public: + + typedef typename CK::Polynomial_1_2 result_type; + typedef Arity_tag<1> Arity; + + result_type + operator() ( const typename CK::Line_2 & l ) + { + return LinearFunctors::get_equation(l); + } + }; + +} // namespace LinearFunctors +} // namespace CGAL + +#endif // CGAL_CIRCULAR_KERNEL_FUNCTION_OBJECTS_ON_LINE_2_H diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/function_objects_polynomial_circular.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/function_objects_polynomial_circular.h new file mode 100644 index 00000000000..3de567565ce --- /dev/null +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/function_objects_polynomial_circular.h @@ -0,0 +1,1122 @@ +// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// 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. +// +// $URL$ +// $Id$ +// +// Author(s) : Monique Teillaud, Sylvain Pion + +// 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) + +#ifndef CGAL_CIRCULAR_KERNEL_FUNCTION_OBJECTS_POLYNOMIAL_CIRCULAR_H +#define CGAL_CIRCULAR_KERNEL_FUNCTION_OBJECTS_POLYNOMIAL_CIRCULAR_H + +#include +#include +#include +#include + +namespace CGAL { +namespace CircularFunctors { + + + template < class CK > + class Compare_x_2 +#ifndef CGAL_CFG_MATCHING_BUG_6 + : public CK::Linear_kernel::Compare_x_2 +#endif + { + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Point_2 Point_2; + + public: + typedef CGAL::Comparison_result result_type; + typedef Arity_tag<2> Arity; + +#ifndef CGAL_CFG_MATCHING_BUG_6 + using CK::Linear_kernel::Compare_x_2::operator(); +#else + result_type + operator() (const Point_2 &p0, + const Point_2 &p1) const + { + typedef typename CK::Linear_kernel LK; + typedef typename LK::Compare_x_2 LK_Compare_x_2; + return LK_Compare_x_2()(p0, p1); + } +#endif + + result_type + operator() (const Circular_arc_point_2 &p0, + const Circular_arc_point_2 &p1) const + { return CircularFunctors::compare_x(p0, p1);} + + }; + + + template < class CK > + class Compare_y_2 +#ifndef CGAL_CFG_MATCHING_BUG_6 + : public CK::Linear_kernel::Compare_y_2 +#endif + { + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Point_2 Point_2; + + public: + typedef CGAL::Comparison_result result_type; + typedef Arity_tag<2> Arity; + +#ifndef CGAL_CFG_MATCHING_BUG_6 + using CK::Linear_kernel::Compare_y_2::operator(); +#else + result_type + operator() (const Point_2 &p0, + const Point_2 &p1) const + { + typedef typename CK::Linear_kernel LK; + typedef typename LK::Compare_y_2 LK_Compare_y_2; + return LK_Compare_y_2()(p0, p1); + } +#endif + + result_type + operator() (const Circular_arc_point_2 &p0, + const Circular_arc_point_2 &p1) const + {return CircularFunctors::compare_y(p0, p1);} + + }; + + template < class CK > + class Compare_xy_2 +#ifndef CGAL_CFG_MATCHING_BUG_6 + : public CK::Linear_kernel::Compare_xy_2 +#endif + { + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Point_2 Point_2; + + public: + typedef CGAL::Comparison_result result_type; + typedef Arity_tag<2> Arity; + +#ifndef CGAL_CFG_MATCHING_BUG_6 + using CK::Linear_kernel::Compare_xy_2::operator(); +#else + result_type + operator() (const Point_2 &p0, + const Point_2 &p1) const + { + typedef typename CK::Linear_kernel LK; + typedef typename LK::Compare_xy_2 LK_Compare_xy_2; + return LK_Compare_xy_2()(p0, p1); + } +#endif + + result_type + operator() (const Circular_arc_point_2 &p0, + const Circular_arc_point_2 &p1) const + { return CircularFunctors::compare_xy(p0, p1);} + + }; + + template < class CK > + class In_x_range_2 + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Line_arc_2 Line_arc_2; + + public: + typedef bool result_type; + typedef Arity_tag<2> Arity; + + result_type + operator()(const Circular_arc_2 &a, const Circular_arc_point_2 &p) const + { return CircularFunctors::point_in_x_range(a, p); } + + result_type + operator()(const Line_arc_2 &a, const Circular_arc_point_2 &p) const + { return CircularFunctors::point_in_x_range(a, p); } + + }; + + + template < class CK > + class Has_on_2 + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Line_arc_2 Line_arc_2; + typedef typename CK::Circle_2 Circle_2; + typedef typename CK::Line_2 Line_2; + + public: + typedef bool result_type; + typedef Arity_tag<2> Arity; + + result_type + operator()(const Circle_2 &a, const Circular_arc_point_2 &p) const + { return has_on(a, p); } + + result_type + operator()(const Line_2 &a, const Circular_arc_point_2 &p) const + { return has_on(a, p); } + + result_type + operator()(const Circular_arc_2 &a, const Circular_arc_point_2 &p) const + { return has_on(a, p); } + + result_type + operator()(const Line_arc_2 &a, const Circular_arc_point_2 &p) const + { return has_on(a, p); } + + }; + + + + template < class CK > + class Compare_y_to_right_2 + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Line_arc_2 Line_arc_2; + + public: + typedef CGAL::Comparison_result result_type; + typedef Arity_tag<3> Arity; + + result_type + operator()(const Circular_arc_2 &a1, + const Circular_arc_2 &a2, + const Circular_arc_point_2 &p) const + { return compare_y_to_right(a1, a2, p); } + + result_type + operator()(const Line_arc_2 &a1, + const Line_arc_2 &a2, + const Circular_arc_point_2 &p) const + { return compare_y_to_right(a1, a2, p); } + + result_type + operator()(const Line_arc_2 &a1, + const Circular_arc_2 &a2, + const Circular_arc_point_2 &p) const + { return compare_y_to_right(a1, a2, p); } + + result_type + operator()(const Circular_arc_2 &a1, + const Line_arc_2 &a2, + const Circular_arc_point_2 &p) const + { if (compare_y_to_right(a2, a1, p) == CGAL::LARGER) + return CGAL::SMALLER; + return CGAL::LARGER; + } + + }; + + template < class CK > + class Equal_2 + #ifndef CGAL_CFG_MATCHING_BUG_6 + : public CK::Linear_kernel::Equal_2 +#endif + { + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Line_arc_2 Line_arc_2; + + public: + typedef bool result_type; + typedef Arity_tag<2> Arity; + + typedef typename CK::Linear_kernel LK; + typedef typename LK::Equal_2 LK_Equal_2; + + typedef typename LK::Point_2 Point_2; + typedef typename LK::Vector_2 Vector_2; + typedef typename LK::Direction_2 Direction_2; + typedef typename LK::Segment_2 Segment_2; + typedef typename LK::Ray_2 Ray_2; + typedef typename LK::Line_2 Line_2; + typedef typename LK::Triangle_2 Triangle_2; + typedef typename LK::Iso_rectangle_2 Iso_rectangle_2; + typedef typename LK::Circle_2 Circle_2; + + +#ifndef CGAL_CFG_MATCHING_BUG_6 + using CK::Linear_kernel::Equal_2::operator(); +#else + result_type + operator() (const Point_2 &p0, + const Point_2 &p1) const + { return LK_Equal_2()(p0,p1); } + + result_type + operator() (const Vector_2 &p0, + const Vector_2 &p1) const + { return LK_Equal_2()(p0,p1); } + + result_type + operator() (const Direction_2 &p0, + const Direction_2 &p1) const + { return LK_Equal_2()(p0,p1); } + + + result_type + operator() (const Segment_2 &p0, + const Segment_2 &p1) const + { return LK_Equal_2()(p0,p1); } + + + result_type + operator() (const Ray_2 &p0, + const Ray_2 &p1) const + { return LK_Equal_2::operator()(p0,p1); } + + result_type + operator() (const Line_2 &p0, + const Line_2 &p1) const + { return LK_Equal_2()(p0,p1); } + + + + result_type + operator() (const Triangle_2 &p0, + const Triangle_2 &p1) const + { return LK_Equal_2()(p0,p1); } + + + result_type + operator() (const Iso_rectangle_2 &p0, + const Iso_rectangle_2 &p1) const + { return LK_Equal_2()(p0,p1); } + + + result_type + operator() (const Circle_2 &p0, + const Circle_2 &p1) const + { return LK_Equal_2()(p0,p1); } +#endif + + result_type + operator() (const Circular_arc_point_2 &p0, + const Circular_arc_point_2 &p1) const + { return equal(p0, p1); } + + result_type + operator() (const Circular_arc_2 &a0, const Circular_arc_2 &a1) const + { return equal(a0, a1); } + + result_type + operator() (const Line_arc_2 &a0, const Line_arc_2 &a1) const + { return equal(a0, a1); } + + result_type + operator() ( const Line_arc_2 &a0, const Circular_arc_2 &a1) const + {return false;} + + result_type + operator() ( const Circular_arc_2 &a0, const Line_arc_2 &a1) const + {return false;} + + }; + + template < class CK > + class Compare_y_at_x_2 + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Line_arc_2 Line_arc_2; + + public: + typedef CGAL::Comparison_result result_type; + typedef Arity_tag<2> Arity; + + result_type + operator() (const Circular_arc_point_2 &p, + const Circular_arc_2 &A1) const + { return CircularFunctors::compare_y_at_x(p, A1); } + + result_type + operator() (const Circular_arc_point_2 &p, + const Line_arc_2 &A1) const + { return CircularFunctors::compare_y_at_x(p, A1); } + + }; + + template < class CK > + class Do_overlap_2 + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Line_arc_2 Line_arc_2; + + public: + typedef bool result_type; + typedef Arity_tag<2> Arity; + + result_type + operator() (const Circular_arc_2 &A1, const Circular_arc_2 &A2) const + { return CircularFunctors::do_overlap(A1, A2); } + + result_type + operator() (const Line_arc_2 &A1, const Line_arc_2 &A2) const + { return CircularFunctors::do_overlap(A1, A2); } + + }; + + + template < class CK > + class Make_x_monotone_2 + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Line_arc_2 Line_arc_2; + + public: + + typedef void result_type; //!!! + typedef Arity_tag<2> Arity; + + template < class OutputIterator > + OutputIterator + operator()(const Circular_arc_2 &A, OutputIterator res) const + { + return CircularFunctors::make_x_monotone (A, res); + } + + template < class OutputIterator > + OutputIterator + operator()(const Line_arc_2 &A, OutputIterator res) const + { + return CircularFunctors::make_x_monotone(A,res); + } + + }; + + template < class CK > + class Make_xy_monotone_2 + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Line_arc_2 Line_arc_2; + + public: + + typedef void result_type; //!!! + typedef Arity_tag<2> Arity; + + template < class OutputIterator > + OutputIterator + operator()(const Circular_arc_2 &A, OutputIterator res) const + { + typedef std::pair relat_pos; + typedef std::pair< CGAL::Object, relat_pos> Obj_descr_2; + std::vector vec; + + CircularFunctors::advanced_make_xy_monotone (A, std::back_inserter(vec)); + + for(int i=0;i + OutputIterator + operator()(const Line_arc_2 &A, OutputIterator res) const + { *res++ = make_object(A); + return res; + } + + }; + + + + template < class CK > + class Advanced_make_x_monotone_2 + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Line_arc_2 Line_arc_2; + + public: + + typedef void result_type; //!!! + typedef Arity_tag<2> Arity; + + template < class OutputIterator > + OutputIterator + operator()(const Circular_arc_2 &A, OutputIterator res) const + { return CircularFunctors::advanced_make_x_monotone (A, res);} + + + // No extra information is meant to be returned for line arcs (should it?) + // So attention on the fact that the second part of the pair contains dummy + // info. Maybe there shouldn't be such an operator for line arcs after all + + template < class OutputIterator > + OutputIterator + operator()(const Line_arc_2 &A, OutputIterator res) const + { *res++ = std::make_pair(make_object(A),false); // + return res; + } + + }; + + +template < class CK > + class Advanced_make_xy_monotone_2 + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Line_arc_2 Line_arc_2; + + public: + + typedef void result_type; //!!! + typedef Arity_tag<2> Arity; + + template < class OutputIterator > + OutputIterator + operator()(const Circular_arc_2 &A, OutputIterator res) const + { return CircularFunctors::advanced_make_xy_monotone (A, res);} + + + // No extra information is meant to be returned for line arcs (should it?) + // So attention on the fact that the second part of the pair contains dummy + // info. Maybe there shouldn't be such an operator for line arcs after all + + template < class OutputIterator > + OutputIterator + operator()(const Line_arc_2 &A, OutputIterator res) const + { *res++ = std::make_pair(make_object(A),std::make_pair(false,false)); + return res; + } + + }; + + + template < class CK > + class Intersect_2 + : public CK::Linear_kernel::Intersect_2 + { + + typedef typename CK::Circle_2 Circle; + typedef typename CK::Circular_arc_2 Circular_arc; + typedef typename CK::Line_arc_2 Line_arc; + + public: + + typedef void result_type; + typedef Arity_tag<3> Arity; + + using CK::Linear_kernel::Intersect_2::operator(); + + template < class OutputIterator > + OutputIterator + operator()(const Circle & c1, const Circle & c2, OutputIterator res) const + { return CircularFunctors::intersect_2 (c1,c2,res); } + + template < class OutputIterator > + OutputIterator + operator()(const Circular_arc & c1, const Circular_arc & c2, + OutputIterator res) const + { return CircularFunctors::intersect_2 (c1,c2,res); } + + template < class OutputIterator > + OutputIterator + operator()(const Line_arc & c1, const Line_arc & c2, + OutputIterator res) const + { return CircularFunctors::intersect_2 (c1,c2,res); } + + template < class OutputIterator > + OutputIterator + operator()(const Line_arc & c1, const Circle & c2, + OutputIterator res) const + { return CircularFunctors::intersect_2 (c1,c2,res); } + + template < class OutputIterator > + OutputIterator + operator()(const Circle & c1, const Line_arc & c2, + OutputIterator res) const + { return CircularFunctors::intersect_2 (c2,c1,res); } + + template < class OutputIterator > + OutputIterator + operator()(const Line_arc & c1, const Circular_arc & c2, + OutputIterator res) const + { return CircularFunctors::intersect_2 (c1,c2,res); } + + template < class OutputIterator > + OutputIterator + operator()(const Circular_arc & c1, const Line_arc & c2, + OutputIterator res) const + { return CircularFunctors::intersect_2 (c2,c1,res); } + + }; + + + template < class CK > + class Split_2 + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Line_arc_2 Line_arc_2; + + public: + + typedef void result_type; + typedef Arity_tag<4> Arity; + + result_type + operator()(const Circular_arc_2 &A, + const Circular_arc_point_2 &p, + Circular_arc_2 &ca1, Circular_arc_2 &ca2) const + { return CircularFunctors::split(A, p, ca1, ca2); } + + + result_type + operator()(const Line_arc_2 &A, + const Circular_arc_point_2 &p, + Line_arc_2 &ca1, Line_arc_2 &ca2) const + { return CircularFunctors::split(A, p, ca1, ca2); } + + }; + + template < class CK > + class Is_vertical_2 + : public CK::Linear_kernel::Is_vertical_2 + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Line_arc_2 Line_arc_2; + + public: + + typedef bool result_type; + typedef Arity_tag<1> Arity; + + using CK::Linear_kernel::Is_vertical_2::operator(); + + result_type + operator()(const Circular_arc_2 &A) const + { return CircularFunctors::is_vertical(A); } + + result_type + operator()(const Line_arc_2 &A) const + { return CircularFunctors::is_vertical(A); } + + }; + + template < class CK > + class Construct_circular_arc_2 + { + + typedef typename CK::FT FT; + typedef typename CK::RT RT; + typedef typename CK::Point_2 Point_2; + typedef typename CK::Line_2 Line_2; + typedef typename CK::Circle_2 Circle_2; + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Kernel_base::Circular_arc_2 RCircular_arc_2; + typedef typename Circular_arc_2::Rep Rep; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + + public: + typedef Circular_arc_2 result_type; + typedef Arity_tag<3> Arity; + + result_type + operator()(void) + { return Rep(); } + + result_type + operator()(const Circle_2 &c) const + { return Rep(c); } + + result_type + operator()(const Circle_2 &support, + const Circular_arc_point_2 &source, + const Circular_arc_point_2 &target) const + { return Rep(support,source,target); } + + result_type + operator()(const Circle_2 &support, + const Line_2 &l1, bool b1, + const Line_2 &l2, bool b2) const + { return Rep(support,l1,b1,l2,b2); } + + result_type + operator()(const Circle_2 &c, + const Circle_2 &c1, bool b_1, + const Circle_2 &c2, bool b_2) const + { return Rep(c,c1,b_1,c2,b_2); } + + result_type + operator()(const Circular_arc_2 &A, + bool b, + const Circle_2 &ccut, bool b_cut) const + { return Rep(A,b,ccut,b_cut); } + + result_type + operator()(const Point_2 &begin, + const Point_2 &middle, + const Point_2 &end) const + { return Rep(begin,middle,end); } + + result_type + operator()(const Point_2 &begin, + const Point_2 &end, + const FT& bulge) const + { return Rep(begin,end,bulge); } + + }; + + template < class CK > + class Construct_line_arc_2 + { + + typedef typename CK::Point_2 Point_2; + typedef typename CK::Line_2 Line_2; + typedef typename CK::Circle_2 Circle_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Segment_2 Segment_2; + typedef typename CK::Line_arc_2 Line_arc_2; + typedef typename CK::Kernel_base::Line_arc_2 RLine_arc_2; + typedef typename Line_arc_2::Rep Rep; + + public: + typedef Line_arc_2 result_type; + typedef Arity_tag<3> Arity; + + result_type + operator()(void) + { return Rep(); } + + result_type + operator()(const Line_2 &support, + const Circle_2 &c1,const bool b1, + const Circle_2 &c2,const bool b2) const + { return Rep(support,c1,b1,c2,b2); } + + result_type + operator()(const Line_2 &support, + const Line_2 &l1, + const Line_2 &l2) const + { return Rep(support,l1,l2); } + + result_type + operator()(const Line_2 &support, + const Circular_arc_point_2 &p1, + const Circular_arc_point_2 &p2) const + { return Rep(support,p1,p2); } + +// result_type +// operator()(const Line_2 &support, +// const Point_2 &p1, +// const Point_2 &p2) const +// { return Rep(support,p1,p2); } + + result_type + operator()(const Segment_2 &s) const + { return Rep(s); } + + result_type + operator()(const Point_2 &p1, + const Point_2 &p2) const + { return Rep(p1,p2); } + + }; + + template < class CK > + class Construct_circular_arc_point_2 + { + typedef typename CK::Point_2 Point_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Kernel_base::Circular_arc_point_2 + RCircular_arc_point_2; + typedef typename Circular_arc_point_2::Rep Rep; + typedef typename Circular_arc_point_2::Root_for_circles_2_2 + Root_for_circles_2_2; + + public: + typedef Circular_arc_point_2 result_type; + typedef Arity_tag<1> Arity; + + result_type + operator()(void) + { return Rep(); } + + result_type + operator()(const Root_for_circles_2_2 & np) const + { return Rep(np); } + + result_type + operator()(const Point_2 & p) const + { return Rep(p); } + + }; + + + template + class Compute_Circular_x_2: Has_qrt + { + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Root_of_2 Root_of_2; + + public: + + typedef Root_of_2 result_type; + typedef const result_type & qualified_result_type; + typedef Arity_tag<1> Arity; + + qualified_result_type operator() (const Circular_arc_point_2 & a) const + { + return (a.rep().x()); + } + }; + + + template + class Compute_Circular_y_2: Has_qrt + { + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Root_of_2 Root_of_2; + + public: + + typedef Root_of_2 result_type; + typedef const result_type & qualified_result_type; + typedef Arity_tag<1> Arity; + + qualified_result_type operator() (const Circular_arc_point_2 & a) const + { + return (a.rep().y()); + } + }; + + + template + class Construct_circular_min_vertex_2 : Has_qrt + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Line_arc_2 Line_arc_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + + public: + + typedef Circular_arc_point_2 result_type; + typedef const result_type & qualified_result_type; + typedef Arity_tag<1> Arity; + + qualified_result_type operator() (const Circular_arc_2 & a) const + { +// if (a.rep().Cache_minmax == 't') +// return (a.rep().source()); +// if (a.rep().Cache_minmax == 's') +// return (a.rep().target()); + return (a.rep().left()); + } + + qualified_result_type operator() (const Line_arc_2 & a) const + { + return (a.rep().left()); + } + + }; + + template + class Construct_circular_max_vertex_2: Has_qrt + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Line_arc_2 Line_arc_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + + public: + + typedef Circular_arc_point_2 result_type; + typedef const result_type & qualified_result_type; + typedef Arity_tag<1> Arity; + + qualified_result_type operator() (const Circular_arc_2 & a) const + { +// if (a.rep().Cache_minmax == 's') +// return (a.rep().source()); +// if (a.rep().Cache_minmax == 't') +// return (a.rep().target()); + return (a.rep().right()); + } + + qualified_result_type operator() (const Line_arc_2 & a) const + { + return (a.rep().right()); + } + + }; + + template + class Construct_circular_source_vertex_2: Has_qrt + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Line_arc_2 Line_arc_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + + public: + + typedef Circular_arc_point_2 result_type; + typedef const result_type & qualified_result_type; + typedef Arity_tag<1> Arity; + + qualified_result_type operator() (const Circular_arc_2 & a) const + { return a.rep().source(); } + + qualified_result_type operator() (const Line_arc_2 & a) const + { return a.rep().source();} + + }; + + + template + class Construct_circular_target_vertex_2: Has_qrt + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Line_arc_2 Line_arc_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + + public: + + typedef Circular_arc_point_2 result_type; + typedef const result_type & qualified_result_type; + typedef Arity_tag<1> Arity; + + qualified_result_type operator() (const Circular_arc_2 & a) const + { return a.rep().target();} + + qualified_result_type operator() (const Line_arc_2 & a) const + { return a.rep().target();} + + }; + + template + class Is_x_monotone_2 + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Line_arc_2 Line_arc_2; + + public: + + typedef bool result_type; + typedef Arity_tag<1> Arity; + + result_type operator() (const Circular_arc_2 & a) const + { + return (a.rep().is_x_monotone()); + } + + result_type operator() (const Line_arc_2 & a) const + { + return (a.rep().is_x_monotone()); + } + + }; + + template + class Is_y_monotone_2 + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Line_arc_2 Line_arc_2; + + public: + + typedef bool result_type; + typedef Arity_tag<1> Arity; + + result_type operator() (const Circular_arc_2 & a) const + { + return (a.rep().is_y_monotone()); + } + + result_type operator() (const Line_arc_2 & a) const + { + return (a.rep().is_y_monotone()); + } + + }; + + + template + class On_upper_part_2 + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + + public: + + typedef bool result_type; + typedef Arity_tag<1> Arity; + + result_type operator() (const Circular_arc_2 & a) const + { + return (a.rep().on_upper_part()); + } + }; + + template + class Construct_supporting_circle_2: Has_qrt + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Circle_2 Circle_2; + + public: + + typedef Circle_2 result_type; + typedef const result_type & qualified_result_type; + typedef Arity_tag<1> Arity; + + qualified_result_type operator() (const Circular_arc_2 & a) const + { + return (a.rep().supporting_circle()); + } + }; + + + template + class Construct_supporting_line_2: Has_qrt + { + typedef typename CK::Line_arc_2 Line_arc_2; + typedef typename CK::Line_2 Line_2; + typedef typename CK::Circle_2 Circle_2; + + public: + + typedef Line_2 result_type; + typedef const result_type & qualified_result_type; + typedef Arity_tag<1> Arity; + + qualified_result_type operator() (const Line_arc_2 & a) const + { + return (a.rep().supporting_line()); + } + }; + + template + class Construct_bbox_2 +#ifndef CGAL_CFG_MATCHING_BUG_6 + : public CK::Linear_kernel::Construct_bbox_2 +#endif + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Line_arc_2 Line_arc_2; + typedef typename CK::Circle_2 Circle_2; + + public: + + typedef CGAL::Bbox_2 result_type; + typedef Arity_tag<1> Arity; + +#ifndef CGAL_CFG_MATCHING_BUG_6 + using CK::Linear_kernel::Construct_bbox_2::operator(); +#else + typedef typename CK::Linear_kernel LK; + typedef typename LK::Construct_bbox_2 LK_Construct_bbox_2; + typedef typename LK::Point_2 Point_2; + + result_type operator() (const Circle_2 & a) const + { + return LK_Construct_bbox_2()(a); + } + + result_type operator() (const Point_2 & a) const + { + return LK_Construct_bbox_2()(a); + } +#endif + + result_type operator() (const Circular_arc_point_2 & a) const + { + return a.rep().bbox(); + } + + result_type operator() (const Circular_arc_2 & a) const + { + return a.rep().bbox(); + } + + result_type operator() (const Line_arc_2 & a) const + { + return a.rep().bbox(); + } + + }; + + template + class Bounded_side_2 + : public CK::Linear_kernel::Bounded_side_2 + { + typedef typename CK::Circle_2 Circle_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + + public: + typedef typename CK::Linear_kernel::Bounded_side result_type; + typedef Arity_tag< 2 > Arity; + + using CK::Linear_kernel::Bounded_side_2::operator(); + + result_type + operator()(const Circle_2& c, const Circular_arc_point_2& p) const + { return bounded_side(c,p); } + + }; + + template + class Has_on_bounded_side_2 + : public CK::Linear_kernel::Has_on_bounded_side_2 + { + typedef typename CK::Circle_2 Circle_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + + public: + typedef bool result_type; + typedef Arity_tag< 2 > Arity; + + using CK::Linear_kernel::Has_on_bounded_side_2::operator(); + + result_type + operator()(const Circle_2& c, const Circular_arc_point_2& p) const + { return CK().bounded_side_2_object()(c,p) == ON_BOUNDED_SIDE; } + + }; + + template + class Has_on_unbounded_side_2 + : public CK::Linear_kernel::Has_on_unbounded_side_2 + { + typedef typename CK::Circle_2 Circle_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + + public: + typedef bool result_type; + typedef Arity_tag< 2 > Arity; + + using CK::Linear_kernel::Has_on_unbounded_side_2::operator(); + + result_type + operator()(const Circle_2& c, const Circular_arc_point_2& p) const + { return CK().bounded_side_2_object()(c,p) == ON_UNBOUNDED_SIDE; } + + }; + +} // namespace CircularFunctors +} // namespace CGAL + +#endif // CGAL_CIRCULAR_KERNEL_FUNCTION_OBJECTS_POLYNOMIAL_CIRCULAR_H diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/functions_on_circle_2.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/functions_on_circle_2.h new file mode 100644 index 00000000000..31035747265 --- /dev/null +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/functions_on_circle_2.h @@ -0,0 +1,61 @@ +// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// 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. +// +// $URL$ +// $Id$ +// +// Author(s) : Monique Teillaud, Sylvain Pion + +// 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) + +#ifndef CGAL_CIRCULAR_KERNEL_FUNCTIONS_ON_CIRCLE_2_H +#define CGAL_CIRCULAR_KERNEL_FUNCTIONS_ON_CIRCLE_2_H + +namespace CGAL { + + // Should we have an iterator based interface, or both ? + template + typename CK::Circular_arc_point_2 + x_extremal_point(const Circle_2 & c, bool i) + { + return CircularFunctors::x_extremal_point(c,i); + } + + template + OutputIterator + x_extremal_points(const Circle_2 & c, OutputIterator res) + { + return CircularFunctors::x_extremal_points(c,res); + } + + template + typename CK::Circular_arc_point_2 + y_extremal_point(const Circle_2 & c, bool i) + { + return CircularFunctors::y_extremal_point(c,i); + } + + template + OutputIterator + y_extremal_points(const Circle_2 & c, OutputIterator res) + { + return CircularFunctors::y_extremal_points(c,res); + } + +} // namespace CGAL + +#endif // CGAL_CIRCULAR_KERNEL_FUNCTIONS_ON_CIRCLE_2_H diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/interface_macros.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/interface_macros.h new file mode 100644 index 00000000000..fcf0e80322b --- /dev/null +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/interface_macros.h @@ -0,0 +1,102 @@ +// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// 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. +// +// $URL$ +// $Id$ +// +// Author(s) : Monique Teillaud, Sylvain Pion + + +// This file is intentionally not protected against re-inclusion. +// It's aimed at being included from within a kernel traits class, this +// way we share more code. + +// It is the responsability of the including file to correctly set the 2 +// macros CGAL_Circular_Kernel_pred and CGAL_Circular_Kernel_cons. +// And they are #undefed at the end of this file. + + CGAL_Circular_Kernel_cons(Get_equation, + get_equation_object) + CGAL_Circular_Kernel_cons(Construct_circle_2, + construct_circle_2_object) + CGAL_Circular_Kernel_pred(Compare_x_2, + compare_x_2_object) + CGAL_Circular_Kernel_pred(Compare_y_2, + compare_y_2_object) + CGAL_Circular_Kernel_pred(Compare_xy_2, + compare_xy_2_object) + CGAL_Circular_Kernel_pred(Compare_y_at_x_2, + compare_y_at_x_2_object) + CGAL_Circular_Kernel_pred(Compare_y_to_right_2, + compare_y_to_right_2_object) + CGAL_Circular_Kernel_pred(Do_overlap_2, + do_overlap_2_object) + CGAL_Circular_Kernel_pred(Equal_2, + equal_2_object) + CGAL_Circular_Kernel_pred(In_x_range_2, + in_x_range_2_object) + CGAL_Circular_Kernel_cons(Make_x_monotone_2, + make_x_monotone_2_object) + CGAL_Circular_Kernel_cons(Make_xy_monotone_2, + make_xy_monotone_2_object) + CGAL_Circular_Kernel_cons(Advanced_make_x_monotone_2, + advanced_make_x_monotone_2_object) + CGAL_Circular_Kernel_cons(Advanced_make_xy_monotone_2, + advanced_make_xy_monotone_2_object) + CGAL_Circular_Kernel_cons(Intersect_2, + intersect_2_object) + CGAL_Circular_Kernel_cons(Split_2, + split_2_object) + CGAL_Circular_Kernel_cons(Construct_circular_arc_2, + construct_circular_arc_2_object) + CGAL_Circular_Kernel_cons(Construct_line_arc_2, + construct_line_arc_2_object) + CGAL_Circular_Kernel_cons(Construct_circular_arc_point_2, + construct_circular_arc_point_2_object) + CGAL_Circular_Kernel_cons(Compute_Circular_x_2, + compute_circular_x_2_object) + CGAL_Circular_Kernel_cons(Compute_Circular_y_2, + compute_circular_y_2_object) + CGAL_Circular_Kernel_cons(Construct_circular_min_vertex_2, + construct_circular_min_vertex_2_object) + CGAL_Circular_Kernel_cons(Construct_circular_max_vertex_2, + construct_circular_max_vertex_2_object) + CGAL_Circular_Kernel_cons(Construct_circular_source_vertex_2, + construct_circular_source_vertex_2_object) + CGAL_Circular_Kernel_cons(Construct_circular_target_vertex_2, + construct_circular_target_vertex_2_object) + CGAL_Circular_Kernel_pred(Is_x_monotone_2, + is_x_monotone_2_object) + CGAL_Circular_Kernel_pred(Is_y_monotone_2, + is_y_monotone_2_object) + CGAL_Circular_Kernel_pred(On_upper_part_2, + on_upper_part_2_object) + CGAL_Circular_Kernel_pred(Is_vertical_2, + is_vertical_2_object) + CGAL_Circular_Kernel_pred(Has_on_2, + has_on_2_object) + + CGAL_Circular_Kernel_pred(Has_on_bounded_side_2, has_on_bounded_side_2_object) + CGAL_Circular_Kernel_pred(Has_on_unbounded_side_2, has_on_unbounded_side_2_object) + CGAL_Circular_Kernel_pred(Bounded_side_2, bounded_side_2_object) + + CGAL_Circular_Kernel_cons(Construct_supporting_circle_2, + construct_supporting_circle_2_object) + CGAL_Circular_Kernel_cons(Construct_supporting_line_2, + construct_supporting_line_2_object) + CGAL_Circular_Kernel_cons(Construct_bbox_2, + construct_bbox_2_object) + + +#undef CGAL_Circular_Kernel_pred +#undef CGAL_Circular_Kernel_cons diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_circle_2.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_circle_2.h new file mode 100644 index 00000000000..e533e94c5e1 --- /dev/null +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_circle_2.h @@ -0,0 +1,194 @@ +// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// 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. +// +// $URL$ +// $Id$ +// +// Author(s) : Monique Teillaud, Sylvain Pion + +// 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) + +#ifndef CGAL_CIRCULAR_KERNEL_INTERNAL_FUNCTIONS_ON_CIRCLE_2_H +#define CGAL_CIRCULAR_KERNEL_INTERNAL_FUNCTIONS_ON_CIRCLE_2_H + +CGAL_BEGIN_NAMESPACE + +// temporary function : where to put it, if we want to keep it ? +template< class CK> +typename CK::Circular_arc_point_2 +circle_intersect( const typename CK::Circle_2 & c1, + const typename CK::Circle_2 & c2, + bool b ) +{ + typedef std::vector solutions_container; + solutions_container solutions; + + CGAL::intersect_2( c1, c2, std::back_inserter(solutions) ); + + typename solutions_container::iterator it = solutions.begin(); + + CGAL_kernel_precondition( it != solutions.end() ); + // the circles intersect + + const std::pair *result; + result = CGAL::object_cast< + std::pair > (&(*it)); + + if ( result->second == 2 ) // double solution + return result->first; + + if (b) + return result->first; + + ++it; + result = CGAL::object_cast< + std::pair >(&(*it)); + + return result->first; +} + +namespace CircularFunctors { + + template < class CK > + typename CK::Polynomial_for_circles_2_2 + get_equation( const typename CK::Circle_2 & c ) + { + typedef typename CK::RT RT; + + typedef typename CK::Algebraic_kernel AK; + + return AK().construct_polynomial_for_circles_2_2_object() + ( c.center().x(), c.center().y(), c.squared_radius() ); + } + + template < class CK > + typename CK::Circle_2 + construct_circle_2( const typename CK::Polynomial_for_circles_2_2 &eq ) + { + return typename + CK::Circle_2( typename CK::Point_2(eq.a(), eq.b()), eq.r_sq() ); + } + + template < class CK > + bool + has_on(const typename CK::Circle_2 &a, + const typename CK::Circular_arc_point_2 &p) + { + typedef typename CK::Algebraic_kernel AK; + typedef typename CK::Polynomial_for_circles_2_2 Polynomial_for_circles_2_2; + Polynomial_for_circles_2_2 equation = CircularFunctors::get_equation(a); + + return (AK().sign_at_object()(equation,p.coordinates()) == ZERO); + } + + template < class CK > + inline bool + non_oriented_equal(const typename CK::Circle_2 & c1, + const typename CK::Circle_2 & c2) { + if(identical(c1,c2)) return true; + return (c1.squared_radius() == c2.squared_radius()) && + (c1.center() == c2.center()); + } + + template < class CK > + inline + typename CK::Linear_kernel::Bounded_side + bounded_side(const typename CK::Circle_2 &c, + const typename CK::Circular_arc_point_2 &p) { + typedef typename CK::AK AK; + typedef typename CK::Polynomial_for_circles_2_2 Equation; + Equation equation = get_equation(c); + Sign sign = AK().sign_at_object()(equation,p.rep().coordinates()); + if(sign == NEGATIVE) return ON_BOUNDED_SIDE; + else if(sign == POSITIVE) return ON_UNBOUNDED_SIDE; + else return ON_BOUNDARY; + } + + template< class CK, class OutputIterator> + OutputIterator + intersect_2( const typename CK::Circle_2 & c1, + const typename CK::Circle_2 & c2, + OutputIterator res ) + { + typedef typename CK::Algebraic_kernel AK; + typedef typename CK::Polynomial_for_circles_2_2 Equation; + typedef typename CK::Root_for_circles_2_2 Root_for_circles_2_2; + Equation e1 = CircularFunctors::get_equation(c1); + Equation e2 = CircularFunctors::get_equation(c2); + + if (e1 == e2) { + *res++ = make_object(e1); + return res; + } + + typedef std::vector< std::pair < Root_for_circles_2_2, unsigned > > + solutions_container; + solutions_container solutions; + + AK().solve_object()(e1, e2, std::back_inserter(solutions)); + // to be optimized + + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + + for ( typename solutions_container::iterator it = solutions.begin(); + it != solutions.end(); ++it ) + { + *res++ = make_object(std::make_pair(Circular_arc_point_2(it->first), + it->second )); + } + + return res; + } + + // Should we have an iterator based interface, or both ? + template + typename CK::Circular_arc_point_2 + x_extremal_point(const typename CK::Circle_2 & c, bool i) + { + typedef typename CK::Algebraic_kernel AK; + return AK().x_critical_points_object()(typename CK::Get_equation()(c),i); + } + + template + OutputIterator + x_extremal_points(const typename CK::Circle_2 & c, OutputIterator res) + { + typedef typename CK::Algebraic_kernel AK; + return AK().x_critical_points_object()(typename CK::Get_equation()(c),res); + } + + template + typename CK::Circular_arc_point_2 + y_extremal_point(const typename CK::Circle_2 & c, bool i) + { + typedef typename CK::Algebraic_kernel AK; + return AK().y_critical_points_object()(typename CK::Get_equation()(c),i); + } + + template + OutputIterator + y_extremal_points(const typename CK::Circle_2 & c, OutputIterator res) + { + typedef typename CK::Algebraic_kernel AK; + return AK().y_critical_points_object()(typename CK::Get_equation()(c),res); + } + +} // namespace CircularFunctors + +CGAL_END_NAMESPACE + +#endif // CGAL_CIRCULAR_KERNEL_INTERNAL_FUNCTIONS_ON_CIRCLE_2_H diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_circular_arc_2.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_circular_arc_2.h new file mode 100644 index 00000000000..cd506b6564a --- /dev/null +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_circular_arc_2.h @@ -0,0 +1,1694 @@ +// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// 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. +// +// $URL$ +// $Id$ +// +// Author(s) : Monique Teillaud, Sylvain Pion + +// 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) + +#ifndef CGAL_CIRCULAR_KERNEL_PREDICATES_ON_CIRCULAR_ARC_2_H +#define CGAL_CIRCULAR_KERNEL_PREDICATES_ON_CIRCULAR_ARC_2_H + +#include +#include +#include + +namespace CGAL { +namespace CircularFunctors { + + + template < class CK > + inline + Comparison_result + compare_x(const typename CK::Circular_arc_point_2 &p0, + const typename CK::Circular_arc_point_2 &p1) + { + typedef typename CK::Algebraic_kernel AK; + if(p0.equal_ref(p1)) return static_cast(0); + return AK().compare_x_object()(p0.coordinates(), p1.coordinates()); + } + + template < class CK > + inline + Comparison_result + compare_y(const typename CK::Circular_arc_point_2 &p0, + const typename CK::Circular_arc_point_2 &p1) + { + typedef typename CK::Algebraic_kernel AK; + if(p0.equal_ref(p1)) return static_cast(0); + return AK().compare_y_object()(p0.coordinates(), p1.coordinates()); + } + + template < class CK > + Comparison_result + compare_xy(const typename CK::Circular_arc_point_2 &p0, + const typename CK::Circular_arc_point_2 &p1) + { + typedef typename CK::Algebraic_kernel AK; + return AK().compare_xy_object()(p0.coordinates(), p1.coordinates()); + } + +// template < class CK > +// inline +// Comparison_result +// compare_x(const typename CK::Circular_arc_point_2 &p0, +// const typename CK::Point_2 &p1) +// { +// return CGAL::compare(p0.x(), p1.x()); +// } + +// template < class CK > +// inline +// Comparison_result +// compare_x(const typename CK::Point_2 &p0, +// const typename CK::Circular_arc_point_2 &p1) +// { +// return CGAL::compare(p0.x(), p1.x()); +// } + + +// template < class CK > +// inline +// Comparison_result +// compare_y(const typename CK::Circular_arc_point_2 &p0, +// const typename CK::Point_2 &p1) +// { +// return CGAL::compare(p0.y(), p1.y()); +// } + +// template < class CK > +// inline +// Comparison_result +// compare_y(const typename CK::Point_2 &p0, +// const typename CK::Circular_arc_point_2 &p1) +// { +// return CGAL::compare(p0.y(), p1.y()); +// } + + +// template < class CK > +// Comparison_result +// compare_xy(const typename CK::Circular_arc_point_2 &p0, +// const typename CK::Point_2 &p1) +// { +// Comparison_result compx = compare_x(p0, p1); +// if (compx != 0) +// return compx; +// return compare_y(p0, p1); +// } + +// template < class CK > +// Comparison_result +// compare_xy(const typename CK::Point_2 &p0, +// const typename CK::Circular_arc_point_2 &p1) +// { +// Comparison_result compx = compare_x(p0, p1); +// if (compx != 0) +// return compx; +// return compare_y(p0, p1); +// } + + + template < class CK > + bool + point_in_x_range(const typename CK::Circular_arc_2 &A, + const typename CK::Circular_arc_point_2 &p) + { + //CGAL_kernel_precondition (A.is_x_monotone()); + // range includes endpoints here + return CircularFunctors::compare_x( p, A.source()) != CircularFunctors::compare_x(p, A.target() ); + } + + template < class CK > + Comparison_result + compare_y_at_x(const typename CK::Circular_arc_point_2 &p, + const typename CK::Circular_arc_2 &A1) + { + //CGAL_kernel_precondition (A1.is_x_monotone()); + //CGAL_kernel_precondition (CircularFunctors::point_in_x_range(A1, p)); + + // Compare the ordinate of p with the ordinate of the center. + Comparison_result sgn = + CGAL::compare(p.y(), A1.supporting_circle().center().y()); + // Is the arc on the lower or upper part of the circle ? + // I.e. it's the comparison of the "ordinate" of the arc with the center. + Comparison_result cmp = A1.on_upper_part() ? LARGER : SMALLER; + if (sgn == opposite(cmp)) + return sgn; + + // If not, then we can compute if p is inside the circle or not. + typedef typename CK::Root_of_2 Root; + Root dx_sqr = CGAL::square(p.x() - A1.supporting_circle().center().x()); + Root dy_sqr = CGAL::square(p.y() - A1.supporting_circle().center().y()); + // NB : that one can be factorized with the above... + + // Now we want the comparison of dx_sqr + dy_sqr with squared_radius. + // It's the same as dx_sqr - squared_radius with -dy_sqr. + + Comparison_result distance_to_center = + CGAL::compare(dx_sqr, A1.supporting_circle().squared_radius() - dy_sqr); + + if (cmp > 0) + return distance_to_center; + else + return opposite(distance_to_center); + } + + + + template < class CK > + Comparison_result + compare_y_to_right(const typename CK::Circular_arc_2 &A1, + const typename CK::Circular_arc_2 &A2, + const typename CK::Circular_arc_point_2 &p) + { + // FIXME : add preconditions to check that the 2 arcs are defined at + // the right of the intersection. + //CGAL_kernel_precondition (A1.is_x_monotone()); + //CGAL_kernel_precondition (A2.is_x_monotone()); + + typedef std::vector solutions_container; + typedef typename CK::Circular_arc_2 Circular_arc_2; + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + // intersection found on the map + solutions_container early_sols; + if(Circular_arc_2::template find_intersection< solutions_container > + (A1,A2,early_sols)) { + if(A1.on_upper_part()) return LARGER; + return SMALLER; + } +#endif + + const typename CK::Circle_2 & C1 = A1.supporting_circle(); + const typename CK::Circle_2 & C2 = A2.supporting_circle(); + + if (CircularFunctors::non_oriented_equal(C1,C2)) { + // The point is either a left vertical tangent point of both, + // or a normal point (-> EQUAL). + bool b1 = A1.on_upper_part(); + bool b2 = A2.on_upper_part(); + if (b1 == b2) + return EQUAL; + if (b1 == true && b2 == false) + return LARGER; + CGAL_kernel_assertion (b1 == false && b2 == true); + return SMALLER; + } + + const typename CK::Root_of_2 b1_y = C1.center().y() - p.y(); + const typename CK::Root_of_2 b2_y = C2.center().y() - p.y(); + + int s_b1_y = CGAL::sign(b1_y); + int s_b2_y = CGAL::sign(b2_y); + + if (s_b1_y == 0) { + // Vertical tangent for A1. + if (s_b2_y != 0) + return A1.on_upper_part() ? LARGER : SMALLER; + // Vertical tangent for A2 also. + bool b1 = A1.on_upper_part(); + bool b2 = A2.on_upper_part(); + if (b1 == b2) + return b1 ? compare_x(C1.center(), C2.center()) + : compare_x(C2.center(), C1.center()); + if (b1 == true && b2 == false) + return LARGER; + CGAL_kernel_assertion (b1 == false && b2 == true); + return SMALLER; + } + + if (s_b2_y == 0) { + // Vertical tangent for A2. + return A2.on_upper_part() ? SMALLER : LARGER; + } + + // No more vertical tangent points. + CGAL_kernel_assertion(s_b1_y != 0); + CGAL_kernel_assertion(s_b2_y != 0); + + int s_b1_x = (int) CGAL::compare(p.x(), C1.center().x()); + int s_b2_x = (int) CGAL::compare(p.x(), C2.center().x()); + + // We compute the slope of the 2 tangents, then we compare them. + Comparison_result cmp = CGAL::compare(s_b1_y * s_b1_x, + s_b2_y * s_b2_x); + // The slopes have different signs. + if (cmp != 0) + return cmp; + + // The slopes have the same signs : we have to square. + if (CGAL::square(squared_distance(C1.center(), C2.center()) + - C1.squared_radius() - C2.squared_radius()) + < 4 * C1.squared_radius() * C2.squared_radius() ) + { + // The two circles are not tangent. + return static_cast + (CGAL::compare(C1.squared_radius() * CGAL::square(b2_y), + C2.squared_radius() * CGAL::square(b1_y)) + * s_b1_y * s_b1_x ); + } + + // tangent circles + if (s_b1_x * s_b2_x < 0) + // Circles are on both sides, and the tangent is not horizontal + return compare_y(C1.center(), C2.center()); + + if (s_b1_x * s_b2_x > 0) + // Circles are on the same side, and the tgt is not horizontal. + return compare_y(C2.center(), C1.center()); + + // The tangent is horizontal. + CGAL_kernel_assertion(s_b1_x == 0 && s_b2_x == 0); + if (s_b1_y == s_b2_y) + // The 2 circles are both below or both above the tangent + return compare_y(C2.center(), C1.center()); + + return compare_y(C1.center(), C2.center()); + } + + template < class CK > + inline + bool + equal(const typename CK::Circular_arc_point_2 &p0, + const typename CK::Circular_arc_point_2 &p1) + { + if(p0.equal_ref(p1)) return static_cast(1); + return CircularFunctors::compare_xy(p0, p1) == 0; + } + + template < class CK > + bool + equal(const typename CK::Circular_arc_2 &A1, + const typename CK::Circular_arc_2 &A2) + { + /*if ((A1.supporting_circle() != A2.supporting_circle()) && + (A1.supporting_circle() != A2.supporting_circle().opposite())) + return false;*/ + + if(!CircularFunctors::non_oriented_equal( + A1.supporting_circle(), A2.supporting_circle())) + return false; + + return (CircularFunctors::equal(A1.source(), A2.source()) && + CircularFunctors::equal(A1.target(), A2.target())); + } + +// template < class CK > +// bool +// equal(const typename CK::Circular_arc_2 &A1, +// const typename CK::Circular_arc_2 &A2) +// { +// CGAL_kernel_precondition (A1.is_x_monotone()); +// CGAL_kernel_precondition (A2.is_x_monotone()); + +// if ( A1.supporting_circle() != A2.supporting_circle() ) +// return false; + +// return equal( A1.source(), A2.source() ) +// && equal( A1.target(), A2.target() ); +// } + + // Small accessory function + // Tests whether a given point is on an arc, with the precondition that + // it's (symbolically) on the supporting circle. + /*template < class CK > + bool + has_on(const typename CK::Circular_arc_2 &a, + const typename CK::Circular_arc_point_2 &p, + const bool has_on_supporting_circle = false) + { + CGAL_kernel_precondition(a.is_x_monotone()); + +// typedef typename CK::Polynomial_for_circles_2_2 Polynomial_for_circles_2_2; +// Polynomial_for_circles_2_2 +// equation = get_equation(a.supporting_circle()); + +// if(CGAL::sign_at +// (equation,p.coordinates())!= ZERO) +// return false; + if(!has_on_supporting_circle) { + if ( ! CircularFunctors::has_on(a.supporting_circle(),p) ) + return false; + } + + if (! CircularFunctors::point_in_x_range(a, p) ) + return false; + + int cmp = CGAL::compare(p.y(), a.supporting_circle().center().y()); + + return cmp == 0 || (cmp > 0 && a.on_upper_part()) + || (cmp < 0 && !a.on_upper_part()); + }*/ + + template < class CK > + bool + has_on(const typename CK::Circular_arc_2 &a, + const typename CK::Circular_arc_point_2 &p, + const bool has_on_supporting_circle = false) + { + if(!has_on_supporting_circle) { + if ( ! CircularFunctors::has_on(a.supporting_circle(),p) ) + return false; + } + + if(a.is_full()) return true; + + if(a.is_x_monotone()) { + int cmp_ps = CircularFunctors::compare_x(p,a.source()); + int cmp_pt = CircularFunctors::compare_x(p,a.target()); + if(cmp_ps == cmp_pt) return false; + int cmp = CGAL::compare(p.y(), a.supporting_circle().center().y()); + return cmp == 0 || (cmp > 0 && a.on_upper_part()) + || (cmp < 0 && !a.on_upper_part()); + } else if(a.is_complementary_x_monotone()) { + int cmp_ps = CircularFunctors::compare_x(p,a.source()); + int cmp_pt = CircularFunctors::compare_x(p,a.target()); + if(cmp_ps == cmp_pt) return true; + if((!cmp_ps) || (!cmp_pt)) return true; + int cmp = CGAL::compare(p.y(), a.supporting_circle().center().y()); + return cmp == 0 || (cmp < 0 && a.complementary_on_upper_part()) + || (cmp > 0 && !a.complementary_on_upper_part()); + } else if(a.is_y_monotone()) { + int cmp_ps = CircularFunctors::compare_y(p,a.source()); + int cmp_pt = CircularFunctors::compare_y(p,a.target()); + if(cmp_ps == cmp_pt) return false; + int cmp = CGAL::compare(p.x(), a.supporting_circle().center().x()); + return cmp == 0 || (cmp < 0 && a.on_left_part()) + || (cmp > 0 && !a.on_left_part()); + } else if(a.is_complementary_y_monotone()) { + int cmp_ps = CircularFunctors::compare_y(p,a.source()); + int cmp_pt = CircularFunctors::compare_y(p,a.target()); + if(cmp_ps == cmp_pt) return true; + if((!cmp_ps) || (!cmp_pt)) return true; + int cmp = CGAL::compare(p.x(), a.supporting_circle().center().x()); + return cmp == 0 || (cmp > 0 && a.complementary_on_left_part()) + || (cmp < 0 && !a.complementary_on_left_part()); + } else { + int cmp_scy = CGAL::compare(a.source().y(), a.supporting_circle().center().y()); + int cmp = CGAL::compare(p.y(), a.supporting_circle().center().y()); + if(cmp_scy < 0) { + if(cmp > 0) return CGAL::compare(p.x(), a.target().x()) >= 0; + else return CGAL::compare(p.x(), a.source().x()) >= 0; + } else { + if(cmp > 0) return CGAL::compare(p.x(), a.source().x()) <= 0; + else return CGAL::compare(p.x(), a.target().x()) <= 0; + } + } + } + + template < class CK > + bool + do_overlap(const typename CK::Circular_arc_2 &A1, + const typename CK::Circular_arc_2 &A2) + { + //CGAL_kernel_precondition (A1.is_x_monotone()); + //CGAL_kernel_precondition (A2.is_x_monotone()); + + /*if ( (A1.supporting_circle() != A2.supporting_circle()) && + (A1.supporting_circle() != A2.supporting_circle().opposite()) ) + return false;*/ + if(!CircularFunctors::non_oriented_equal( + A1.supporting_circle(), A2.supporting_circle())) + return false; + + //if ( A1.on_upper_part() != A2.on_upper_part() ) return false; + + //return CircularFunctors::compare_x(A1.right(), A2.left()) > 0 + // && CircularFunctors::compare_x(A1.left(), A2.right()) < 0; + if(A1.is_full()) return true; + if(A2.is_full()) return true; + if((has_on(A1,A2.target(),true)) || + (has_on(A1,A2.source(),true))) return true; + return has_on(A2,A1.source(),true); + } + + + template < class CK > + void + split(const typename CK::Circular_arc_2 &A, + const typename CK::Circular_arc_point_2 &p, + typename CK::Circular_arc_2 &ca1, + typename CK::Circular_arc_2 &ca2) + { + //CGAL_kernel_precondition( A.is_x_monotone() ); + //CGAL_kernel_precondition( CircularFunctors::point_in_x_range( A, p ) ); + //CGAL_kernel_precondition( A.on_upper_part() == (p.y() > + // A.supporting_circle().center().y()) ); + //CGAL_kernel_precondition( CircularFunctors::has_on(A, p) ); + + typedef typename CK::Circular_arc_2 Circular_arc_2; + + const Circular_arc_2 &rc1 = + Circular_arc_2( A.supporting_circle(), A.source(), p); + const Circular_arc_2 &rc2 = + Circular_arc_2( A.supporting_circle(), p, A.target()); + + if ( CircularFunctors::compare_x(rc1.source(), rc2.source()) != SMALLER) { + ca1 = rc2; + ca2 = rc1; + } else { + ca1 = rc1; + ca2 = rc2; + } +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + std::vector < CGAL::Object > res; + + if(A.is_full()) { + res.push_back(make_object(std::make_pair(ca1.source(),1u))); + res.push_back(make_object(std::make_pair(ca2.source(),1u))); + } else { + res.push_back(make_object(std::make_pair(p,1u))); + } + + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,res); +#endif + + /*ca1 = Circular_arc_2( A.supporting_circle(), A.source(), p); + ca2 = Circular_arc_2( A.supporting_circle(), p, A.target()); + //if ( ca1.right()!=ca2.left() ) + if ( CircularFunctors::compare_x(ca1.left(), ca2.left()) != SMALLER ) + { + //std::cout << " SWAP " << std::endl; + std::swap(ca1,ca2); + }*/ + } + + template< class CK, class OutputIterator> + OutputIterator + intersect_2( const typename CK::Circular_arc_2 &a1, + const typename CK::Circular_arc_2 &a2, + OutputIterator res ) + { + typedef std::vector solutions_container; + typedef typename CK::Circular_arc_2 Circular_arc_2; + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + // same curve + if(a1.number() == a2.number()) { + *res++ = make_object(a1); + return res; + } + + // intersection found on the map + solutions_container early_sols; + if(Circular_arc_2::template find_intersection< solutions_container > + (a1,a2,early_sols)) { + for (typename solutions_container::iterator it = early_sols.begin(); + it != early_sols.end(); ++it) { + *res++ = *it; + } + return res; + } +#endif + + const bool sqr1_eq_sqr2 = (a1.squared_radius() == a2.squared_radius()); + const bool c1_eq_c2 = (a1.center() == a2.center()); + + if(sqr1_eq_sqr2 && c1_eq_c2) { + if(a1.is_full()) { + *res++ = make_object(a2); + //return res; + } + else if(a2.is_full()) { + *res++ = make_object(a1); + //return res; + } else { + bool t2_in_a1 = has_on(a1,a2.target(),true); + bool s2_in_a1 = has_on(a1,a2.source(),true); + if(t2_in_a1 && s2_in_a1) { + bool t1_in_a2 = has_on(a2,a1.target(),true); + bool s1_in_a2 = has_on(a2,a1.source(),true); + if(t1_in_a2 && s1_in_a2) { + const Comparison_result comp = + CircularFunctors::compare_xy(a1.source(), a2.source()); + if(comp < 0) { + if(a1.source() == a2.target()) { + *res++ = make_object(std::make_pair(a1.source(),1u)); + } else { + const Circular_arc_2 & arc = + Circular_arc_2(a1.supporting_circle(),a1.source(),a2.target()); + *res++ = make_object(arc); + } + if(a2.source() == a1.target()) { + *res++ = make_object(std::make_pair(a2.source(),1u)); + } else { + const Circular_arc_2 & arc = + Circular_arc_2(a1.supporting_circle(),a2.source(),a1.target()); + *res++ = make_object(arc); + } + } else if (comp > 0) { + if(a2.source() == a1.target()) { + *res++ = make_object(std::make_pair(a2.source(),1u)); + } else { + const Circular_arc_2 & arc = + Circular_arc_2(a1.supporting_circle(),a2.source(),a1.target()); + *res++ = make_object(arc); + } + if(a1.source() == a2.target()) { + *res++ = make_object(std::make_pair(a1.source(),1u)); + } else { + const Circular_arc_2 & arc = + Circular_arc_2(a1.supporting_circle(),a1.source(),a2.target()); + *res++ = make_object(arc); + } + } else { + *res++ = make_object(a1); + } + } else { + *res++ = make_object(a2); + //return res; + } + } + else if(t2_in_a1) { + if(a1.source() == a2.target()) + *res++ = make_object(std::make_pair(a1.source(),1u)); + else { + const Circular_arc_2 & arc = + Circular_arc_2(a1.supporting_circle(),a1.source(),a2.target()); + *res++ = make_object(arc); + } //return res; + } else if(s2_in_a1) { + if(a2.source() == a1.target()) { + *res++ = make_object(std::make_pair(a2.source(),1u)); + } else { + const Circular_arc_2 & arc = + Circular_arc_2(a1.supporting_circle(),a2.source(),a1.target()); + *res++ = make_object(arc); + } //return res; + } else if(has_on(a2,a1.source(),true)) { + *res++ = make_object(a1); + //return res; + } + //return res; + } + } else if(!c1_eq_c2) { + solutions_container solutions; + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + if(!Circular_arc_2::template + find_intersection_circle_circle< solutions_container > + (a1,a2,solutions)) { +#endif + + CGAL::intersect_2 ( a1.supporting_circle(), a2.supporting_circle(), + std::back_inserter(solutions) ); + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + Circular_arc_2::template + put_intersection_circle_circle< std::vector < CGAL::Object > > + (a1,a2,solutions); + } +#endif + + if(solutions.size() == 0) return res; + else { + // The supporting circles are not the same and intersects + for (typename solutions_container::iterator it = solutions.begin(); + it != solutions.end(); ++it) { + const std::pair + *result = CGAL::object_cast + > (&(*it)); + if (has_on(a1,result->first,true) && + has_on(a2,result->first,true)) { + *res++ = *it; + } + } + //return res; + } + } + return res; + } + + + // !!!! a lot of useless assertions for debug + /*template< class CK, class OutputIterator> + OutputIterator + intersect_2( const typename CK::Circular_arc_2 &a1, + const typename CK::Circular_arc_2 &a2, + OutputIterator res ) + { + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Circular_arc_2 Circular_arc_2; + + if (a1.is_x_monotone() && a2.is_x_monotone()) { + // Overlapping curves. + if ( (a1.supporting_circle() == a2.supporting_circle()) || + (a1.supporting_circle() == a2.supporting_circle().opposite()) ) { + // The ranges need to overlap in order for the curves to overlap. + if ( CircularFunctors::compare_x(a1.left(), a2.right()) > 0 || + CircularFunctors::compare_x(a2.left(), a1.right()) > 0) + return res; + + // They both need to be on the same upper/lower part. + if (a1.on_upper_part() != a2.on_upper_part()) { + // But they could share the left vertical tangent point. + if (a1.left() == a2.left()) + *res++ = make_object(std::make_pair(a1.left(),1u)); + // Or they could share the right vertical tangent point. + if (a1.right() == a2.right()) + *res++ = make_object(std::make_pair(a1.right(),1u)); + return res; + } + + // We know they overlap, determine the extremities of + // the common subcurve + // TODO : We should use std::max and std::min, but they + // require less_x_2. + const Circular_arc_2 & arctmp = + CircularFunctors::compare_x(a1.right(), a2.right()) < 0 ? a1 : a2; + // we know that the right endpoint is correct, let us look for + // the left now: + + + //? a1.left() : a2.left(); + if (CircularFunctors::compare_x(a1.left(), a2.left()) > 0) { + //the left endpoint is a1's + if (CircularFunctors::compare_x(a1.left(), a2.right()) < 0){ + if (a1.on_upper_part()) { + const Circular_arc_2 & arc = + Circular_arc_2(a1.supporting_circle(),a2.right(),a1.left()); + CGAL_kernel_assertion(arc.is_x_monotone()); + *res++ = make_object(arc); + } + else { + const Circular_arc_2 & arc = + Circular_arc_2(a1.supporting_circle(),a1.left(), a2.right()); + CGAL_kernel_assertion(arc.is_x_monotone()); + *res++ = make_object(arc); + } + } + else + *res++ = make_object(std::make_pair(arctmp.right(),1u)); + } + else if( CircularFunctors::compare_x(a1.left(), a2.left()) < 0 ) { + //the left endpoint is a2's + if(CircularFunctors::compare_x(a1.right(), a2.left()) > 0) { + if(a1.on_upper_part()){ + const Circular_arc_2 & arc = + Circular_arc_2(a1.supporting_circle(), a1.right(), a2.left()); + CGAL_kernel_assertion(arc.is_x_monotone()); + *res++ = make_object(arc); + } + else { + const Circular_arc_2 & arc = + Circular_arc_2(a1.supporting_circle(), a2.left(), a1.right()); + CGAL_kernel_assertion(arc.is_x_monotone()); + *res++ = make_object(arc); + } + } + else + *res++ = make_object(std::make_pair(arctmp.right(),1u)); + } + else { + if(CircularFunctors::compare_x(a1.right(), a2.right()) >= 0) + *res++ = make_object(a2); + else if(CircularFunctors::compare_x(a1.right(), a2.right()) < 0) + *res++ = make_object(a1); + else + *res++ = make_object(std::make_pair(arctmp.right(),1u)); + } + return res; + } + +// // We need to check that the supporting circles +// // do intersect before going further. +// if (! do_intersect(a1.supporting_circle(), a2.supporting_circle())) +// { return res; } +// +// // Get the two intersection points of the supporting circles. +// +// std::vector intersection_points; +// CGAL::intersect_2 +// ( a1.supporting_circle(), a2.supporting_circle(), +// std::back_inserter(intersection_points) ); + + std::vector intersection_points; + CGAL::intersect_2 ( a1.supporting_circle(), a2.supporting_circle(), + std::back_inserter(intersection_points) ); + if(intersection_points.size() == 0) return res; + + const Circular_arc_point_2 &left = + (CGAL::object_cast< std::pair > + (&(intersection_points[0])))->first; + if (intersection_points.size() < 2){// multiplicity 2 + if (CircularFunctors::has_on(a1, left) && CircularFunctors::has_on(a2, left)) + *res++ = make_object(std::make_pair(left,2u)); + } + else {// multiplicity 1 + const Circular_arc_point_2 &right = + (CGAL::object_cast< std::pair > + (&(intersection_points[1])))->first; + // We also need to check that these intersection points are on the arc. + if (CircularFunctors::has_on(a1, left) && CircularFunctors::has_on(a2, left)) + *res++ = make_object(std::make_pair(left,1u)); + if (CircularFunctors::has_on(a1, right) && CircularFunctors::has_on(a2, right)) + *res++ = make_object(std::make_pair(right,1u)); + } + return res; + } + else {//a1 or a2 are not x_monotone + std::vector< CGAL::Object > arcs_a1_x_monotone; + make_x_monotone( a1, std::back_inserter(arcs_a1_x_monotone)); + std::vector< CGAL::Object > arcs_a2_x_monotone; + make_x_monotone( a2, std::back_inserter(arcs_a2_x_monotone)); + std::vector< Circular_arc_2 > circle_arcs; + std::vector< Circular_arc_point_2 > circle_arc_endpoints; + + for ( std::vector< CGAL::Object >::iterator it1 = + arcs_a1_x_monotone.begin(); + it1 != arcs_a1_x_monotone.end(); ++it1 ) { + //CGAL_kernel_assertion(assign( a1_aux, *it1)); + const Circular_arc_2 *a1_aux = + CGAL::object_cast< Circular_arc_2 >(&*it1); + + for ( std::vector< CGAL::Object >::iterator it2 = + arcs_a2_x_monotone.begin(); + it2 != arcs_a2_x_monotone.end(); ++it2 ) { + //CGAL_kernel_assertion(assign( a2_aux, *it2)); + //assign( a2_aux, *it2); + const Circular_arc_2 *a2_aux = + CGAL::object_cast(&*it2); + std::vector< CGAL::Object > res_aux; + CircularFunctors::intersect_2( *a1_aux, *a2_aux, std::back_inserter(res_aux)); + if(res_aux.size() == 2){ + //it can't be a circular_arc_2 + //CGAL_kernel_assertion(assign(the_pair, res_aux[0])); + const std::pair *the_pair1 = + CGAL::object_cast > + (&res_aux[0]); + Circular_arc_point_2 arc_end1 = the_pair1->first; + //assign(the_pair, res_aux[1]); + const std::pair *the_pair2 = + CGAL::object_cast > + (&res_aux[1]); + Circular_arc_point_2 arc_end2 = the_pair2->first; + bool exist = false; + for (typename std::vector< Circular_arc_point_2 >::iterator it + = circle_arc_endpoints.begin(); + it != circle_arc_endpoints.end(); ++it ) { + if (arc_end1 == *it) { + exist = true; + break; + } + } + if (!exist) { + circle_arc_endpoints.push_back(arc_end1); + } + else exist = false; + for ( typename std::vector< Circular_arc_point_2 >::iterator it + = circle_arc_endpoints.begin(); + it != circle_arc_endpoints.end(); ++it ) { + if (arc_end2 == *it) { + exist = true; + break; + } + } + if (!exist) + circle_arc_endpoints.push_back(arc_end2); + } + else if( res_aux.size() == 1){ + //it can be a Circular_arc_point_2 or a Circular_arc_2 + if(const Circular_arc_2 *arc = + CGAL::object_cast(&res_aux[0])) { + //if(assign(arc,res_aux[0])){ + circle_arcs.push_back(*arc); + } + else { + //CGAL_kernel_assertion(assign(the_pair, res_aux[0])); + //assign(the_pair, res_aux[0]); + const std::pair *the_pair = + CGAL::object_cast > + (&res_aux[0]); + Circular_arc_point_2 arc_end = the_pair->first; + if (the_pair->second == 2u) {//there are only one tangent point + *res++ = res_aux[0]; + return res; + } + bool exist = false; + for (typename std::vector< Circular_arc_point_2 >::iterator it + = circle_arc_endpoints.begin(); + it != circle_arc_endpoints.end(); ++it ) { + if (arc_end == *it) { + exist = true; + break; + } + } + if (!exist) + circle_arc_endpoints.push_back(arc_end); + } + } + } + } + //there are not double + if (circle_arcs.size() > 0){ + std::size_t i = 1; + while((i < circle_arcs.size()) && + (circle_arcs[i-1].target().x() == circle_arcs[i].source().x()) && + (circle_arcs[i-1].target().y() == circle_arcs[i].source().y()) + ) + {i++;} + + *res++ = make_object + (Circular_arc_2(circle_arcs[0].supporting_circle(), + circle_arcs[0].source(), + circle_arcs[i-1].target() + )); + if (i < circle_arcs.size()) {//there are 2 circle arcs + std::size_t j = i; + i++; + while((i < circle_arcs.size()) + && (circle_arcs[i-1].target() == circle_arcs[i].source())) + i++; + *res++ = make_object + (Circular_arc_2(circle_arcs[j].supporting_circle(), + circle_arcs[j].source(), + circle_arcs[i-1].target() + )); + return res; + } + else {//There are one circle arc and there can be maximum one endpoint + for (typename std::vector< Circular_arc_point_2 >::iterator it1 + = circle_arc_endpoints.begin(); + it1 != circle_arc_endpoints.end(); ++it1 ) { + bool other_point = true; + for (typename std::vector< Circular_arc_2 >::iterator it2 + = circle_arcs.begin(); + it2 != circle_arcs.end(); ++it2 ) + { + if (CircularFunctors::has_on(*it2, *it1)) { + other_point = false; + break; + } + } + if (other_point) { + *res++ = make_object(std::make_pair(*it1,1u)); + break; + } + } + return res; + } + } + else{//there are one or two endpoint + if (circle_arc_endpoints.size() > 1){ + *res++ = make_object(std::make_pair(circle_arc_endpoints[0],1u)); + *res++ = make_object(std::make_pair(circle_arc_endpoints[1],1u)); + } + else if (circle_arc_endpoints.size() == 1) + *res++ = make_object(std::make_pair(circle_arc_endpoints[0],1u)); + return res; + } + } + }*/ + + template < class CK > + bool + is_vertical(const typename CK::Circular_arc_2 &a) + { + return false; + } + +template < class CK, class OutputIterator > + OutputIterator + make_x_monotone( const typename CK::Circular_arc_2 &A, + OutputIterator res ) + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Circle_2 Circle_2; + typedef typename CK::FT FT; + typedef typename CK::Point_2 Point_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Root_for_circles_2_2 Root_for_circles_2_2; + + CGAL_kernel_precondition(A.supporting_circle().squared_radius() != 0); + + if (A.is_x_monotone()) { + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + // get a number for its supporting circle + A.circle_number(); +#endif + + *res++ = make_object(A); + return res; + } + + std::vector< Root_for_circles_2_2 > vector_x_extremal_points; + CircularFunctors::x_extremal_points(A.supporting_circle(), + std::back_inserter(vector_x_extremal_points)); + Circular_arc_point_2 x_extremal_point1 = vector_x_extremal_points[0]; + Circular_arc_point_2 x_extremal_point2 = vector_x_extremal_points[1]; + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + std::vector < CGAL::Object > intersecs1; + std::vector < CGAL::Object > intersecs2; + std::vector < CGAL::Object > intersecs3; +#endif + + if (A.is_full()) { + const Circular_arc_2 &ca1 = Circular_arc_2(A.supporting_circle(), + x_extremal_point1, + x_extremal_point2); + const Circular_arc_2 &ca2 = Circular_arc_2(A.supporting_circle(), + x_extremal_point2, + x_extremal_point1); + ca1._setx_info(2,1,0); //setting flags outside + ca2._setx_info(2,2,0); + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + // get a number for its supporting circle + unsigned int cn = ca1.circle_number(); + ca2.set_circle_number(cn); +#endif + + *res++ = make_object(ca1); + *res++ = make_object(ca2); + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + intersecs1.push_back(make_object(std::make_pair(x_extremal_point1,1u))); + intersecs1.push_back(make_object(std::make_pair(x_extremal_point2,1u))); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,intersecs1); +#endif + + return res; + } + + int cmp_begin = CGAL::compare(A.source().y(), A.center().y()); + int cmp_end = CGAL::compare(A.target().y(), A.center().y()); + + // Define the 2 Circular_arc_endpoints + // in the 2 vertical tangent points + + + if (cmp_begin > 0) { + const Circular_arc_2 &ca1 = Circular_arc_2(A.supporting_circle(), + A.source(), + x_extremal_point1); + ca1._setx_info(2,2,0); + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + unsigned int cn = ca1.circle_number(); +#endif + + *res++ = make_object(ca1); + if (cmp_end > 0) { + // We must cut in 3 parts. + const Circular_arc_2 &ca2 = Circular_arc_2(A.supporting_circle(), + x_extremal_point1, + x_extremal_point2); + const Circular_arc_2 &ca3 = Circular_arc_2(A.supporting_circle(), + x_extremal_point2, + A.target()); + ca2._setx_info(2,1,0); + ca3._setx_info(2,2,0); + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + ca2.set_circle_number(cn); + ca3.set_circle_number(cn); +#endif + + *res++ = make_object(ca2); + *res++ = make_object(ca3); +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + intersecs1.push_back(make_object(std::make_pair(x_extremal_point1,1u))); + intersecs2.push_back(make_object(std::make_pair(x_extremal_point2,1u))); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,intersecs1); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca2,ca3,intersecs2); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca3,intersecs3); //empty - no intersection +#endif + } + else { + const Circular_arc_2 &ca2 = Circular_arc_2(A.supporting_circle(), + x_extremal_point1, + A.target()); + ca2._setx_info(2,1,0); + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + ca2.set_circle_number(cn); +#endif + + *res++ = make_object(ca2); + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + intersecs1.push_back(make_object(std::make_pair(x_extremal_point1,1u))); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,intersecs1); +#endif + + } + } + else if (cmp_begin < 0) { + const Circular_arc_2 &ca1 = Circular_arc_2(A.supporting_circle(), + A.source(), + x_extremal_point2); + ca1._setx_info(2,1,0); + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + unsigned int cn = ca1.circle_number(); +#endif + + *res++ = make_object(ca1); + if (cmp_end < 0) { + const Circular_arc_2 &ca2 = Circular_arc_2(A.supporting_circle(), + x_extremal_point2, + x_extremal_point1); + const Circular_arc_2 &ca3 = Circular_arc_2(A.supporting_circle(), + x_extremal_point1, + A.target()); + ca2._setx_info(2,2,0); + ca3._setx_info(2,1,0); + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + ca2.set_circle_number(cn); + ca3.set_circle_number(cn); +#endif + + *res++ = make_object(ca2); + *res++ = make_object(ca3); + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + intersecs1.push_back(make_object(std::make_pair(x_extremal_point2,1u))); + intersecs2.push_back(make_object(std::make_pair(x_extremal_point1,1u))); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,intersecs1); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca2,ca3,intersecs2); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca3,intersecs3); +#endif + + } + else { + const Circular_arc_2 &ca2 = Circular_arc_2(A.supporting_circle(), + x_extremal_point2, + A.target()); + ca2._setx_info(2,2,0); + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + ca2.set_circle_number(cn); +#endif + + *res++ = make_object(ca2); + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + intersecs1.push_back(make_object(std::make_pair(x_extremal_point2,1u))); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,intersecs1); +#endif + + } + } + else { // cmp_begin == 0 + if (CGAL::compare(A.source().x(), A.center().x()) < 0) { + CGAL_kernel_assertion (cmp_end >= 0); + const Circular_arc_2 &ca1 = Circular_arc_2(A.supporting_circle(), + x_extremal_point1, + x_extremal_point2); + const Circular_arc_2 &ca2 = Circular_arc_2(A.supporting_circle(), + x_extremal_point2, + A.target()); + ca1._setx_info(2,1,0); + ca2._setx_info(2,2,0); + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + unsigned int cn = ca1.circle_number(); + ca2.set_circle_number(cn); +#endif + + *res++ = make_object(ca1); + *res++ = make_object(ca2); + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + intersecs1.push_back(make_object(std::make_pair(x_extremal_point2,1u))); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,intersecs1); +#endif + + } + else { + CGAL_kernel_assertion + (CGAL::compare(A.source().x(), A.center().x()) > 0); + CGAL_kernel_assertion (cmp_end != LARGER); + const Circular_arc_2 &ca1 = Circular_arc_2(A.supporting_circle(), + x_extremal_point2, + x_extremal_point1); + const Circular_arc_2 &ca2 = Circular_arc_2(A.supporting_circle(), + x_extremal_point1, + A.target()); + ca1._setx_info(2,2,0); + ca2._setx_info(2,1,0); + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + unsigned int cn = ca1.circle_number(); + ca2.set_circle_number(cn); +#endif + + *res++ = make_object(ca1); + *res++ = make_object(ca2); + +#ifdef CGAL_INTERSECTION_MAP_FOR_XMONOTONIC_ARC_WITH_SAME_SUPPORTING_CIRCLE + intersecs1.push_back(make_object(std::make_pair(x_extremal_point1,1u))); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,intersecs1); +#endif + + } + } + return res; + } + + + /* template < class CK, class OutputIterator > + OutputIterator + make_x_monotone( const typename CK::Circular_arc_2 &A, + OutputIterator res ) + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Circle_2 Circle_2; + typedef typename CK::FT FT; + typedef typename CK::Point_2 Point_2; + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Root_for_circles_2_2 Root_for_circles_2_2; + + if (A.is_x_monotone()) { + *res++ = make_object(A); + return res; + } + + // Define the 2 Circular_arc_endpoints + // in the 2 vertical tangent points + + std::vector< Root_for_circles_2_2 > vector_x_extremal_points; + CircularFunctors::x_extremal_points(A.supporting_circle(), + std::back_inserter(vector_x_extremal_points)); + Circular_arc_point_2 x_extremal_point1 = vector_x_extremal_points[0]; + Circular_arc_point_2 x_extremal_point2 = vector_x_extremal_points[1]; + + std::vector < CGAL::Object > intersecs1; + std::vector < CGAL::Object > intersecs2; + std::vector < CGAL::Object > intersecs3; + + if (A.is_full()) { + Circular_arc_2 ca1(A.supporting_circle(), x_extremal_point1, + x_extremal_point2); + Circular_arc_2 ca2(A.supporting_circle(), x_extremal_point2, + x_extremal_point1); + *res++ = make_object(ca1); + *res++ = make_object(ca2); + intersecs1.push_back(make_object(std::make_pair(x_extremal_point1,1u))); + intersecs1.push_back(make_object(std::make_pair(x_extremal_point2,1u))); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,intersecs1); + return res; + } + + int cmp_begin = CGAL::compare(A.source().y(), A.center().y()); + int cmp_end = CGAL::compare(A.target().y(), A.center().y()); + + if (cmp_begin > 0) { + Circular_arc_2 ca1(A.supporting_circle(), A.source(), x_extremal_point1); + *res++ = make_object(ca1); + if (cmp_end > 0) { + // We must cut in 3 parts. + Circular_arc_2 ca2(A.supporting_circle(), x_extremal_point1, + x_extremal_point2); + Circular_arc_2 ca3(A.supporting_circle(), x_extremal_point2, + A.target()); + *res++ = make_object(ca2); + *res++ = make_object(ca3); + intersecs1.push_back(make_object(std::make_pair(x_extremal_point1,1u))); + intersecs2.push_back(make_object(std::make_pair(x_extremal_point2,1u))); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,intersecs1); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca2,ca3,intersecs2); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca3,intersecs3); //empty - no intersection + } + else { + Circular_arc_2 ca2(A.supporting_circle(), x_extremal_point1, + A.target()); + *res++ = make_object(ca2); + intersecs1.push_back(make_object(std::make_pair(x_extremal_point1,1u))); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,intersecs1); + } + } + else if (cmp_begin < 0) { + // Very similar to the previous case. + Circular_arc_2 ca1(A.supporting_circle(), A.source(), x_extremal_point2); + *res++ = make_object(ca1); + if (cmp_end > 0) { + // We must cut in 3 parts. + Circular_arc_2 ca2(A.supporting_circle(), x_extremal_point2, + x_extremal_point1); + Circular_arc_2 ca3(A.supporting_circle(), x_extremal_point1, + A.target()); + *res++ = make_object(ca2); + *res++ = make_object(ca3); + intersecs1.push_back(make_object(std::make_pair(x_extremal_point2,1u))); + intersecs2.push_back(make_object(std::make_pair(x_extremal_point1,1u))); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,intersecs1); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca2,ca3,intersecs2); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca3,intersecs3); //empty - no intersection + } + else { + Circular_arc_2 ca2(A.supporting_circle(), x_extremal_point2, + A.target()); + *res++ = make_object(ca2); + intersecs1.push_back(make_object(std::make_pair(x_extremal_point2,1u))); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,intersecs1); + } + } + else { // cmp_begin == 0 + if (CGAL::compare(A.source().x(), A.center().x()) < 0) { + CGAL_kernel_assertion (cmp_end >= 0); + Circular_arc_2 ca1(A.supporting_circle(), x_extremal_point1, + x_extremal_point2); + Circular_arc_2 ca2(A.supporting_circle(), x_extremal_point2, + A.target()); + *res++ = make_object(ca1); + *res++ = make_object(ca2); + intersecs1.push_back(make_object(std::make_pair(x_extremal_point2,1u))); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,intersecs1); + } + else { + CGAL_kernel_assertion + (CGAL::compare(A.source().x(), A.center().x()) > 0); + CGAL_kernel_assertion (cmp_end != LARGER); + Circular_arc_2 ca1(A.supporting_circle(), x_extremal_point2, + x_extremal_point1); + Circular_arc_2 ca2(A.supporting_circle(), x_extremal_point1, + A.target()); + *res++ = make_object(ca1); + *res++ = make_object(ca2); + intersecs1.push_back(make_object(std::make_pair(x_extremal_point1,1u))); + Circular_arc_2::template put_intersection< std::vector < CGAL::Object > > + (ca1,ca2,intersecs1); + } + } + return res; + }*/ + + + + +// This is the make_x_monotone function returning extra information: +// The ouput iterator refers to pairs, the first part of which is an +// object containing the x-monotone arc and the second part is a +// boolean defining whether the arc is on the upper part of the +// circle or not. This extra information returned by make_x_monotone +// and make_xy_monotone helps us to avoid doing twice the same +// comparisons by the functions which call these two in order to define +// the position of the returned arcs on the circle , like in the +// construct_bounding_hexagons function + + template < class CK, class OutputIterator > + OutputIterator + advanced_make_x_monotone( const typename CK::Circular_arc_2 &A, + OutputIterator res ) + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Circle_2 Circle_2; + typedef typename CK::FT FT; + typedef typename CK::Point_2 Point_2; + typedef std::pair S_pair; + + + int cmp_begin_y = CGAL::compare + (A.source().y(), A.supporting_circle().center().y()); + int cmp_end_y = CGAL::compare + (A.target().y(), A.supporting_circle().center().y()); + + int cmp_x=compare_x(A.source(),A.target()); + + // We don't need to split + if (cmp_begin_y != opposite(cmp_end_y) && + (((cmp_begin_y > 0 || cmp_end_y > 0) && cmp_x > 0) || + (cmp_begin_y < 0 || cmp_end_y < 0) && cmp_x < 0) ) { + + *res++ = S_pair(make_object(A),(cmp_begin_y>0 || cmp_end_y>0) ); + return res; + } + + // Half circles + if (cmp_begin_y == 0 && cmp_end_y == 0 && cmp_x != 0) { + *res++ = std::make_pair(make_object(A), cmp_x>0 ); + return res; + } + + // We need to split + //assert(!A.is_x_monotone()); + if (cmp_begin_y > 0) { + + *res++ = S_pair + (make_object(Circular_arc_2(A.supporting_circle(), A.source(), + CircularFunctors::x_extremal_point + (A.supporting_circle(),true))), + true); + + if (cmp_end_y > 0) { + // We must cut in 3 parts. + *res++ = std::make_pair + (make_object(Circular_arc_2 (A.supporting_circle(), + CircularFunctors::x_extremal_point + (A.supporting_circle(),true), + CircularFunctors::x_extremal_point + (A.supporting_circle(),false))), + false); + + *res++ = std::make_pair + (make_object(Circular_arc_2 (A.supporting_circle(), + CircularFunctors::x_extremal_point + (A.supporting_circle(),false), + A.target())), + true); + } else { + *res++ = std::make_pair + (make_object(Circular_arc_2 (A.supporting_circle(), + CircularFunctors::x_extremal_point + (A.supporting_circle(),true), + A.target())), + false); + } + } + else if (cmp_begin_y < 0) { + // Very similar to the previous case. + *res++ = std::make_pair + (make_object(Circular_arc_2 (A.supporting_circle(), + A.source(), + CircularFunctors::x_extremal_point + (A.supporting_circle(),false))), + false); + + if (cmp_end_y < CGAL::EQUAL) { + // We must cut in 3 parts. + *res++ = std::make_pair + (make_object(Circular_arc_2 (A.supporting_circle(), + CircularFunctors::x_extremal_point + (A.supporting_circle(),false), + CircularFunctors::x_extremal_point + (A.supporting_circle(),true))) , + true ); + + *res++ = std::make_pair + (make_object(Circular_arc_2 (A.supporting_circle(), + CircularFunctors::x_extremal_point + (A.supporting_circle(),true), + A.target())), + false); + } else { + *res++ = std::make_pair + (make_object(Circular_arc_2 (A.supporting_circle(), + CircularFunctors::x_extremal_point + (A.supporting_circle(),false), + A.target())), + true); + } + } + else { // cmp_begin_y == 0 + if ( compare(A.source().x(),A.supporting_circle().center().x())< 0) { + assert (cmp_end_y >= 0); + *res++ = std::make_pair + (make_object(Circular_arc_2 (A.supporting_circle(), + A.source(), + CircularFunctors::x_extremal_point + (A.supporting_circle(),false))), + false); + + *res++ = std::make_pair + (make_object(Circular_arc_2 (A.supporting_circle(), + CircularFunctors::x_extremal_point + (A.supporting_circle(),false), + A.target())), + true); + } + else { + assert( compare(A.source().x(),A.supporting_circle().center().x())< 0); + assert (cmp_end_y != LARGER); + *res++ = std::make_pair + (make_object(Circular_arc_2 (A.supporting_circle(), + A.source(), + CircularFunctors::x_extremal_point + (A.supporting_circle(),true))), + true); + + *res++ = std::make_pair + (make_object(Circular_arc_2 (A.supporting_circle(), + CircularFunctors::x_extremal_point + (A.supporting_circle(),true), + A.target())), + false); + } + } + + return res; + } + +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// + + +// In the same as the advanced_make_x_monotone works, this make_xy_function +// returns extra information, descriptive of the position of the returned +// xy-monotone arcs on the circle: The output iterator refers to pairs, the +// first part of which is the object containing tha arc and the second part +// is another pair containing 2 booleans which equavalently describe whether the +// returned xy-monotone arc is on the upper part and the left side of the circle + +template < typename CK , typename Output_iterator> +Output_iterator +advanced_make_xy_monotone( const typename CK::Circular_arc_2 &a, + Output_iterator res) +{ + + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef std::pair relat_pos; + typedef std::pair< CGAL::Object, bool> Obj_descr_1; + typedef std::pair< CGAL::Object, relat_pos> Obj_descr_2; + typedef std::vector Obj_vector_1; + typedef std::vector Obj_vector_2; + + Obj_vector_1 vec; + Obj_vector_2 vec2; + Obj_descr_2 dscr2; + + advanced_make_x_monotone(a,std::back_inserter(vec)); + + for(unsigned int i=0;i(&vec.at(i).first); + + int cmp_begin_x = CGAL::compare + (tmp_arc->source().x(), tmp_arc->supporting_circle().center().x()); + int cmp_end_x = CGAL::compare + (tmp_arc->target().x(), tmp_arc->supporting_circle().center().x()); + + if(cmp_begin_x!=opposite(cmp_end_x) || cmp_begin_x==CGAL::EQUAL) { + dscr2.first=vec.at(i).first; + dscr2.second.first=vec.at(i).second; + dscr2.second.second= (cmp_begin_x==CGAL::SMALLER || + cmp_end_x==CGAL::SMALLER ) ? + true : false; + *res++=dscr2; // The arc is xy_monotone + } + else{ //We have to split the x_monotone_arc into 2 y_monotone arcs + + Obj_descr_1 tmp=vec.at(i); + Obj_descr_2 tmp1,tmp2; + const Circular_arc_2 *tmp_arc = + CGAL::object_cast(&tmp.first); + + tmp1.first = make_object + (Circular_arc_2(a.supporting_circle(),tmp_arc->source(), + CircularFunctors::y_extremal_point + (a.supporting_circle(),!tmp.second))); + + tmp1.second.first=tmp.second; + tmp1.second.second= (tmp.second)? false : true ; + + tmp2.first = make_object + (Circular_arc_2(a.supporting_circle(), + CircularFunctors::y_extremal_point + (a.supporting_circle(),!tmp.second), + tmp_arc->target())); + + tmp2.second.first=tmp.second; + tmp2.second.second= (tmp.second)? true : false ; + + *res++=tmp1; + *res++=tmp2; + } + + } + + return res; + +} + + template + CGAL::Bbox_2 circular_arc_bbox + ( const typename CK::Kernel_base::Circular_arc_2 & a) + { + typedef typename CK::Root_of_2 Root_of_2; + typedef typename CK::FT FT; + typedef CGAL::Interval_nt::Protector IntervalProtector; + typedef CGAL::Interval_nt Interval; + + if(a.is_x_monotone()) { + // The arc is xy-monotone so we just add the bboxes of the endpoints + if(a.is_y_monotone()) + return a.left().bbox() + a.right().bbox(); + + // Just x-monotone, so we have to find the y-critical point + + bool is_on_upper = a.on_upper_part(); + + Bbox_2 + left_bb = a.left().bbox(), + right_bb = a.right().bbox(); + + IntervalProtector ip; + Interval cy = to_interval(a.center().y()); + Interval r2 = to_interval(a.squared_radius()); + Interval r = CGAL::sqrt(r2); + + double ymin, ymax; + + if(is_on_upper) { + ymin = CGAL::min(left_bb.ymin(),right_bb.ymin()); + ymax = cy.sup() + r.sup(); + } else { + ymin = cy.inf() - r.sup(); + ymax = CGAL::max(left_bb.ymax(),right_bb.ymax()); + } + /* + double ymin = (is_on_upper) ? + CGAL::min(left_bb.ymin(),right_bb.ymin()) : + to_interval + ( CircularFunctors::y_extremal_point(a.supporting_circle(),true).y()).first; + double ymax = (is_on_upper) ? + to_interval + ( CircularFunctors::y_extremal_point(a.supporting_circle(),false).y() ).second : + CGAL::max(left_bb.ymax(),right_bb.ymax()); + */ + return Bbox_2(left_bb.xmin(),ymin,right_bb.xmax(),ymax); + } + + if(a.is_y_monotone()) { + bool is_on_left = a.on_left_part(); + IntervalProtector ip; + Bbox_2 + source_bb = a.source().bbox(), + target_bb = a.target().bbox(); + Interval cx = to_interval(a.center().x()); + Interval r2 = to_interval(a.squared_radius()); + Interval r = CGAL::sqrt(r2); + double xmin, xmax; + if(is_on_left) { + xmax = CGAL::max(source_bb.xmax(), target_bb.xmax()); + xmin = cx.inf() - r.sup(); + } else { + xmax = cx.sup() + r.sup(); + xmin = CGAL::min(source_bb.xmin(), target_bb.xmin()); + } + return Bbox_2(xmin, + CGAL::min(source_bb.ymin(),target_bb.ymin()), + xmax, + CGAL::max(source_bb.ymax(),target_bb.ymax())); + } + + // Else return the bounding box of the circle. + return a.supporting_circle().bbox(); + /* More precise version for non-x-monotone arcs. + double xmin,xmax,ymin,ymax; + + // In this case, we can't avoid doing these heavy comparisons + + Comparison_result cmp_source_x=compare(a.source().x(),a.supporting_circle().center().x()), + cmp_target_x=compare(a.target().x(),a.supporting_circle().center().x()), + cmp_source_y=compare(a.source().y(),a.supporting_circle().center().y()), + cmp_target_y=compare(a.target().y(),a.supporting_circle().center().y()); + + //Since it's not x-monotone, it must include at least one x-critical point + + if(cmp_source_y==cmp_target_y || cmp_source_y==0 || cmp_target_y==0) + { + if(cmp_source_x==cmp_target_x || cmp_source_x==0 || cmp_target_x==0) + return a.supporting_circle().bbox(); + + xmin=to_interval( x_extremal_points(a.supporting_circle(),true).x() ).first; + xmax=to_interval( x_extremal_points(a.supporting_circle(),false).x() ).second; + + if( cmp_source_y==LARGER || cmp_target_y==LARGER) + { + ymin=to_interval( y_extremal_point(a.supporting_circle(),true).y() ).first; + ymax=CGAL::max(to_interval(a.source().y()).second,to_interval(a.target().y()).second); + } + else{ + ymax=to_interval( y_extremal_point(a.supporting_circle(),false).y() ).second; + ymin=CGAL::min(to_interval(a.source().y()).first,to_interval(a.target().y()).first); + } + + return Bbox_2(xmin,ymin,xmax,ymax); + } + + if(cmp_source_y > EQUAL) + { + xmin=to_interval(x_extremal_points(a.supporting_circle(),true).x()).first; + xmax=CGAL::max(to_interval(a.source().x()).second,to_interval(a.target().x()).second); + } + else + { + xmin=CGAL::min(to_interval(a.source().x()).first,to_interval(a.target().x()).first); + xmax=to_interval(x_extremal_points(a.supporting_circle(),false).x()).second; + } + + + if( ( cmp_source_y== LARGER && cmp_source_x>= EQUAL) || + ( cmp_target_y== LARGER && cmp_target_x<= EQUAL) ) + ymax=to_interval(y_extremal_point(a.supporting_circle(),false).y()).second; + else + ymax=CGAL::max(to_interval(a.source().y()).second,to_interval(a.target().y()).second); + + + if( ( cmp_source_y== SMALLER && cmp_source_x<= EQUAL) || + ( cmp_target_y== SMALLER && cmp_target_x>= EQUAL) ) + ymin=to_interval(y_extremal_point(a.supporting_circle(),true).y()).first; + else + ymin=CGAL::min(to_interval(a.source().y()).first,to_interval(a.target().y()).first); + + return Bbox_2(xmin,ymin,xmax,ymax); + */ + } + +} // namespace CircularFunctors +} // namespace CGAL + +#endif // CGAL_CIRCULAR_KERNEL_PREDICATES_ON_CIRCULAR_ARC_2_H diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_line_2.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_line_2.h new file mode 100644 index 00000000000..e5287c0ddba --- /dev/null +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_line_2.h @@ -0,0 +1,110 @@ +// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// 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. +// +// $URL$ +// $Id$ +// +// Author(s) : Monique Teillaud, Sylvain Pion + +// 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) + +#ifndef CGAL_CIRCULAR_KERNEL_FUNCTIONS_ON_LINE_2_H +#define CGAL_CIRCULAR_KERNEL_FUNCTIONS_ON_LINE_2_H + +namespace CGAL { +namespace LinearFunctors { + + template < class CK > + typename CK::Polynomial_1_2 + get_equation( const typename CK::Line_2 & L ) + { + typedef typename CK::RT RT; + + return typename CK::Polynomial_1_2(L.a(),L.b(),L.c()); + } + + template < class CK > + typename CK::Line_2 + construct_line_2 ( const typename CK::Polynomial_1_2 &eq ) + { + return typename CK::Line_2(eq[2],eq[1],eq[0]); + } + + template < class CK > + bool + has_on(const typename CK::Line_2 & l, + const typename CK::Circular_arc_point_2 &p) + { + typedef typename CK::Algebraic_kernel AK; + typedef typename CK::Polynomial_1_2 Polynomial_1_2; + Polynomial_1_2 equation = CGAL::LinearFunctors::get_equation(l); + + return(AK().sign_at_object()(equation,p.coordinates())== ZERO); + } + + template < class CK > + inline bool + non_oriented_equal(const typename CK::Line_2 & a1, + const typename CK::Line_2 & a2) { + if(identical(a1,a2)) return true; + const typename CK::RT &a1c = a1.a(); + const typename CK::RT &b1c = a1.b(); + const typename CK::RT &c1c = a1.c(); + const typename CK::RT &a2c = a2.a(); + const typename CK::RT &b2c = a2.b(); + const typename CK::RT &c2c = a2.c(); + return (a1c*b2c == a2c*b1c) && + (a1c*c2c == a2c*c1c) && + (b1c*c2c == b2c*c1c); + } + + template< class CK, class OutputIterator> + OutputIterator + intersect_2( const typename CK::Line_2 & l, + const typename CK::Circle_2 & c, + OutputIterator res ) + { + typedef typename CK::Algebraic_kernel AK; + typedef typename CK::Polynomial_1_2 Equation_line; + typedef typename CK::Polynomial_for_circles_2_2 Equation_circle; + typedef typename CK::Root_for_circles_2_2 Root_for_circles_2_2; + + Equation_line e1 = CGAL::get_equation(l); + Equation_circle e2 = CGAL::get_equation(c); + + typedef std::vector< std::pair < Root_for_circles_2_2, unsigned > > + solutions_container; + solutions_container solutions; + + AK().solve_object()(e1, e2, std::back_inserter(solutions)); + // to be optimized + + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + + for ( typename solutions_container::iterator it = solutions.begin(); + it != solutions.end(); ++it ) + { + *res++ = make_object + (std::make_pair(Circular_arc_point_2(it->first), it->second )); + } + + return res; + } + +} // namespace LinearFunctors +} // namespace CGAL +#endif // CGAL_CIRCULAR_KERNEL_FUNCTIONS_ON_LINE_2_H diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_line_arc_2.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_line_arc_2.h new file mode 100644 index 00000000000..02c4e912d33 --- /dev/null +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_line_arc_2.h @@ -0,0 +1,518 @@ +// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// 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. +// +// $URL$ +// $Id$ +// +// Author(s) : Monique Teillaud, Sylvain Pion + +// 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) + +#ifndef CGAL_CIRCULAR_KERNEL_PREDICATES_ON_LINE_ARC_2_H +#define CGAL_CIRCULAR_KERNEL_PREDICATES_ON_LINE_ARC_2_H + +#include +#include + +namespace CGAL { +namespace CircularFunctors { + + template < class CK > + bool + point_in_x_range(const typename CK::Line_arc_2 &A, + const typename CK::Circular_arc_point_2 &p) + { + // range includes endpoints here + return ( (CircularFunctors::compare_x(p, A.source()) != CircularFunctors::compare_x(p, A.target())) + || (CircularFunctors::compare_x(p, A.source()) == CGAL::EQUAL) ); + } + + template < class CK > + bool + equal(const typename CK::Line_arc_2 &A1, + const typename CK::Line_arc_2 &A2) + { + if (!LinearFunctors::non_oriented_equal( + A1.supporting_line(),A2.supporting_line())) + return false; + + return ( (equal(A1.source(), A2.source()) && + equal(A1.target(), A2.target())) || + (equal(A1.target(), A2.source()) && + equal(A1.source(), A2.target())) ); + } + + template < class CK > + bool + do_overlap(const typename CK::Line_arc_2 &A1, + const typename CK::Line_arc_2 &A2) + { + if (!LinearFunctors::non_oriented_equal( + A1.supporting_line(),A2.supporting_line())) + return false; + + return CircularFunctors::compare_xy(A1.right(), A2.left()) > 0 + && CircularFunctors::compare_xy(A1.left(), A2.right()) < 0; + } + + + template < class CK > + bool + has_on(const typename CK::Line_arc_2 &a, + const typename CK::Circular_arc_point_2 &p, + const bool has_on_supporting_line = false) + { + if(!has_on_supporting_line) { + if(!CGAL::LinearFunctors::has_on(a.supporting_line(),p)) + return false; + } + + return (CircularFunctors::compare_xy(p, a.source()) != CircularFunctors::compare_xy(p, a.target())); + } + + + template< class CK> + bool + is_vertical(const typename CK::Line_arc_2 &l) + { + return l.supporting_line().is_vertical(); + } + + template< class CK> + bool + is_x_monotone(const typename CK::Line_arc_2 &l) + { + return true; + } + + template< class CK> + bool + is_y_monotone(const typename CK::Line_arc_2 &l) + { + return true; + } + + template < class CK > + Comparison_result + compare_y_at_x(const typename CK::Circular_arc_point_2 &p, + const typename CK::Line_arc_2 &A1) + { + //CGAL_kernel_precondition (CircularFunctors::point_in_x_range(A1, p)); + //vertical case + if (CircularFunctors::is_vertical(A1)) { + if (p.y() <= A1.right().y()) { + if(A1.left().y() <= p.y()) { + return CGAL::EQUAL; + } + return CGAL::SMALLER; + } + return CGAL::LARGER; + } + //general case + typedef typename CK::Polynomial_1_2 Polynomial_1_2; + typedef typename CK::Root_of_2 Root_of_2; + Polynomial_1_2 equation = + CGAL::LinearFunctors::get_equation(A1.supporting_line()); + Root_of_2 y((-p.x()*equation.a() - equation.c())/equation.b()); + if (y == p.y()) + return CGAL::EQUAL; + else if (y < p.y()) + return CGAL::LARGER; + else return CGAL::SMALLER; + } + + template < class CK > + Comparison_result + compare_y_to_right(const typename CK::Line_arc_2 &A1, + const typename CK::Line_arc_2 &A2, + const typename CK::Circular_arc_point_2 &p) + { + if(A1.supporting_line().is_vertical()){ + if(A2.supporting_line().is_vertical()) + return CGAL::EQUAL; + return CGAL::LARGER; + } + if(A2.supporting_line().is_vertical()) + return CGAL::SMALLER; + + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Polynomial_1_2 Polynomial_1_2; + typedef typename CK::Root_of_2 Root_of_2; + + Polynomial_1_2 equation; + if(A1.right().x() < A2.right().x()){ + equation = CGAL::LinearFunctors::get_equation(A2.supporting_line()); + Root_of_2 y((-A1.right().x()*equation.a() - equation.c())/equation.b()); + Root_of_2 A1_right_y = A1.right().y(); + if (y == A1_right_y) + return CGAL::EQUAL; + if (y < A1_right_y) + return CGAL::LARGER; + return CGAL::SMALLER; + } + else{ + equation = CGAL::LinearFunctors::get_equation(A1.supporting_line()); + Root_of_2 y((-A2.right().x()*equation.a() - equation.c())/equation.b()); + Root_of_2 A2_right_y = A2.right().y(); + if (y == A2_right_y) + return CGAL::EQUAL; + if (y < A2_right_y) + return CGAL::SMALLER; + return CGAL::LARGER; + } + + } + + template < class CK > + Comparison_result + compare_y_to_right(const typename CK::Line_arc_2 &A1, + const typename CK::Circular_arc_2 &A2, + const typename CK::Circular_arc_point_2 &p) + { + //CGAL_kernel_precondition (A2.is_x_monotone()); + if(A1.supporting_line().is_vertical()) + return CGAL::LARGER; + + typedef typename CK::Polynomial_1_2 Polynomial_1_2; + typedef typename CK::Root_of_2 Root_of_2; + + const typename CK::Circle_2 & C2 = A2.supporting_circle(); + + Root_of_2 b2_y = C2.center().y() - p.y(); + + int s_b2_y = CGAL::sign(b2_y); + + if (s_b2_y == 0) { + // Vertical tangent for A1. + return A2.on_upper_part() ? CGAL::SMALLER : CGAL::LARGER; + } + + typename CK::Root_of_2 b2_x = C2.center().x() - p.x(); + + Root_of_2 tangent_2_x; + Root_of_2 tangent_2_y; + if (b2_y < 0){ + tangent_2_x = -b2_y; + tangent_2_y = b2_x; + } + else{ + tangent_2_x = b2_y; + tangent_2_y = -b2_x; + } + + Polynomial_1_2 equation = + CGAL::LinearFunctors::get_equation(A1.supporting_line()); + typedef typename CK::FT FT; + FT tangent_1_x; + FT tangent_1_y; + if (equation.b() < 0){ + tangent_1_x = -equation.b(); + tangent_1_y = equation.a(); + } + else{ + tangent_1_x = equation.b(); + tangent_1_y = -equation.a(); + } + + + + if (((tangent_1_x < 0) && (tangent_2_x > 0)) || + ((tangent_1_x > 0) && (tangent_2_x < 0))){ + Root_of_2 prod_left = tangent_1_y * tangent_2_x; + Root_of_2 prod_right = tangent_2_y * tangent_1_x; + if (prod_left < prod_right) + return CGAL::LARGER; + if (prod_left == prod_right) + return A2.on_upper_part() ? CGAL::LARGER : CGAL::SMALLER; + return CGAL::SMALLER; + } + else{ + Root_of_2 prod_left = tangent_1_y * tangent_2_x; + Root_of_2 prod_right = tangent_2_y * tangent_1_x; + if (prod_left < prod_right) + return CGAL::SMALLER; + if (prod_left == prod_right) + return A2.on_upper_part() ? CGAL::LARGER : CGAL::SMALLER; + return CGAL::LARGER; + } + } + + template < class CK > + Comparison_result + compare_y_to_right(const typename CK::Circular_arc_2 &A1, + const typename CK::Line_arc_2 &A2, + const typename CK::Circular_arc_point_2 &p) + { + if (compare_y_to_right(A2, A1, p) == CGAL::LARGER) + return CGAL::SMALLER; + return CGAL::LARGER; + } + + + template < class CK > + void + split(const typename CK::Line_arc_2 &A, + const typename CK::Circular_arc_point_2 &p, + typename CK::Line_arc_2 &ca1, + typename CK::Line_arc_2 &ca2) + { + CGAL_kernel_precondition( has_on(A, p)); + + typedef typename CK::Line_arc_2 Line_arc_2; + + ca1 = Line_arc_2( A.supporting_line(), A.source(), p); + ca2 = Line_arc_2( A.supporting_line(), p, A.target()); + + if ( CircularFunctors::compare_xy(ca1.left(), ca2.left()) != SMALLER ) + { + std::swap(ca1,ca2); + } + + return; + } + + template< class CK, class OutputIterator> + OutputIterator + intersect_2( const typename CK::Line_arc_2 &a1, + const typename CK::Line_arc_2 &a2, + OutputIterator res ) + { + typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; + typedef typename CK::Line_arc_2 Line_arc_2; + typedef typename CK::Point_2 Point_2; + typedef typename CK::Root_of_2 Root_of_2; + typedef typename CK::Root_for_circles_2_2 Root_for_circles_2_2; + + if(LinearFunctors::non_oriented_equal( + a1.supporting_line(),a2.supporting_line())) { + if(compare_xy(a1.left(),a2.left()) < 0) { + int comparison = compare_xy(a2.left(),a1.right()); + if(comparison < 0){ + if(compare_xy(a1.right(),a2.right()) <= 0){ + *res++ = make_object + (Line_arc_2(a1.supporting_line(), a2.left(), a1.right() )); + } + else{ + *res++ = make_object + (Line_arc_2(a1.supporting_line(), a2.left(), a2.right() )); + } + } + else if (comparison == 0){ + *res++ =make_object + ( std::make_pair(a2.left(),1u)); + } + return res; + } + else{ + int comparison = compare_xy(a1.left(),a2.right()); + if(comparison < 0){ + if(compare_xy(a1.right(),a2.right()) <= 0){ + *res++ = make_object + (Line_arc_2(a1.supporting_line(), a1.left(), a1.right() )); + } + else{ + *res++ = make_object + (Line_arc_2(a1.supporting_line(), a1.left(), a2.right() )); + } + } + else if (comparison == 0){ + *res++ = make_object + ( std::make_pair(a1.left(),1u)); + } + return res; + } + } + + Object obj = intersection(a1.supporting_line(), a2.supporting_line()); + const Point_2 *pt = CGAL::object_cast(&obj); + if(pt == NULL) return res; + Circular_arc_point_2 intersect_point = Circular_arc_point_2(*pt); + // (Root_for_circles_2_2(Root_of_2(pt->x()),Root_of_2(pt->y()))); + + if ((CircularFunctors::compare_xy(intersect_point, a1.source()) != + CircularFunctors::compare_xy(intersect_point, a1.target())) && + (CircularFunctors::compare_xy(intersect_point, a2.source()) != + CircularFunctors::compare_xy(intersect_point, a2.target()))) + *res++ = make_object(std::make_pair(intersect_point, 1u)); + + return res; + } + + template< class CK, class OutputIterator> + OutputIterator + intersect_2( const typename CK::Line_arc_2 &l, + const typename CK::Circle_2 &c, + OutputIterator res ) + { + typedef std::vector solutions_container; + solutions_container solutions; + + CGAL::LinearFunctors::intersect_2 + ( l.supporting_line(), c, std::back_inserter(solutions) ); + + for (typename solutions_container::iterator it = solutions.begin(); + it != solutions.end(); ++it) { + const std::pair + *result = CGAL::object_cast + > (&(*it)); + if ( has_on(l,result->first,true)) + *res++ = *it; + } + return res; + } + + /*template< class CK, class OutputIterator> + OutputIterator + intersect_2( const typename CK::Line_arc_2 &l, + const typename CK::Circle_2 &c, + OutputIterator res ) + { + typedef std::vector solutions_container; + solutions_container solutions; + + CGAL::LinearFunctors::intersect_2 + ( l.supporting_line(), c, std::back_inserter(solutions) ); + + for (typename solutions_container::iterator it = solutions.begin(); + it != solutions.end(); ++it) { + const std::pair *result; + result = CGAL::object_cast + > (&(*it)); + if ( has_on(l,result->first)) + *res++ = *it; + } + return res; + }*/ + + template< class CK, class OutputIterator> + OutputIterator + intersect_2( const typename CK::Circle_2 &c, + const typename CK::Line_arc_2 &l, + OutputIterator res ) + { + return intersect_2(l,c,res); + } + + template< class CK, class OutputIterator> + OutputIterator + intersect_2( const typename CK::Line_arc_2 &l, + const typename CK::Circular_arc_2 &c, + OutputIterator res ) + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef typename CK::Line_arc_2 Line_arc_2; + typedef std::vector solutions_container; + + solutions_container solutions; + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + if(!Line_arc_2::template + find_intersection_circle_line< solutions_container > + (c,l,solutions)) { +#endif + + CGAL::LinearFunctors::intersect_2 + ( l.supporting_line(), c.supporting_circle(), + std::back_inserter(solutions) ); + +#ifdef CGAL_INTERSECTION_MAP_FOR_SUPPORTING_CIRCLES + Line_arc_2::template + put_intersection_circle_line< std::vector < CGAL::Object > > + (c,l,solutions); + } +#endif + + + for (typename solutions_container::iterator it = solutions.begin(); + it != solutions.end(); ++it) { + const std::pair + *result = CGAL::object_cast + > (&(*it)); + if (has_on(l,result->first,true) && + has_on(c,result->first,true)) { + *res++ = *it; + } + } + return res; + } + + /*template< class CK, class OutputIterator> + OutputIterator + intersect_2( const typename CK::Line_arc_2 &l, + const typename CK::Circular_arc_2 &c, + OutputIterator res ) + { + typedef typename CK::Circular_arc_2 Circular_arc_2; + typedef std::vector solutions_container; + + solutions_container solutions; + CGAL::LinearFunctors::intersect_2 + ( l.supporting_line(), c.supporting_circle(), + std::back_inserter(solutions) ); + + solutions_container objects_monotone; + std::vector arcs_x_monotone; + make_x_monotone( c, std::back_inserter(objects_monotone)); + for(typename solutions_container::iterator it2 = objects_monotone.begin(); + it2 != objects_monotone.end(); ++it2){ + arcs_x_monotone.push_back(CGAL::object_cast(&(*it2))); + } + + for (typename solutions_container::iterator it = solutions.begin(); + it != solutions.end(); ++it){ + const std::pair *result; + result = CGAL::object_cast + > (&(*it)); + if ( has_on(l,result->first)) { + bool is_on_arc = false; + for(typename std::vector::iterator + it2 = arcs_x_monotone.begin(); + it2 != arcs_x_monotone.end(); ++it2){ + if(has_on(**it2, result->first)){ + is_on_arc = true; + break; + } + } + if(is_on_arc) + *res++ = *it; + } + } + return res; + }*/ + + template< class CK, class OutputIterator> + OutputIterator + intersect_2( const typename CK::Circular_arc_2 &c, + const typename CK::Line_arc_2 &l, + OutputIterator res ) + { + return intersect_2(l,c,res); + } + + template < class CK, class OutputIterator > + OutputIterator + make_x_monotone( const typename CK::Line_arc_2 &A, + OutputIterator res ) + { + *res++ = make_object(A); + return res; + } + +} // namespace CircularFunctors +} // namespace CGAL + +#endif // CGAL_CIRCULAR_KERNEL_PREDICATES_ON_LINE_ARC_2_H diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/intersection_line_2_circle_2_map.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/intersection_line_2_circle_2_map.h new file mode 100644 index 00000000000..bb07a5dac07 --- /dev/null +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/intersection_line_2_circle_2_map.h @@ -0,0 +1,79 @@ +// Copyright (c) 2003-2006 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// 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. +// +// $URL: $ +// $Id: $ +// +// Author(s) : Monique Teillaud, Sylvain Pion, Pedro Machado + +// 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) + +#ifndef INTERSECTION_LINE_2_CIRCLE_2_MAP_H +#define INTERSECTION_LINE_2_CIRCLE_2_MAP_H + +#include +#include +#include + +namespace CGAL { +namespace CGALi { + +class Intersection_line_2_circle_2_map { + +typedef struct inter_map_pair { + int x, y; + inter_map_pair(int xx=0, int yy=0) : x(xx), y(yy) {} + inter_map_pair(const inter_map_pair &i) : x(i.x), y(i.y) {} + bool operator<(const inter_map_pair &i) const { + if(x < i.x) return true; + if(x > i.x) return false; + if(y < i.y) return true; + return false; + } +} inter_map_pair; +typedef std::map< inter_map_pair , CGAL::Object > Table; + +private: + Table intersection_map; + unsigned int id_gen; + +public: + Intersection_line_2_circle_2_map() : id_gen(0) { intersection_map.clear(); } + ~Intersection_line_2_circle_2_map() { intersection_map.clear(); } + + unsigned int get_new_id() { + return ++id_gen; + } + + template < class T > + bool find(int id1, int id2, T& res) const { + Table::const_iterator p = intersection_map.find( + inter_map_pair(id1,id2)); + if(p == intersection_map.end()) return false; + assign(res, p->second); + return true; + } + + template < class T > + void put(const int id1, const int id2, const T& res) { + intersection_map[inter_map_pair(id1,id2)] = CGAL::make_object(res); + } +}; + +} // endof internal cgal namespace +} //endof cgal namespace +#endif // INTERSECTION_LINE_2_CIRCLE_2_MAP_H