// Copyright (c) 1997 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. // // $Source$ // $Revision$ $Date$ // $Name$ // // Author(s) : Iddo Hanniel // Eyal Flato // Oren Nechushtan // Eti Ezra // Shai Hirsch // Eugene Lipovetsky // Efi Fogel // Ron Wein #ifndef CGAL_PM_SEGMENT_TRAITS_2_H #define CGAL_PM_SEGMENT_TRAITS_2_H #include CGAL_BEGIN_NAMESPACE template class Pm_segment_traits_2 : public Kernel_ { public: typedef Kernel_ Kernel; // Categories: // #define HAS_LEFT_NOT #if !defined(HAS_LEFT_NOT) typedef Tag_true Has_left_category; #else typedef Tag_false Has_left_category; #endif // Traits objects typedef typename Kernel::Point_2 Point_2; typedef typename Kernel::Segment_2 X_monotone_curve_2; // Backward compatability typedef Point_2 Point; typedef X_monotone_curve_2 X_curve; protected: // Functors: typedef typename Kernel::Compare_x_2 Compare_x_2; typedef typename Kernel::Compare_xy_2 Compare_xy_2; typedef typename Kernel::Is_vertical_2 Is_vertical_2; typedef typename Kernel::Construct_vertex_2 Construct_vertex_2; typedef typename Kernel::Less_x_2 Less_x_2; typedef typename Kernel::Equal_2 Equal_2; public: // Creation Pm_segment_traits_2() {} // Operations // ---------- /*! compare_x() compares the x-coordinates of two given points * \param p1 the first point * \param p2 the second point * \return LARGER if x(p1) > x(p2); SMALLER if x(p1) < x(p2); or else EQUAL */ Comparison_result compare_x(const Point_2 & p1, const Point_2 & p2) const { return compare_x_2_object()(p1, p2); } /*! compare_xy() compares lexigoraphically the two points 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); * or else EQUAL */ Comparison_result compare_xy(const Point_2 & p1, const Point_2 & p2) const { return compare_xy_2_object()(p1, p2); } /*! curve_is_vertical() * \param cv the curve * \return true iff the curve is vertical */ bool curve_is_vertical(const X_monotone_curve_2 & cv) const { return is_vertical_2_object()(cv); } /*! point_in_x_range() * \param cv the curve * \param q the point * \return true if q is in the x range of cv */ bool point_in_x_range(const X_monotone_curve_2 & cv, const Point_2 & q) const { #if 1 Compare_x_2 compare_x = compare_x_2_object(); Construct_vertex_2 construct_vertex = construct_vertex_2_object(); Comparison_result res1 = compare_x(construct_vertex(cv, 0), q); Comparison_result res2 = compare_x(construct_vertex(cv, 1), q); // We check if x(p) equals the x value of one of the end-points. // If not, we check whether one end-point is to p's left and the other is // to its right. return ((res1 == EQUAL) || (res2 == EQUAL) || (res1 != res2)); #else // \todo use this code instead, after the calls it uses are supported // in the LEDA kernel. Compare_x_2 compare_x = compare_x_2_object(); Comparison_result res1 = compare_x(cv, 0, q); Comparison_result res2 = compare_x(cv, 1, q); // We check if x(p) equals the x value of one of the end-points. // If not, we check whether one end-point is to p's left and the other is // to its right. return ((res1 == EQUAL) || (res2 == EQUAL) || (res1 != res2)); #endif } /*! curves_compare_y_at_x() compares the y-coordinate of two given curves at * the x-coordinate of a given point. * \param cv1 the first curve * \param cv2 the second curve * \param q the point * \return LARGER if cv1(x(q)) > cv2(x(q)); SMALLER if cv1(x(q)) < cv2(x(q)); * or else EQUAL. * \pre The point q is in the x range of the two curves. */ Comparison_result curves_compare_y_at_x(const X_monotone_curve_2 & cv1, const X_monotone_curve_2 & cv2, const Point_2 & q) const { CGAL_precondition(point_in_x_range(cv1, q)); CGAL_precondition(point_in_x_range(cv2, q)); return compare_y_at_x_2_object()(q, cv1, cv2); } #if !defined(HAS_LEFT_NOT) /*! curves_compare_y_at_x_left() compares the y value of two curves in an * epsilon environment to the left of the x value of the input point * Preconditions: The point q is in the x range of the two curves, and both * of them must be also be defined to its left. The two curves must also * intersect at x(q). */ Comparison_result curves_compare_y_at_x_left(const X_monotone_curve_2 & cv1, const X_monotone_curve_2 & cv2, const Point_2 & q) const { // The two curve must be defined at q and also to its left. CGAL_precondition_code( Construct_vertex_2 construct_vertex = construct_vertex_2_object(); Compare_xy_2 cmp_xy = compare_xy_2_object(); const Point_2 & source1 = construct_vertex(cv1, 0); const Point_2 & target1 = construct_vertex(cv1, 1); const Point_2 & source2 = construct_vertex(cv2, 0); const Point_2 & target2 = construct_vertex(cv2, 1); const Is_vertical_2 is_vertical = is_vertical_2_object(); ); CGAL_precondition((cmp_xy(source1, q) == SMALLER) || (cmp_xy(target1, q) == SMALLER)); CGAL_precondition((cmp_xy(source1, q) != SMALLER) || (cmp_xy(target1, q) != SMALLER)); CGAL_precondition((cmp_xy(source2, q) == SMALLER) || (cmp_xy(target2, q) == SMALLER)); CGAL_precondition((cmp_xy(source2, q) != SMALLER) || (cmp_xy(target2, q) != SMALLER)); // Since the curves are continuous, if they are not equal at q, the same // result also applies to q's left. CGAL_precondition((is_vertical(cv1) && has_on_2_object()(cv1, q)) || (is_vertical(cv2) && has_on_2_object()(cv2, q)) || (compare_y_at_x_2_object()(q, cv1, cv2) == EQUAL)); // and meet at a point with the same x-coordinate as q // compare their derivatives. return compare_slope_2_object()(cv2, cv1); } #else /*! point_reflect_in_x_and_y() reflects the given point about the origin */ Point_2 point_reflect_in_x_and_y(const Point_2 & pt) const { Point_2 org = construct_point_2_object()(ORIGIN); typename Kernel::Vector_2 v = construct_vector_2_object()(pt, org); Point_2 reflected_pt(v); return reflected_pt; } /*! curve_reflect_in_x_and_y reflects the given curve about the origin */ X_monotone_curve_2 curve_reflect_in_x_and_y(const X_monotone_curve_2 & cv) const { X_monotone_curve_2 reflected_cv(point_reflect_in_x_and_y(cv.source()), point_reflect_in_x_and_y(cv.target())); return reflected_cv; } #endif /*! curves_compare_y_at_x_right() compares the y value of two curves in an * epsilon environment to the right of the x value of the input point * Preconditions: The point q is in the x range of the two curves, and both * of them must be also be defined to its right. The two curves must also * intersect at x(q). */ Comparison_result curves_compare_y_at_x_right(const X_monotone_curve_2 & cv1, const X_monotone_curve_2 & cv2, const Point_2 & q) const { // The two curve must be defined at q and also to its right. CGAL_precondition_code( Construct_vertex_2 construct_vertex = construct_vertex_2_object(); Compare_xy_2 cmp_xy = compare_xy_2_object(); const Point_2 & source1 = construct_vertex(cv1, 0); const Point_2 & target1 = construct_vertex(cv1, 1); const Point_2 & source2 = construct_vertex(cv2, 0); const Point_2 & target2 = construct_vertex(cv2, 1); ); CGAL_precondition((cmp_xy(q, source1) == SMALLER)|| (cmp_xy(q, target1) == SMALLER)); CGAL_precondition((cmp_xy(q, source1) != SMALLER) | (cmp_xy(q, target1) != SMALLER)); CGAL_precondition((cmp_xy(q, source2) == SMALLER) || (cmp_xy(q, target2) == SMALLER)); CGAL_precondition((cmp_xy(q, source2) != SMALLER) || (cmp_xy(q, target2) != SMALLER)); // Since the curves are continuous, if they are not equal at q, the same // result also applies to q's left. CGAL_precondition((is_vertical_2_object()(cv1) && has_on_2_object()(cv1, q)) || (is_vertical_2_object()(cv2) && has_on_2_object()(cv2, q)) || (compare_y_at_x_2_object()(q, cv1, cv2) == EQUAL)); // and meet at a point with the same x-coordinate as q // compare their derivatives return compare_slope_2_object()(cv1, cv2); } /*! 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)), that is the point is below the curve; * LARGER if y(p) > cv(x(p)), that is the point is above the curve; * or else (if p is on the curve) EQUAL. */ Comparison_result curve_compare_y_at_x (const Point_2 & p, const X_monotone_curve_2 & cv) const { CGAL_precondition(point_in_x_range(cv, p)); return compare_y_at_x_2_object()(p, cv); } /*! Check if the two 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. */ bool curve_equal(const X_monotone_curve_2 & cv1, const X_monotone_curve_2 & cv2) const { Equal_2 equal = equal_2_object(); const X_monotone_curve_2 & ocv1 = construct_opposite_segment_2_object()(cv1); return equal(cv1, cv2) || equal(ocv1, cv2); } /*! Check if the two points are the same. * \param p1 The first point. * \param p2 The second point. * \return (true) if p1 == p2. */ bool point_equal(const Point_2 & p1, const Point_2 & p2) const { return equal_2_object()(p1, p2); } /*! Get the curve source. * \param cv The curve. * \return The source point. */ Point_2 curve_source(const X_monotone_curve_2 & cv) const { return construct_vertex_2_object()(cv, 0); } /*! Get the curve target. * \param cv The curve. * \return The target point. */ Point_2 curve_target(const X_monotone_curve_2 & cv) const { return construct_vertex_2_object()(cv, 1); } }; CGAL_END_NAMESPACE #endif