diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Hyperbolic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Hyperbolic_arc_2.h new file mode 100644 index 00000000000..836b891f56b --- /dev/null +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Hyperbolic_arc_2.h @@ -0,0 +1,409 @@ +// Copyright (c) 2006 Tel-Aviv University (Israel). +// 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) : Ron Wein + +#ifndef CGAL_HYPERBOLIC_ARC_2_H +#define CGAL_HYPERBOLIC_ARC_2_H + +/*! \file + * Header file for the _Hyperbolic_arc_2 class. + */ +#include +#include +#include +#include +#include +#include +#include + +CGAL_BEGIN_NAMESPACE + +/*! \class + * Representation of an x-monotone hyprbolic arc, defined by: + * y = a*x^2 + b*x + c, for x <= x_min < = x_max. + * Note that a, b and c are rational numbers, while x_min and x_max + * may be one-root numbers. + */ +template +class _Hyperbolic_arc_2 +{ +public: + + typedef Kernel_ Kernel; + typedef _Hyperbolic_arc_2 Self; + typedef typename Kernel::FT NT; + typedef _One_root_point_2 Point_2; + typedef typename Point_2::CoordNT CoordNT; + +protected: + + NT _a; // The coefficient of x^2. + NT _b; // The coefficient of x. + NT _c; // The free coefficient. + + Point_2 _source; // The source point. + Point_2 _target; // The target point. + +public: + + /*! + * Default constructor. + */ + _Hyperbolic_arc_2 () : + _a(), _b(), _c(), + _source(), _target() + {} + + /*! + * Construct an arc. + * \param a, b, c The coefficients of the supporting hyperbola. + * \param x_min, x_max Define the x-range of the hyperbolic arc. + */ + _Hyperbolic_arc_2 (const NT& a, const NT& b, const NT& c, + const CoordNT& x_min, const CoordNT& x_max) : + _a (a), + _b (b), + _c (c) + { + CGAL_precondition (CGAL::compare (x_min, x_max) == CGAL::SMALLER); + + // Compute the endpoints. + _source = Point_2 (x_min, _get_y (x_min)); + _target = Point_2 (x_max, _get_y (x_max)); + } + + /*! + * Construct a segment arc from two kernel points + * \param source the source point. + * \ param target the target point. + * \pre The source is lexicographically smaller than the target. + */ + _Hyperbolic_arc_2 (const typename Kernel::Point_2& source, + const typename Kernel::Point_2& target) : + _source(source.x(), source.y()), + _target(target.x(), target.y()) + { + CGAL_precondition (CGAL::compare(source.x(), target.x()) == CGAL::SMALLER); + + // Set the coefficients of the supporting curve + typename Kernel::Line_2 line(source, target); + _a = 0; + _b = - line.a() / line.b(); + _c = - line.c() / line.b(); + } + + /*! Check if the arc is linear. */ + inline bool is_linear () const + { + return (CGAL::sign(_a) == CGAL::ZERO); + } + + /*! Check if the arc is hyperbolic. */ + inline bool is_hyperbolic () const + { + return (CGAL::sign(_a) != CGAL::ZERO); + } + + /*! + * Get the coefficients of the supporting curve. + */ + const NT& a () const + { + return (_a); + } + + const NT& b () const + { + return (_b); + } + + const NT& c () const + { + return (_c); + } + + /*! Get the source point. */ + inline const Point_2& source () const + { + return (_source); + } + + /*! Get the target point. */ + inline const Point_2& target () const + { + return (_target); + } + + /*! Get the left endpoint of the arc. */ + inline const Point_2& left () const + { + return (_source); + } + + /*! Get the right endpoint of the arc. */ + inline const Point_2& right () const + { + return (_target); + } + + /*! + * Check whether the given point is in the x-range of the arc. + */ + bool is_in_x_range (const Point_2& p) const + { + Comparison_result res = CGAL::compare (p.x(), left().x()); + + if (res == SMALLER) + return (false); + else if (res == EQUAL) + return (true); + + return (CGAL::compare (p.x(), right().x()) != LARGER); + } + + /*! + * Check the position of a given point with respect to the arc. + */ + Comparison_result point_position (const Point_2& p) const + { + return (CGAL::compare (p.y(), _get_y (p.x()))); + } + + /*! + * Compare the two arcs to the right of their intersection point. + */ + Comparison_result compare_to_right (const Self& cv, const Point_2& p) const + { + // Compute the first-order derivatives of both curves at p. + const CoordNT der1 = p.x() * 2 * _a + _b; + const CoordNT der2 = p.x() * 2 * cv._a + cv._b; + Comparison_result res = CGAL::compare (der1, der2); + + // In case of inequality, return the comparison reult. + if (res != CGAL::EQUAL) + return (res); + + // In case of equality, compare the second-order derivatives. + return (CGAL::compare (_a, cv._a)); + } + + /*! + * Compare the two arcs to the left of their intersecton point. + */ + Comparison_result compare_to_left (const Self& cv, const Point_2& p) const + { + // Compute the first-order derivatives of both curves at p. + const CoordNT der1 = p.x() * 2 * _a + _b; + const CoordNT der2 = p.x() * 2 * cv._a + cv._b; + Comparison_result res = CGAL::compare (der1, der2); + + // In case of inequality, negate the comparison reult. + if (res != CGAL::EQUAL) + return (CGAL::opposite (res)); + + // In case of equality, compare the second-order derivatives. + return (CGAL::compare (_a, cv._a)); + } + + /*! + * Check whether the two arcs have the same supporting curve. + */ + bool has_same_supporting_curve (const Self& cv) const + { + return (CGAL::compare (_a, cv._a) == CGAL::EQUAL && + CGAL::compare (_b, cv._b) == CGAL::EQUAL && + CGAL::compare (_c, cv._c) == CGAL::EQUAL); + } + + /*! + * Check if the two curves are equal. + */ + bool equals (const Self& cv) const + { + if (! this->has_same_supporting_curve (cv)) + return (false); + + return (left().equals (cv.left()) && right().equals (cv.right())); + } + + /*! + * Split the curve at a given point into two sub-arcs. + */ + void split (const Point_2& p, Self& c1, Self& c2) const + { + // Copy the properties of this arc to the sub-arcs. + c1 = *this; + c2 = *this; + + // Change the endpoints, such that c1 lies to the right of c2: + c1._target = p; + c2._source = p; + + return; + } + + /*! + * Compute the intersections between the two arcs or segments. + */ + template + OutputIterator intersect (const Self& cv, OutputIterator oi) const + { + // Solve the quadratic equation A*x^2 + B*x + C = 0 in order to find + // the x-coordinates of the intersection points, where: + const NT A = _a - cv._a; + const NT B = _b - cv._b; + const NT C = _c - cv._c; + Point_2 p; + unsigned int mult; + + // Check if we have a linear equation. + if (CGAL::sign (A) == CGAL::ZERO) + { + if (CGAL::sign (B) == ZERO) + { + if (CGAL::sign (C) == ZERO) + { + // Here we have to handle overlaps! + //CGAL_assertion (false); + } + + return (oi); + } + + // We have a single (rational) intersection point. + const NT x = -C / B; + const NT y = (x * _a + _b) * x + _c; + + p = Point_2 (CoordNT(x), CoordNT(y)); + mult = 1; + + *oi = CGAL::make_object (std::make_pair (p, mult)); + ++oi; + + return (oi); + } + + // In this case we have to solve a quadratic equation. + const NT disc = B*B - 4*A*C; + CGAL::Sign sign_disc = CGAL::sign (disc); + + if (sign_disc == CGAL::NEGATIVE) + // No intersection: + return (oi); + + const NT _1_over_2A = 1 / (2*A); + + if (sign_disc == CGAL::ZERO) + { + // We have a single tangency point with rational coordinates. + const NT x = -B * _1_over_2A; + const NT y = (x * _a + _b) * x + _c; + + p = Point_2 (CoordNT(x), CoordNT(y)); + mult = 2; + + *oi = CGAL::make_object (std::make_pair (p, mult)); + ++oi; + + return (oi); + } + + // In this case we have two solutions, given by: + CoordNT xs[2]; + int k; + + if (CGAL::sign (A) == CGAL::POSITIVE) + { + xs[0] = CoordNT (-B * _1_over_2A, - _1_over_2A, disc); + xs[1] = CoordNT (-B * _1_over_2A, _1_over_2A, disc); + } + else + { + xs[0] = CoordNT (-B * _1_over_2A, _1_over_2A, disc); + xs[1] = CoordNT (-B * _1_over_2A, - _1_over_2A, disc); + } + + for (k = 0; k < 2; k++) + { + // Check if the x-coordinate is in the x-range of both arcs. + if ((CGAL::compare (xs[k], left().x()) != SMALLER && + CGAL::compare (xs[k], right().x()) != LARGER) && + (CGAL::compare (xs[k], cv.left().x()) != SMALLER && + CGAL::compare (xs[k], cv.right().x()) != LARGER)) + { + p = Point_2 (xs[k], _get_y (xs[k])); + mult = 1; + + *oi = CGAL::make_object (std::make_pair (p, mult)); + ++oi; + } + } + + return (oi); + } + + Bbox_2 bbox() const + { + double x_min = CGAL::to_double (left().x()); + double x_max = CGAL::to_double (right().x()); + double y_min = CGAL::to_double (left().y()); + double y_max = CGAL::to_double (right().y()); + + if(y_min > y_max) + std::swap(y_min, y_max); + + return Bbox_2(x_min, y_min, x_max, y_max); + } + +private: + + /*! + * Compute the y-coordiate at a given x-coordinate. + */ + CoordNT _get_y (const CoordNT& x) const + { + if (x.is_rational()) + return ((_a * x.alpha() + _b) * x.alpha() + _c); + + const CoordNT z1 = _a * CGAL::square(x); + const CoordNT z2 = _b * x; + + return (CoordNT (z1.alpha() + z2.alpha() + _c, + z1.beta() + z2.beta(), + z1.gamma())); + } +}; + +/*! + * Exporter for circular arcs (or line segments). + */ +template +std::ostream& +operator<< (std::ostream& os, + const _Hyperbolic_arc_2 & arc) +{ + if (! arc.is_linear()) + os << "(" << arc.a() << "*x^2 + " << arc.b() << "*x + " << arc.c() << ") "; + + os << "[" << arc.source() << " --> " << arc.target() << "]" << std::endl; + return (os); +} + +CGAL_END_NAMESPACE + +#endif diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_hyperbolic_arc_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_hyperbolic_arc_traits_2.h new file mode 100644 index 00000000000..6800eac2fec --- /dev/null +++ b/Arrangement_on_surface_2/include/CGAL/Arr_hyperbolic_arc_traits_2.h @@ -0,0 +1,408 @@ +// Copyright (c) 2006 Tel-Aviv University (Israel). +// 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) : Ron Wein + +#ifndef CGAL_ARR_HYPERBOLIC_ARC_TRAITS_2_H +#define CGAL_ARR_HYPERBOLIC_ARC_TRAITS_2_H + +/*! \file + * The header file for the Arr_hyperbolic_arc_traits_2 class. + */ + +#include +#include + +#include + +CGAL_BEGIN_NAMESPACE + +/*! \class + * A traits class for maintaining an arrangement of circles. + */ +template +class Arr_hyperbolic_arc_traits_2 +{ +public: + + typedef Kernel_ Kernel; + typedef typename Kernel::FT NT; + typedef _One_root_point_2 Point_2; + typedef typename Point_2::CoordNT CoordNT; + typedef _Hyperbolic_arc_2 Curve_2; + typedef Curve_2 X_monotone_curve_2; + typedef Arr_hyperbolic_arc_traits_2 Self; + + // Category tags: + typedef Tag_true Has_left_category; + typedef Tag_false Has_merge_category; + typedef Tag_false Has_boundary_category; + +public: + + /*! Default constructor. */ + Arr_hyperbolic_arc_traits_2 () + {} + + /// \name Basic functor definitions. + //@{ + + class Compare_x_2 + { + public: + /*! + * Compare the x-coordinates of two points. + * \param p1 The first point. + * \param p2 The second point. + * \return LARGER if x(p1) > x(p2); + * SMALLER if x(p1) < x(p2); + * EQUAL if x(p1) = x(p2). + */ + Comparison_result operator() (const Point_2& p1, const Point_2& p2) const + { + if (p1.identical (p2)) + return (EQUAL); + + return (CGAL::compare (p1.x(), p2.x())); + } + }; + + /*! Get a Compare_x_2 functor object. */ + Compare_x_2 compare_x_2_object () const + { + return Compare_x_2(); + } + + class Compare_xy_2 + { + public: + /*! + * Compares two points lexigoraphically: by x, then by y. + * \param p1 The first point. + * \param p2 The second point. + * \return LARGER if x(p1) > x(p2), or if x(p1) = x(p2) and y(p1) > y(p2); + * SMALLER if x(p1) < x(p2), or if x(p1) = x(p2) and y(p1) < y(p2); + * EQUAL if the two points are equal. + */ + Comparison_result operator() (const Point_2& p1, const Point_2& p2) const + { + if (p1.identical (p2)) + return (EQUAL); + + Comparison_result res = CGAL::compare (p1.x(), p2.x()); + + if (res != EQUAL) + return (res); + + return (CGAL::compare (p1.y(), p2.y())); + } + }; + + /*! Get a Compare_xy_2 functor object. */ + Compare_xy_2 compare_xy_2_object () const + { + return Compare_xy_2(); + } + + class Construct_min_vertex_2 + { + public: + /*! + * Get the left endpoint of the x-monotone curve (segment). + * \param cv The curve. + * \return The left endpoint. + */ + const Point_2& operator() (const X_monotone_curve_2 & cv) const + { + return (cv.left()); + } + }; + + /*! Get a Construct_min_vertex_2 functor object. */ + Construct_min_vertex_2 construct_min_vertex_2_object () const + { + return Construct_min_vertex_2(); + } + + class Construct_max_vertex_2 + { + public: + /*! + * Get the right endpoint of the x-monotone curve (segment). + * \param cv The curve. + * \return The right endpoint. + */ + const Point_2& operator() (const X_monotone_curve_2 & cv) const + { + return (cv.right()); + } + }; + + /*! Get a Construct_max_vertex_2 functor object. */ + Construct_max_vertex_2 construct_max_vertex_2_object () const + { + return Construct_max_vertex_2(); + } + + class Is_vertical_2 + { + public: + /*! + * Check whether the given x-monotone curve is a vertical segment. + * \param cv The curve. + * \return (true) if the curve is a vertical segment; (false) otherwise. + */ + bool operator() (const X_monotone_curve_2& cv) const + { + // No vertical segments are supported. + return (false); + } + }; + + /*! Get an Is_vertical_2 functor object. */ + Is_vertical_2 is_vertical_2_object () const + { + return Is_vertical_2(); + } + + class Compare_y_at_x_2 + { + public: + /*! + * Return the location of the given point with respect to the input curve. + * \param cv The curve. + * \param p The point. + * \pre p is in the x-range of cv. + * \return SMALLER if y(p) < cv(x(p)), i.e. the point is below the curve; + * LARGER if y(p) > cv(x(p)), i.e. the point is above the curve; + * EQUAL if p lies on the curve. + */ + Comparison_result operator() (const Point_2& p, + const X_monotone_curve_2& cv) const + { + CGAL_precondition (cv.is_in_x_range (p)); + + return (cv.point_position (p)); + } + }; + + /*! Get a Compare_y_at_x_2 functor object. */ + Compare_y_at_x_2 compare_y_at_x_2_object () const + { + return Compare_y_at_x_2(); + } + + class Compare_y_at_x_right_2 + { + public: + /*! + * Compares the y value of two x-monotone curves immediately to the right + * of their intersection point. + * \param cv1 The first curve. + * \param cv2 The second curve. + * \param p The intersection point. + * \pre The point p lies on both curves, and both of them must be also be + * defined (lexicographically) to its right. + * \return The relative position of cv1 with respect to cv2 immdiately to + * the right of p: SMALLER, LARGER or EQUAL. + */ + Comparison_result operator() (const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + const Point_2& p) const + { + // Make sure that p lies on both curves, and that both are defined to its + // right (so their right endpoint is lexicographically larger than p). + CGAL_precondition (cv1.point_position (p) == EQUAL && + cv2.point_position (p) == EQUAL); + + CGAL_precondition (CGAL::compare (p.x(), cv1.right().x()) != LARGER && + CGAL::compare (p.x(), cv2.right().x()) != LARGER); + + // Compare the two curves immediately to the right of p: + return (cv1.compare_to_right (cv2, p)); + } + }; + + /*! Get a Compare_y_at_x_right_2 functor object. */ + Compare_y_at_x_right_2 compare_y_at_x_right_2_object () const + { + return Compare_y_at_x_right_2(); + } + + class Compare_y_at_x_left_2 + { + public: + /*! + * Compares the y value of two x-monotone curves immediately to the left + * of their intersection point. + * \param cv1 The first curve. + * \param cv2 The second curve. + * \param p The intersection point. + * \pre The point p lies on both curves, and both of them must be also be + * defined (lexicographically) to its left. + * \return The relative position of cv1 with respect to cv2 immdiately to + * the left of p: SMALLER, LARGER or EQUAL. + */ + Comparison_result operator() (const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + const Point_2& p) const + { + // Make sure that p lies on both curves, and that both are defined to its + // left (so their left endpoint is lexicographically smaller than p). + CGAL_precondition (cv1.point_position (p) == EQUAL && + cv2.point_position (p) == EQUAL); + + CGAL_precondition (CGAL::compare (p.x(), cv1.left().x()) != SMALLER && + CGAL::compare (p.x(), cv2.left().x()) != SMALLER); + + // Compare the two curves immediately to the left of p: + return (cv1.compare_to_left (cv2, p)); + } + }; + + /*! Get a Compare_y_at_x_left_2 functor object. */ + Compare_y_at_x_left_2 compare_y_at_x_left_2_object () const + { + return Compare_y_at_x_left_2(); + } + + class Equal_2 + { + public: + /*! + * Check if the two x-monotone curves are the same (have the same graph). + * \param cv1 The first curve. + * \param cv2 The second curve. + * \return (true) if the two curves are the same; (false) otherwise. + */ + bool operator() (const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2) const + { + if (&cv1 == &cv2) + return (true); + + return (cv1.equals (cv2)); + } + + /*! + * Check if the two points are the same. + * \param p1 The first point. + * \param p2 The second point. + * \return (true) if the two point are the same; (false) otherwise. + */ + bool operator() (const Point_2& p1, const Point_2& p2) const + { + return (p1.equals (p2)); + } + }; + + /*! Get an Equal_2 functor object. */ + Equal_2 equal_2_object () const + { + return Equal_2(); + } + //@} + + /// \name Functor definitions for supporting intersections. + //@{ + struct Make_x_monotone_2 + { + + /*! + * Cut the given conic curve (or conic arc) into x-monotone subcurves + * and insert them to the given output iterator. + * \param cv The curve. + * \param oi The output iterator, whose value-type is Object. The returned + * objects are all wrappers X_monotone_curve_2 objects. + * \return The past-the-end iterator. + */ + template + OutputIterator operator() (const Curve_2& cv, OutputIterator oi) + { + // In our case every curve is x-monotone: + *oi = CGAL::make_object (cv); + ++oi; + return (oi); + } + }; + + /*! Get a Make_x_monotone_2 functor object. */ + Make_x_monotone_2 make_x_monotone_2_object () + { + return Make_x_monotone_2(); + } + + class Split_2 + { + public: + + /*! + * Split a given x-monotone curve at a given point into two sub-curves. + * \param cv The curve to split + * \param p The split point. + * \param c1 Output: The left resulting subcurve (p is its right endpoint). + * \param c2 Output: The right resulting subcurve (p is its left endpoint). + * \pre p lies on cv but is not one of its end-points. + */ + void operator() (const X_monotone_curve_2& cv, const Point_2& p, + X_monotone_curve_2& c1, X_monotone_curve_2& c2) const + { + CGAL_precondition (cv.is_in_x_range (p) && + ! p.equals (cv.source()) && ! p.equals (cv.target())); + + cv.split (p, c1, c2); + return; + } + }; + + /*! Get a Split_2 functor object. */ + Split_2 split_2_object () + { + return Split_2(); + } + + struct Intersect_2 + { + /*! + * Find the intersections of the two given curves and insert them to the + * given output iterator. As two segments may itersect only once, only a + * single will be contained in the iterator. + * \param cv1 The first curve. + * \param cv2 The second curve. + * \param oi The output iterator. + * \return The past-the-end iterator. + */ + template + OutputIterator operator() (const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + OutputIterator oi) + { + return (cv1.intersect (cv2, oi)); + } + }; + + /*! Get an Intersect_2 functor object. */ + Intersect_2 intersect_2_object () + { + return Intersect_2(); + } + +}; + +CGAL_END_NAMESPACE + +#endif