This commit is contained in:
Efi Fogel 2003-04-09 18:46:08 +00:00
parent 48cef11276
commit 08165872d2
1 changed files with 297 additions and 21 deletions

View File

@ -23,18 +23,16 @@
// chapter : Arrangement_2
//
// ======================================================================
#ifndef CGAL_ARR_SEGMENT_EXACT_TRAITS_H
#define CGAL_ARR_SEGMENT_EXACT_TRAITS_H
#include <CGAL/Pm_segment_traits_tight_2.h>
#include <CGAL/intersections.h>
#ifndef CGAL_ARR_SEGMENT_TRAITS_TIGHT_H
#define CGAL_ARR_SEGMENT_TRAITS_TIGHT_H
#include <CGAL/tags.h>
#include <list>
CGAL_BEGIN_NAMESPACE
template <class Kernel_>
class Arr_segment_traits_tight_2 : public Pm_segment_traits_tight_2<Kernel_>
class Arr_segment_traits_2
{
public:
typedef Kernel_ Kernel;
@ -42,12 +40,18 @@ public:
typedef int Info_edge;
typedef int Info_vertex;
typedef Pm_segment_traits_tight_2<Kernel> Base;
typedef typename Base::Has_left_category Has_left_category;
// 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_curve_2;
typedef typename Base::Point_2 Point_2;
typedef typename Base::X_curve_2 X_curve_2;
typedef X_curve_2 Curve_2;
// Obsolete, for backward compatibility
@ -56,12 +60,225 @@ public:
typedef Curve_2 Curve;
protected:
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;
typedef typename Kernel::Construct_vertex_2 Construct_vertex_2;
typedef typename Kernel::Construct_segment_2 Construct_segment_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;
typedef typename Kernel::Compare_y_at_x_2 Compare_y_at_x_2;
typedef typename Kernel::Is_vertical_2 Is_vertical_2;
typedef typename Kernel::Orientation_2 Orientation_2;
public:
Arr_segment_traits_tight_2() : Base() { }
Arr_segment_traits_2() {}
* \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
*
* \todo replace indirect use curve_is_vertical() with is_vertical_2()
*/
bool curve_is_vertical(const X_curve_2 & cv) const
{ return is_vertical_2_object()(cv); }
/*! curve_is_in_x_range()
* \param cv the curve
* \param q the point
* \return true if q is in the x range of cv
*
* \todo Intorduce Is_in_x_range_2() or perhaps Is_in_x_closed_range_2()
* in kernel. Currently, this is implemented using existing traits (kernel)
* functions (curve_source(), curve_target()) that return the source and
* target points by value, which is not as efficient as possible.
*/
bool curve_is_in_x_range(const X_curve_2 & cv, const Point_2 & q) const
{
Construct_vertex_2 construct_vertex = construct_vertex_2_object();
const Point_2 & source = construct_vertex(cv, 0);
const Point_2 & target = construct_vertex(cv, 1);
Less_x_2 less_x = less_x_2_object();
return !((less_x(source, q) && less_x(target, q)) ||
(less_x(q, source) && less_x(q, target)));
}
/*! curve_compare_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.
*
* \todo replace indirect use curve_compare_at_x() with compare_y_at_x_2()
*/
Comparison_result curve_compare_at_x(const X_curve_2 & cv1,
const X_curve_2 & cv2,
const Point_2 & q) const
{
CGAL_precondition(curve_is_in_x_range(cv1, q));
CGAL_precondition(curve_is_in_x_range(cv2, q));
return compare_y_at_x_2_object()(q, cv1, cv2);
}
#if !defined(HAS_LEFT_NOT)
/*! curve_compare_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 curve_compare_at_x_left(const X_curve_2 & cv1,
const X_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(
Construct_vertex_2 construct_vertex = construct_vertex_2_object();
Less_x_2 less_x = less_x_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 (less_x(source1, q) || less_x(target1, q));
CGAL_precondition (!(less_x(source1, q) && less_x(target1, q)));
CGAL_precondition (less_x(source2, q) || less_x(target2, q));
CGAL_precondition (!(less_x(source2, q) && less_x(target2, q)));
// Since the curves are continuous, if they are not equal at q, the same
// result also applies to q's left.
CGAL_precondition (compare_y_at_x_2_object()(q, cv1, cv2) == EQUAL);
// <cv2> and <cv1> 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_curve_2 curve_reflect_in_x_and_y(const X_curve_2 & cv) const
{
X_curve_2 reflected_cv(point_reflect_in_x_and_y ( cv.source()),
point_reflect_in_x_and_y ( cv.target()));
return reflected_cv;
}
#endif
/*! curve_compare_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 curve_compare_at_x_right(const X_curve_2 & cv1,
const X_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(
Construct_vertex_2 construct_vertex = construct_vertex_2_object();
Less_x_2 less_x = less_x_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 (less_x(q, source1) || less_x(q, target1));
CGAL_precondition (!(less_x(q, source1) && less_x(q, target1)));
CGAL_precondition (less_x(q, source2) || less_x(q, target2));
CGAL_precondition (!(less_x(q, source2) && less_x(q, target2)));
// Since the curves are continuous, if they are not equal at q, the same
// result also applies to q's left.
CGAL_precondition (curve_compare_at_x(cv1, cv2, q) == EQUAL);
// <cv1> and <cv2> meet at a point with the same x-coordinate as q
// compare their derivatives
return compare_slope_2_object()(cv1, cv2);
}
/*! Return the curve-point status of the input objects.
* \pre p must be in the x-range of cv.
*/
Comparison_result curve_get_point_status (const X_curve_2 & cv,
const Point_2 & p) const
{
CGAL_precondition(curve_is_in_x_range(cv, p));
Comparison_result res = compare_y_at_x_2_object()(p, cv);
if (res == SMALLER)
return (LARGER);
else if (res == LARGER)
return (SMALLER);
return (EQUAL);
}
/*! \todo replace indirect use curve_is_same() with equal_2()
*/
bool curve_is_same(const X_curve_2 & cv1,const X_curve_2 & cv2) const
{
Equal_2 equal = equal_2_object();
const X_curve_2 & ocv1 = construct_opposite_segment_2_object()(cv1);
return equal(cv1, cv2) || equal(ocv1, cv2);
}
/*! \todo replace indirect use point_is_same() with equal_2()
*/
bool point_is_same(const Point_2 & p1, const Point_2 & p2) const
{
return equal_2_object()(p1, p2);
}
/*! \todo replace indirect use curve_source() with construct_vertex_2()
*/
Point_2 curve_source(const X_curve_2 & cv) const
{ return construct_vertex_2_object()(cv, 0); }
/*! \todo replace indirect use curve_target() with construct_vertex_2()
*/
Point_2 curve_target(const X_curve_2 & cv) const
{ return construct_vertex_2_object()(cv, 1); }
///////////////////////////////////////////////////////////////////////////
// Planar map with intersection requirement:
///////////////////////////////////////////////////////////////////////////
/*! is_x_monotone()
* \return true if the given curve is an x-monotone curve. False, otherwise.
@ -106,9 +323,9 @@ public:
CGAL_precondition(compare_xy(curve_target(cv), split_pt) != EQUAL);
Construct_vertex_2 construct_vertex = construct_vertex_2_object();
Construct_segment_2 construct_segment = construct_segment_2_object();
const Point_2 & source = construct_vertex(cv, 0);
const Point_2 & target = construct_vertex(cv, 1);
Construct_segment_2 construct_segment = construct_segment_2_object();
c1 = construct_segment(source, split_pt);
c2 = construct_segment(split_pt, target);
}
@ -139,10 +356,13 @@ public:
const Point_2 & pt,
Point_2 & p1, Point_2 & p2) const
{
Point_2 ip;
X_curve_2 seg;
Object res = intersect_2_object()(c1, c2);
// Empty object is returned - no intersection.
if (res.is_empty()) return (false);
// Intersection is a point
Point_2 ip;
if (assign(p1,res)) {
// the intersection is a point:
if (compare_xy_2_object()(p1, pt) == LARGER) {
@ -151,7 +371,9 @@ public:
}
return false;
}
// Intersection is a segment
X_curve_2 seg;
if (assign(seg, res)) {
// the intersection is a curve:
Construct_vertex_2 construct_vertex = construct_vertex_2_object();
@ -197,11 +419,65 @@ public:
* (i.e., not in a finite number of points). Otherwise, false.
* \todo end point coincidence instead of intersection!
*/
bool curves_overlap(const X_curve_2 & c1, const X_curve_2 & c2) const
bool curves_overlap(const X_curve_2 & cv1, const X_curve_2 & cv2) const
{
Object res = intersect_2_object()(c1, c2);
X_curve_2 seg;
return (assign(seg, res) != 0);
Construct_vertex_2 construct_vertex = construct_vertex_2_object();
const Point_2 & src2 = construct_vertex(cv2, 0);
const Point_2 & trg2 = construct_vertex(cv2, 1);
const Point_2 & src1 = construct_vertex(cv1, 0);
const Point_2 & trg1 = construct_vertex(cv1, 1);
Orientation_2 orient = orientation_2_object();
if ((!orient(src1, trg1, src2) == COLLINEAR) ||
(!orient(src1, trg1, trg2) == COLLINEAR))
return false;
Is_vertical_2 is_vertical = is_vertical_2_object();
if (is_vertical(cv1)) {
if (is_vertical(cv2)) {
Compare_y_2 compare_y = compare_y_2_object();
Comparison_result res_ss = compare_y (src1, src2);
Comparison_result res_st = compare_y (src1, trg2);
if (res_ss == SMALLER) {
if (res_st == LARGER) return true;
if (compare_y (trg1, src2) == LARGER) return true;
return (compare_y (trg1, trg2) == LARGER);
}
if (res_ss == LARGER) {
if (res_st == SMALLER) return true;
if (compare_y (trg1, src2) == SMALLER) return true;
return (compare_y (trg1, trg2) == SMALLER);
}
// res_ss == EQUAL
if (res_st == SMALLER)
return (compare_y (trg1, src2) == LARGER);
return (compare_y (trg1, src2) == SMALLER);
}
return false;
}
if (is_vertical(cv2)) return false;
Compare_x_2 compare_x = compare_x_2_object();
Comparison_result res_ss = compare_x (src1, src2);
Comparison_result res_st = compare_x (src1, trg2);
if (res_ss == SMALLER) {
if (res_st == LARGER) return true;
if (compare_x (trg1, src2) == LARGER) return true;
return (compare_x (trg1, trg2) == LARGER);
}
if (res_ss == LARGER) {
if (res_st == SMALLER) return true;
if (compare_x (trg1, src2) == SMALLER) return true;
return (compare_x (trg1, trg2) == SMALLER);
}
// res_ss == EQUAL
if (res_st == SMALLER)
return (compare_x (trg1, src2) == LARGER);
return (compare_x (trg1, src2) == SMALLER);
}
};