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

360 lines
13 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) : Iddo Hanniel <hanniel@math.tau.ac.il>
// Efi Fogel <efif@post.tau.ac.il>
#ifndef CGAL_ARR_SEGMENT_EXACT_TRAITS_H
#define CGAL_ARR_SEGMENT_EXACT_TRAITS_H
#include <CGAL/Pm_segment_traits_2.h>
#include <CGAL/intersections.h>
#include <list>
CGAL_BEGIN_NAMESPACE
template <class Kernel_>
class Arr_segment_traits_2 : public Pm_segment_traits_2<Kernel_>
{
public:
typedef Kernel_ Kernel;
typedef int Info_face;
typedef int Info_edge;
typedef int Info_vertex;
typedef Pm_segment_traits_2<Kernel> Base;
typedef typename Base::Has_left_category Has_left_category;
typedef typename Base::Point_2 Point_2;
typedef typename Base::X_monotone_curve_2 X_monotone_curve_2;
typedef X_monotone_curve_2 Curve_2;
// Obsolete, for backward compatibility
typedef Point_2 Point;
typedef X_monotone_curve_2 X_curve;
typedef Curve_2 Curve;
protected:
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::Equal_2 Equal_2;
typedef typename Kernel::Orientation_2 Orientation_2;
public:
Arr_segment_traits_2() : Base() { }
/*! is_x_monotone()
* \return true if the given curve is an x-monotone curve. False, otherwise.
* For segments, this is always true
*/
bool is_x_monotone(const Curve_2 &) {return true;}
/*! curve_make_x_monotone() cuts the given curve into x-monotone subcurves
* and inserts them to the given output iterator. The order in which they
* are inserted defines their order in the hierarchy tree.
* While segments are x_monotone, still need to pass them out.
* \param cv the input 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 o) const
{
*o++ = cv;
return o;
}
/*! curve_opposite() flips a given curve
* \param cv the curve
* \return a segment with source and target point interchanged
*/
X_monotone_curve_2 curve_opposite(const X_monotone_curve_2 & cv) const
{
return construct_opposite_segment_2_object()(cv);
}
/*! curve_split() splits 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 split_pt
* \pre split_pt is on cv but is not an endpoint.
*/
void curve_split(const X_monotone_curve_2 & cv,
X_monotone_curve_2 & c1, X_monotone_curve_2 & c2,
const Point_2 & split_pt) const
{
//split curve at split point (x coordinate) into c1 and c2
CGAL_precondition(curve_compare_y_at_x(split_pt, cv) == EQUAL);
CGAL_precondition_code(Equal_2 is_equal = equal_2_object());
CGAL_precondition(!is_equal(curve_source(cv), split_pt));
CGAL_precondition(!is_equal(curve_target(cv), split_pt));
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);
Construct_segment_2 construct_segment = construct_segment_2_object();
c1 = construct_segment(source, split_pt);
c2 = construct_segment(split_pt, target);
}
/*! nearest_intersection_to_right() finds the nearest intersection point of
* two given curves to the right of a given point. Nearest is defined as the
* lexicographically nearest not including the point itself with one
* exception explained bellow..
* 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 right, they are returned through two
* other point references p1 and p2. If pt is between the source and target
* of the overlapping subcurve, or pt is its left endpoint, pt and the target
* of the right endpoint of the subcurve are returned through p1 and p2
* respectively.
* If the intersection of the two curves is a point to the right of pt, pt
* is returned through the p1 and p2.
* \param c1 the first curve
* \param c2 the second curve
* \param pt the point to compare against
* \param p1 the first point reference
* \param p2 the second point reference
* \return true if c1 and c2 do intersect to the right of pt. Otherwise,
* false
*/
bool nearest_intersection_to_right(const X_monotone_curve_2 & c1,
const X_monotone_curve_2 & c2,
const Point_2 & pt,
Point_2 & p1, Point_2 & p2) const
{
Object res = intersect_2_object()(c1, c2);
// Empty object is returned - no intersection.
if (res.is_empty()) return (false);
// Intersection is a point
if (assign(p1,res)) {
// the intersection is a point:
if (compare_xy_2_object()(p1, pt) == LARGER) {
p2 = p1;
return true;
}
return false;
}
// Intersection is a segment
X_monotone_curve_2 seg;
if (assign(seg, res)) {
// the intersection is a curve:
Construct_vertex_2 construct_vertex = construct_vertex_2_object();
const Point_2 & src = construct_vertex(seg, 0);
const Point_2 & trg = construct_vertex(seg, 1);
Compare_xy_2 compare_xy = compare_xy_2_object();
Comparison_result src_pt = compare_xy(src, pt);
Comparison_result trg_pt = compare_xy(trg, pt);
if (src_pt == LARGER && trg_pt == LARGER) {
// the subcurve is completely to the right:
p1 = src;
p2 = trg;
return true;
}
if (trg_pt != LARGER && src_pt == LARGER) {
// target is to the left, source is to the right:
p1 = pt;
p2 = src;
return true;
}
if (src_pt != LARGER && trg_pt == LARGER) {
// source is to the left, target is to the right:
p1 = pt;
p2 = trg;
return true;
}
// the subcurve is completely to the left:
return false;
}
// the curves do not intersect:
return false;
}
/*! nearest_intersection_to_left() finds 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 bellow..
* 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 pt is between the source and target
* of the overlapping subcurve, or pt is its left endpoint, pt and the target
* 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 pt, pt
* is returned through the p1 and p2.
* \param c1 the first curve
* \param c2 the second curve
* \param pt the point to compare against
* \param p1 the first point reference
* \param p2 the second point reference
* \return true if c1 and c2 do intersect to the left of pt. Otherwise,
* false
*/
bool nearest_intersection_to_left(const X_monotone_curve_2 & c1,
const X_monotone_curve_2 & c2,
const Point_2 & pt,
Point_2 & p1, Point_2 & p2) const
{
Object res = intersect_2_object()(c1, c2);
// Empty object is returned - no intersection.
if (res.is_empty()) return (false);
// Intersection is a point
if (assign(p1,res)) {
// the intersection is a point:
if (compare_xy_2_object()(p1, pt) == SMALLER) {
p2 = p1;
return true;
}
return false;
}
// Intersection is a segment
X_monotone_curve_2 seg;
if (assign(seg, res)) {
// the intersection is a curve:
Construct_vertex_2 construct_vertex = construct_vertex_2_object();
const Point_2 & src = construct_vertex(seg, 0);
const Point_2 & trg = construct_vertex(seg, 1);
Compare_xy_2 compare_xy = compare_xy_2_object();
Comparison_result src_pt = compare_xy(src, pt);
Comparison_result trg_pt = compare_xy(trg, pt);
if (src_pt == SMALLER && trg_pt == SMALLER) {
// the subcurve is completely to the left:
p1 = src;
p2 = trg;
return true;
}
if (trg_pt != SMALLER && src_pt == SMALLER) {
// target is to the right, source is to the left:
p1 = pt;
p2 = src;
return true;
}
if (src_pt != SMALLER && trg_pt == SMALLER) {
// source is to the right, target is to the left:
p1 = pt;
p2 = trg;
return true;
}
// the subcurve is completely to the right:
return false;
}
// the curves do not intersect:
return false;
}
/*! curves_overlap() test overlapping between two given curves
* \patam c1 the first curve
* \patam c2 the second curve
* \return true if c1 and c2 overlap in a one-dimensional subcurve
* (i.e., not in a finite number of points). Otherwise, false.
*/
bool curves_overlap(const X_monotone_curve_2 & cv1,
const X_monotone_curve_2 & cv2) const
{
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);
}
};
CGAL_END_NAMESPACE
#endif