mirror of https://github.com/CGAL/cgal
171 lines
5.9 KiB
C++
171 lines
5.9 KiB
C++
// ============================================================================
|
|
//
|
|
// Copyright (c) 2000 The CGAL Consortium
|
|
//
|
|
// This software and related documentation is part of an INTERNAL release
|
|
// of the Computational Geometry Algorithms Library (CGAL). It is not
|
|
// intended for general use.
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
// release : $CGAL_Revision $
|
|
// release_date : $CGAL_Date $
|
|
//
|
|
// file : include/CGAL/Segment_less_yx_2.h
|
|
// package : $CGAL_Package: Partition_2 $
|
|
// maintainer : Susan Hert <hert@mpi-sb.mpg.de>
|
|
// chapter : Planar Polygon Partitioning
|
|
//
|
|
// revision : $Revision$
|
|
// revision_date : $Date$
|
|
//
|
|
// author(s) : Susan Hert <hert@mpi-sb.mpg.de>
|
|
//
|
|
// coordinator : MPI (Susan Hert <hert@mpi-sb.mpg.de>)
|
|
//
|
|
// implementation: Ordering of segments for visibility sweep.
|
|
// ============================================================================
|
|
|
|
#ifndef CGAL_SEGMENT_LESS_YX_2_H
|
|
#define CGAL_SEGMENT_LESS_YX_2_H
|
|
|
|
#include <utility>
|
|
#include <CGAL/Turn_reverser.h>
|
|
|
|
namespace CGAL {
|
|
|
|
//
|
|
// Compares two pairs of points representing two segments. The first is
|
|
// "less than" the second if the second can see some point of the first
|
|
// by looking straight down (i.e., in direction -pi/2). If the first can see
|
|
// the second in this way, it is greater than the second. If neither sees
|
|
// the other when looking in the direction -pi/2, the one that is farther
|
|
// to the left is less than the one farther to the right.
|
|
//
|
|
template <class Traits>
|
|
class Segment_less_yx_2
|
|
{
|
|
typedef typename Traits::Point_2 Point_2;
|
|
typedef std::pair<Point_2, Point_2> Point_pair;
|
|
typedef typename Traits::Less_xy_2 Less_xy_2;
|
|
typedef typename Traits::Compare_x_2 Compare_x_2;
|
|
typedef typename Traits::Compare_y_2 Compare_y_2;
|
|
typedef typename Traits::Left_turn_2 Left_turn_2;
|
|
typedef Turn_reverser<Point_2, Left_turn_2> Right_turn_2;
|
|
|
|
public:
|
|
Segment_less_yx_2() :
|
|
_less_xy_2(Traits().less_xy_2_object()),
|
|
_compare_x_2(Traits().compare_x_2_object()),
|
|
_compare_y_2(Traits().compare_y_2_object()),
|
|
_left_turn_2(Traits().left_turn_2_object()),
|
|
_right_turn_2(Right_turn_2(_left_turn_2))
|
|
{ }
|
|
|
|
|
|
bool
|
|
operator()(const Point_pair& p, const Point_pair& q) const
|
|
{
|
|
Point_2 p_smaller_xy, p_larger_xy;
|
|
Point_2 q_smaller_xy, q_larger_xy;
|
|
// order the point pairs by x value
|
|
if (_less_xy_2(p.first, p.second))
|
|
{
|
|
p_smaller_xy = p.first;
|
|
p_larger_xy = p.second;
|
|
}
|
|
else
|
|
{
|
|
p_smaller_xy = p.second;
|
|
p_larger_xy = p.first;
|
|
}
|
|
if (_less_xy_2(q.first, q.second))
|
|
{
|
|
q_smaller_xy = q.first;
|
|
q_larger_xy = q.second;
|
|
}
|
|
else
|
|
{
|
|
q_smaller_xy = q.second;
|
|
q_larger_xy = q.first;
|
|
}
|
|
|
|
|
|
// x range of p comes before x range of q
|
|
if (_compare_x_2(p_larger_xy, q_smaller_xy) == SMALLER)
|
|
return true;
|
|
else if (_compare_x_2(p_larger_xy, q_smaller_xy) == EQUAL)
|
|
{
|
|
// x range of p ends where x range of q starts
|
|
Comparison_result y_comp = _compare_y_2(p_larger_xy, q_smaller_xy);
|
|
if (y_comp == SMALLER)
|
|
return true;
|
|
else if (y_comp == LARGER)
|
|
return false;
|
|
else // y_comp == EQUAL, so p's x range comes before q's
|
|
return true;
|
|
}
|
|
// x range of q comes before x range of p
|
|
else if (_compare_x_2(q_larger_xy, p_smaller_xy) == SMALLER)
|
|
return false;
|
|
else if (_compare_x_2(q_larger_xy, p_smaller_xy) == EQUAL)
|
|
{
|
|
// x range of p starts where x range of q ends
|
|
Comparison_result y_comp = _compare_y_2(p_smaller_xy, q_larger_xy);
|
|
if (y_comp == SMALLER)
|
|
return true;
|
|
else if (y_comp == LARGER)
|
|
return false;
|
|
else // y_comp == EQUAL, so p's x range comes after q's
|
|
return false;
|
|
}
|
|
// see if one of q's endpoints is contained in p's x range
|
|
else if (_compare_x_2(p_smaller_xy,q_smaller_xy) == SMALLER &&
|
|
_compare_x_2(q_smaller_xy,p_larger_xy) == SMALLER)
|
|
return _left_turn_2(p_smaller_xy,p_larger_xy,q_smaller_xy);
|
|
else if (_compare_x_2(p_smaller_xy,q_larger_xy) == SMALLER &&
|
|
_compare_x_2(q_larger_xy,p_larger_xy) == SMALLER)
|
|
return _left_turn_2(p_smaller_xy,p_larger_xy,q_larger_xy);
|
|
//
|
|
// neither of q's endpoints is in p's x-range so see if one of
|
|
// p's endpoints is in q's x-range
|
|
//
|
|
else if (_compare_x_2(q_smaller_xy,p_smaller_xy) == SMALLER &&
|
|
_compare_x_2(p_smaller_xy,q_larger_xy) == SMALLER)
|
|
return _right_turn_2(q_smaller_xy,q_larger_xy,p_smaller_xy);
|
|
else if (_compare_x_2(q_smaller_xy,p_larger_xy) == SMALLER &&
|
|
_compare_x_2(p_larger_xy,q_larger_xy) == SMALLER )
|
|
return _right_turn_2(q_smaller_xy,q_larger_xy,p_larger_xy);
|
|
else // the x ranges are exactly the same
|
|
{
|
|
Comparison_result y_comp = _compare_y_2(p_smaller_xy, q_smaller_xy);
|
|
if (y_comp == SMALLER)
|
|
return true;
|
|
else if (y_comp == LARGER)
|
|
return false;
|
|
else // look at the other endpoint
|
|
{
|
|
y_comp = _compare_y_2(p_larger_xy, q_larger_xy);
|
|
if (y_comp == SMALLER)
|
|
return true;
|
|
else if (y_comp == LARGER)
|
|
return false;
|
|
else // point pairs are identical
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
Less_xy_2 _less_xy_2;
|
|
Compare_x_2 _compare_x_2;
|
|
Compare_y_2 _compare_y_2;
|
|
Left_turn_2 _left_turn_2;
|
|
Right_turn_2 _right_turn_2;
|
|
};
|
|
|
|
}
|
|
|
|
#endif // CGAL_SEGMENT_LESS_YX_2_H
|
|
|