// Copyright (c) 2005 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_RATIONAL_ARC_TRAITS_2_H #define CGAL_ARR_RATIONAL_ARC_TRAITS_2_H /*! \file * Definition of the Arr_rational_arc_traits_2 class. */ #include #include CGAL_BEGIN_NAMESPACE /*! \class * A traits class for maintaining an arrangement of bounded arcs (segments) of * rational functions of arbitrary degree. * * The class is templated with two parameters: * Alg_kernel A geometric kernel, where Alg_kernel::FT is the number type * for the coordinates of arrangement vertices, which are algebraic * numbers (defined by Nt_traits::Algebraic). * Nt_traits A traits class for performing various operations on the integer, * rational and algebraic types. */ template class Arr_rational_arc_traits_2 { public: typedef Alg_kernel_ Alg_kernel; typedef Nt_traits_ Nt_traits; typedef typename Alg_kernel::FT Algebraic; typedef typename Nt_traits::Integer Integer; // Category tags: typedef Tag_true Has_left_category; typedef Tag_true Has_merge_category; typedef Tag_true Has_infinite_category; // Traits objects: typedef _Rational_arc_2 Curve_2; typedef _Rational_arc_2 X_monotone_curve_2; typedef typename Alg_kernel::Point_2 Point_2; typedef typename Curve_2::Rat_vector Rat_vector; public: /*! * Default constructor. */ Arr_rational_arc_traits_2 () {} /// \name 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 { Alg_kernel ker; return (ker.compare_x_2_object() (p1, p2)); } /*! * Compare the relative positions of a vertical curve and another given * curves at y = +/- oo. * \param p A reference point; we refer to a vertical line incident to p. * \param cv The compared curve. * \param ind MIN_END if we refer to cv's minimal end, * MIN_END if we refer to its maximal end. * \pre cv's relevant end is defined at y = +/- oo. * \return SMALLER if p lies to the left of cv; * LARGER if p lies to the right cv; * EQUAL in case of an overlap. */ Comparison_result operator() (const Point_2& p, const X_monotone_curve_2& cv, Curve_end ind) const { return (cv.compare_end (p, ind)); } /*! * Compare the relative positions of two curves at y = +/- oo. * \param cv1 The first curve. * \param ind1 MIN_END if we refer to cv1's minimal end, * MIN_END if we refer to its maximal end. * \param cv2 The second curve. * \param ind2 MIN_END if we refer to cv2's minimal end, * MIN_END if we refer to its maximal end. * \pre The curves are defined at y = +/- oo. * \return SMALLER if cv1 lies to the left of cv2; * LARGER if cv1 lies to the right cv2; * EQUAL in case of an overlap. */ Comparison_result operator() (const X_monotone_curve_2& cv1, Curve_end ind1, const X_monotone_curve_2& cv2, Curve_end ind2) const { return (cv1.compare_ends (ind1, cv2, ind2)); } }; /*! 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 { Alg_kernel ker; return (ker.compare_xy_2_object() (p1, p2)); } }; /*! Get a Compare_xy_2 functor object. */ Compare_xy_2 compare_xy_2_object () const { return Compare_xy_2(); } class Infinite_in_x_2 { public: /*! * Check if an end of a given x-monotone curve is infinite at x. * \param cv The curve. * \param ind MIN_END if we refer to cv's minimal end, * MIN_END if we refer to its maximal end. * \return MINUS_INFINITY if the curve end lies at x = -oo; * FINITE if the curve end has a finite x-coordinate; * PLUS_INFINITY if the curve end lies at x = +oo. */ Infinity_type operator() (const X_monotone_curve_2& cv, Curve_end ind) const { if (ind == MIN_END) return (cv.left_infinite_in_x()); else return (cv.right_infinite_in_x()); } }; /*! Get an Infinite_in_x_2 functor object. */ Infinite_in_x_2 infinite_in_x_2_object () const { return Infinite_in_x_2(); } class Infinite_in_y_2 { public: /*! * Check if an end of a given x-monotone curve is infinite at y. * \param cv The curve. * \param ind MIN_END if we refer to cv's minimal end, * MIN_END if we refer to its maximal end. * \return MINUS_INFINITY if the curve end lies at y = -oo; * FINITE if the curve end has a finite y-coordinate; * PLUS_INFINITY if the curve end lies at y = +oo. */ Infinity_type operator() (const X_monotone_curve_2& cv, Curve_end ind) const { if (ind == MIN_END) return (cv.left_infinite_in_y()); else return (cv.right_infinite_in_y()); } }; /*! Get an Infinite_in_y_2 functor object. */ Infinite_in_y_2 infinite_in_y_2_object () const { return Infinite_in_y_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 { // A rational function can never be vertical: 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 { return (cv.point_position (p)); } /*! * Compare the relative y-positions of two curves at x = +/- oo. * \param cv1 The first curve. * \param cv2 The second curve. * \param ind MIN_END if we compare at x = -oo; * MAX_END if we compare at x = +oo. * \pre The curves are defined at x = +/- oo. * \return SMALLER if cv1 lies below cv2; * LARGER if cv1 lies above cv2; * EQUAL in case of an overlap. */ Comparison_result operator() (const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2, Curve_end ind) const { if (ind == MIN_END) return (cv1.compare_at_minus_infinity (cv2)); else return (cv1.compare_at_plus_infinity (cv2)); } }; /*! 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_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_code ( Alg_kernel ker; ); CGAL_precondition ((cv1.left_infinite_in_x() != FINITE || cv1.left_infinite_in_y() != FINITE || ker.compare_xy_2_object() (p, cv1.left()) == LARGER) && (cv2.left_infinite_in_x() != FINITE || cv2.left_infinite_in_y() != FINITE || ker.compare_xy_2_object() (p, cv2.left()) == LARGER)); // Compare the slopes of the two arcs. Comparison_result res; unsigned int mult; res = cv1.compare_slopes (cv2, p, mult); // The comparison result is to the right of p. In case the multiplicity // of the intersection point p is odd, reverse this result. if (mult % 2 == 1) { if (res == SMALLER) res = LARGER; else if (res == LARGER) res = SMALLER; } return (res); } }; /*! 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 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 // left (so their left endpoint is lexicographically smaller than p). CGAL_precondition (cv1.point_position (p) == EQUAL && cv2.point_position (p) == EQUAL); CGAL_precondition_code ( Alg_kernel ker; ); CGAL_precondition((cv1.right_infinite_in_x() != FINITE || cv1.right_infinite_in_y() != FINITE || ker.compare_xy_2_object() (p, cv1.right()) == SMALLER) && (cv2.right_infinite_in_x() != FINITE || cv2.right_infinite_in_y() != FINITE || ker.compare_xy_2_object() (p, cv2.right()) == SMALLER)); // Compare the slopes of the two arcs to determine thir relative // position immediately to the right of p. unsigned int mult; return (cv1.compare_slopes (cv2, p, mult)); } }; /*! 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 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 { if (&p1 == &p2) return (true); Alg_kernel ker; return (ker.compare_xy_2_object() (p1, p2) == EQUAL); } }; /*! Get an Equal_2 functor object. */ Equal_2 equal_2_object () const { return Equal_2(); } class Make_x_monotone_2 { public: /*! * 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 is a wrapper for an X_monotone_curve_2 object. * \return The past-the-end iterator. */ template OutputIterator operator() (const Curve_2& cv, OutputIterator oi) { // Make the rational arc continuous. std::list arcs; cv.make_continuous (std::back_inserter (arcs)); // Create objects. typename std::list::const_iterator iter; for (iter = arcs.begin(); iter != arcs.end(); ++iter) { *oi = make_object (*iter); ++oi; } return (oi); } }; /*! Get a Make_x_monotone_2 functor object. */ Make_x_monotone_2 make_x_monotone_2_object () const { 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 { cv.split (p, c1, c2); return; } }; /*! Get a Split_2 functor object. */ Split_2 split_2_object () const { return Split_2(); } class Intersect_2 { public: /*! * 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 () const { return Intersect_2(); } class Are_mergeable_2 { public: /*! * Check whether it is possible to merge two given x-monotone curves. * \param cv1 The first curve. * \param cv2 The second curve. * \return (true) if the two curves are mergeable - if they are supported * by the same line and share a common endpoint; (false) otherwise. */ bool operator() (const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2) const { return (cv1.can_merge_with (cv2)); } }; /*! Get an Are_mergeable_2 functor object. */ Are_mergeable_2 are_mergeable_2_object () const { return Are_mergeable_2(); } class Merge_2 { public: /*! * Merge two given x-monotone curves into a single curve (segment). * \param cv1 The first curve. * \param cv2 The second curve. * \param c Output: The merged curve. * \pre The two curves are mergeable, that is they are supported by the * same conic curve and share a common endpoint. */ void operator() (const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2, X_monotone_curve_2& c) const { c = cv1; c.merge (cv2); return; } }; /*! Get a Merge_2 functor object. */ Merge_2 merge_2_object () const { return Merge_2(); } //@} /// \name Functor definitions for the Boolean set-operation traits. //@{ class Compare_endpoints_xy_2 { public: /*! * Compare the endpoints of an $x$-monotone curve lexicographically. * (assuming the curve has a designated source and target points). * \param cv The curve. * \return SMALLER if the curve is directed right; * LARGER if the curve is directed left. */ Comparison_result operator() (const X_monotone_curve_2& cv) { if (cv.is_directed_right()) return (SMALLER); else return (LARGER); } }; /*! Get a Compare_endpoints_xy_2 functor object. */ Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const { return Compare_endpoints_xy_2(); } class Construct_opposite_2 { public: /*! * Construct an opposite x-monotone (with swapped source and target). * \param cv The curve. * \return The opposite curve. */ X_monotone_curve_2 operator() (const X_monotone_curve_2& cv) { return (cv.flip()); } }; /*! Get a Construct_opposite_2 functor object. */ Construct_opposite_2 construct_opposite_2_object() const { return Construct_opposite_2(); } //@} }; CGAL_END_NAMESPACE #endif