cgal/Packages/Arrangement/include/CGAL/Arr_hyper_segment_traits_2.h

466 lines
15 KiB
C++

// 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) : Ron Wein <wein@post.tau.ac.il>
#ifndef CGAL_ARR_HYPER_SEGMENT_TRAITS_2_H
#define CGAL_ARR_HYPER_SEGMENT_TRAITS_2_H
#include <CGAL/tags.h>
#include <CGAL/Arrangement_2/Hyper_segment_2.h>
CGAL_BEGIN_NAMESPACE
/*!
* A traits class for maintaining an arrangement of x-monotone segments of
* canonical hyperbolas.
*/
template <class Kernel_>
class Arr_hyper_segment_traits_2 : public Kernel_
{
public:
typedef Kernel_ Kernel;
typedef Tag_true Has_left_category;
// Traits objects:
typedef typename Kernel::Point_2 Point_2;
typedef Hyper_segment_2<Kernel> X_monotone_curve_2;
typedef Hyper_segment_2<Kernel> Curve_2;
// For backward compatability:
typedef Point_2 Point;
typedef X_monotone_curve_2 X_curve;
typedef X_monotone_curve_2 Curve;
protected:
// Functors:
typedef typename Kernel::Less_x_2 Less_x_2;
typedef typename Kernel::Equal_2 Equal_2;
typedef typename Kernel::Compare_x_2 Compare_x_2;
typedef typename Kernel::Compare_y_2 Compare_y_2;
typedef typename Kernel::Compare_xy_2 Compare_xy_2;
public:
/*!
* Default constructor.
*/
Arr_hyper_segment_traits_2() {}
/*!
* Compare 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));
}
/*!
* Compares lexigoraphically the two points: by x, then by y.
* \param p1 Te 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));
}
/*!
* Check whether the given curve is a vertical segment.
* \param cv The curve.
* \return (true) if the curve is vertical.
*/
bool curve_is_vertical(const X_monotone_curve_2 & cv) const
{
// Currently no vertical segments are allowed:
return (false);
}
/*!
* Check whether the given point is in the x-range of the given curve.
* In out case, the curve is a segment [s, t], check whether x(s)<=x(q)<=x(t)
* or whether x(t)<=x(q)<=x(s).
* \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
{
return (cv.point_is_in_x_range(q));
}
/*!
* Get the relative status of two curves at the x-coordinate of a given
* point.
* \param cv1 The first curve.
* \param cv2 The second curve.
* \param q The point.
* \pre The point q is in the x-range of the two curves.
* \return LARGER if cv1(x(q)) > cv2(x(q)); SMALLER if cv1(x(q)) < cv2(x(q));
* or else EQUAL.
*/
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 (cv1.compare_y_at_x (cv2, q));
}
/*!
* Compares the y value of two curves in an epsilon environment to the left
* of the x-value of their intersection point.
* \param cv1 The first curve.
* \param cv2 The second curve.
* \param q The point.
* \pre The point q is in the x range of the two curves, and both of them
* must be also be defined to its left. Furthermore, cv1(x(q) == cv2(x(q)).
* \return The relative position of cv1 with respect to cv2 to the left of
* x(q): LARGER, SMALLER or EQUAL.
*/
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 curves must not be vertical.
CGAL_precondition(! curve_is_vertical(cv1));
CGAL_precondition(! curve_is_vertical(cv2));
// The two curve must be defined at q and also to its left.
CGAL_precondition_code(Less_x_2 less_x = less_x_2_object(););
CGAL_precondition (point_in_x_range(cv1, q));
CGAL_precondition (less_x(cv1.source(), q) || less_x(cv1.target(), q));
CGAL_precondition (point_in_x_range(cv2, q));
CGAL_precondition (less_x(cv2.source(), q) || less_x(cv2.target(), q));
// Notice q is a placeholder for the x coordinate of the two curves.
// That is, if we compare them at x(q) the result should be EQUAL.
CGAL_precondition(cv1.compare_y_at_x (cv2, q) == EQUAL);
// Compare the slopes of the two segments to determine thir relative
// position immediately to the left of q.
// Notice we use the supporting lines in order to compare the slopes.
return (cv2.compare_slopes (cv1, q));
}
/*!
* Compares the y value of two curves in an epsilon environment to the right
* of the x-value of their intersection point.
* \param cv1 The first curve.
* \param cv2 The second curve.
* \param q The point.
* \pre The point q is in the x range of the two curves, and both of them
* must be also be defined to its right. Furthermore, cv1(x(q) == cv2(x(q)).
* \return The relative position of cv1 with respect to cv2 to the right of
* x(q): LARGER, SMALLER or EQUAL.
*/
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 curves must not be vertical.
CGAL_precondition(! curve_is_vertical(cv1));
CGAL_precondition(! curve_is_vertical(cv2));
// The two curve must be defined at q and also to its right.
CGAL_precondition_code(Less_x_2 less_x = less_x_2_object(););
CGAL_precondition (point_in_x_range(cv1, q));
CGAL_precondition (less_x(q, cv1.source()) || less_x(q, cv1.target()));
CGAL_precondition (point_in_x_range(cv2, q));
CGAL_precondition (less_x(q, cv2.source()) || less_x(q, cv2.target()));
// Notice q is a placeholder for the x coordinate of the two curves.
// That is, if we compare them at x(q) the result should be EQUAL.
CGAL_precondition(cv1.compare_y_at_x (cv2, q) == EQUAL);
// Compare the slopes of the two segments to determine thir relative
// position immediately to the left of q.
// Notice we use the supporting lines in order to compare the slopes.
return (cv1.compare_slopes (cv2, q));
}
/*!
* 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 (cv.point_position(p));
}
/*!
* 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
{
return (cv1.is_equal (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.
*/
const Point_2& curve_source(const X_monotone_curve_2 & cv) const
{
return (cv.source());
}
/*!
* Get the curve target.
* \param cv The curve.
* \return The target point.
*/
const Point_2& curve_target(const X_monotone_curve_2 & cv) const
{
return (cv.target());
}
/*!
* Check whether the curve is x-monotone.
* \param cv The curves.
* \return (true) if the curve is x-monotone. In case of segments, the
* function always returns (true), since all segments are x-monotone.
* Vertical segments are also considered as 'weakly' x-monotone.
*/
bool is_x_monotone(const Curve_2 &) const
{
// Return true, since a hyper-segment is always x-monotone.
return (true);
}
/*!
* Cut the given curve into x-monotone subcurves and insert them to the
* given output iterator. While segments are x_monotone, still need to pass
* them out.
* \param cv The curve.
* \param o The output iterator
* \return The past-the-end iterator
*/
template<class OutputIterator>
OutputIterator curve_make_x_monotone (const Curve_2& cv,
OutputIterator oi) const
{
*oi++ = cv;
return (oi);
}
/*!
* Flip a given curve.
* \param cv The input curve.
* \return The flipped curve. In case of segments, if the input is [s,t],
* then the flipped curve is simply [t,s].
*/
X_monotone_curve_2 curve_opposite (const X_monotone_curve_2 & cv) const
{
return (cv.flip());
}
/*!
* Split a given curve at a given split point into two sub-curves.
* \param cv the curve to split
* \param c1 the output first part of the split curve. Its source is the
* source of the original curve.
* \param c2 the output second part of the split curve. Its target is the
* target of the original curve.
* \param p the split point.
* \pre p lies on cv but is not one of its end-points.
*/
void curve_split(const X_monotone_curve_2& cv,
X_monotone_curve_2& c1, X_monotone_curve_2& c2,
const Point_2& p) const
{
cv.split (p, c1, c2);
return;
}
/*!
* Find the nearest intersection point (or points) of two given curves to
* the right lexicographically of a given point not includin the point
* itself, (with one exception explained below).
* If the intersection of the two curves is an X_monotone_curve_2, that is,
* they overlap at infinitely many points, then if the right endpoint and the
* left endpoint of the overlapping subcurve are strickly to the right of
* the given point, they are returned through the two other point
* references respectively. If the given point is between the
* overlapping-subcurve endpoints, or the point is its left endpoint,
* the point and the right endpoint of the subcurve are returned through
* the point references respectively. If the intersection of the two curves
* is a point to the right of the given point, it is returned through the
* point references.
* \param cv1 The first curve.
* \param cv2 The second curve.
* \param p The refernece point.
* \param p1 The first output point.
* \param p2 The second output point.
* \return (true) if c1 and c2 do intersect to the right of p, or (false)
* if no such intersection exists.
*/
bool nearest_intersection_to_right(const X_monotone_curve_2 & cv1,
const X_monotone_curve_2 & cv2,
const Point_2 & p,
Point_2 & p1, Point_2 & p2) const
{
int n_pts = cv1.intersect(cv2, p1, p2);
if (n_pts == 0)
{
return (false);
}
else if (n_pts == 1)
{
// Check if the intersection is to p's right.
if (compare_xy_2_object()(p1, p) == LARGER)
{
p2 = p1;
return (true);
}
else
return (false);
}
else // In case of an overlap.
{
// Notice that p1 < p2.
if (compare_xy_2_object()(p1, p) == LARGER)
{
return (true);
}
else if (compare_xy_2_object()(p2, p) == LARGER)
{
p1 = p;
return (true);
}
return (false);
}
}
/*!
* Find the nearest intersection point of two given curves to the left of
* a given point. Nearest is defined as the lexicographically nearest not
* including the point itself (with one exception explained below).
* If the intersection of the two curves is an X_monotone_curve_2, that is,
* there is an overlapping subcurve, then if the the source and target of the
* subcurve are strickly to the left, they are returned through two
* other point references p1 and p2. If p is between the source and target
* of the overlapping subcurve, or p is its right endpoint, p and the source
* of the left endpoint of the subcurve are returned through p1 and p2
* respectively.
* If the intersection of the two curves is a point to the left of p, it is
* returned through the p1 and p2.
* \param cv1 The first curve.
* \param cv2 The second curve.
* \param p The refernece point.
* \param p1 The first output point.
* \param p2 The second output point.
* \return (true) if c1 and c2 do intersect to the left of p, or (false)
* if no such intersection exists.
*/
bool nearest_intersection_to_left(const X_monotone_curve_2 & cv1,
const X_monotone_curve_2 & cv2,
const Point_2 & p,
Point_2 & p1, Point_2 & p2) const
{
int n_pts = cv1.intersect(cv2, p1, p2);
if (n_pts == 0)
{
return (false);
}
else if (n_pts == 1)
{
// Check if the intersection is to p's left.
if (compare_xy_2_object()(p1, p) == SMALLER)
{
p2 = p1;
return (true);
}
return (false);
}
else // In case of an overlap.
{
// Notice that p1 < p2.
if (compare_xy_2_object()(p2, p) == SMALLER)
{
return (true);
}
else if (compare_xy_2_object()(p1, p) == SMALLER)
{
p2 = p;
return (true);
}
return (false);
}
}
/*!
* Check whether the two given curves overlap.
* \patam cv1 The first curve.
* \patam cv2 The second curve.
* \return (true) if the two curves overlap in a one-dimensional subcurve
* (i.e., not in a finite number of points). Otherwise, if they have a finite
* number of intersection points, or none at all, return (false).
*/
bool curves_overlap(const X_monotone_curve_2 & cv1,
const X_monotone_curve_2 & cv2) const
{
Point_2 p1, p2;
return (cv1.intersect(cv2, p1, p2) == 2);
}
};
CGAL_END_NAMESPACE
#endif