cgal/include/CGAL/Side_of_bounded_square_2.h

268 lines
9.4 KiB
C++

//ON_UNBOUNDED_SIDE = -1,
//ON_BOUNDARY = 0,
//ON_BOUNDED_SIDE = 1
#ifndef CGAL_SIDE_OF_BOUNDED_SQUARE_2_H
#define CGAL_SIDE_OF_BOUNDED_SQUARE_2_H
#include <CGAL/basic.h>
#include <CGAL/enum.h>
#include <CGAL/Orientation_Linf_2.h>
namespace CGAL {
template<class K>
class Side_of_bounded_square_2
{
private:
typedef typename K::Point_2 Point_2;
typedef Orientation_Linf_2<K> Orientation_Linf_2_Type;
typedef typename K::Compare_x_2 Compare_x_2;
typedef typename K::Compare_y_2 Compare_y_2;
typedef typename K::FT FT;
typedef typename K::Comparison_result Comparison_result;
Compare_x_2 compare_x_2;
Compare_y_2 compare_y_2;
Orientation_Linf_2_Type orientation_Linf;
Bounded_side predicate(const Point_2 &p, const Point_2 &q,
const Point_2 &r, const Point_2 &t) const
{
CGAL_SDG_DEBUG(std::cout << "debug Side_of_bounded_square_2 entering"
<< std::endl;);
CGAL_SDG_DEBUG(std::cout << "debug Side_of_bs (pqrt)= (" << p << ") ("
<< q << ") (" << r << ") (" << t << ")" << std::endl;);
Point_2 px_min, px_max, py_min, py_max;
//should be added as CGAL precondition
if (orientation_Linf(p,q,r) == DEGENERATE) {
CGAL_SDG_DEBUG(std::cout << "debug: error: p,q,r are monotone!" << std::endl;);
exit(0);
}
Comparison_result cmpxpq = compare_x_2(p, q);
Comparison_result cmpypq = compare_y_2(p, q);
Comparison_result cmpxpr = compare_x_2(p, r);
Comparison_result cmpypr = compare_y_2(p, r);
Comparison_result cmpxqr = compare_x_2(q, r);
Comparison_result cmpyqr = compare_y_2(q, r);
//compute the minimum x and maximum x
if ( (cmpxpq == LARGER or cmpxpq == EQUAL)
and (cmpxpr == LARGER or cmpxpr == EQUAL) ){
px_max = p;
px_min = (cmpxqr == LARGER or cmpxqr == EQUAL) ? r : q;
}
else if ((cmpxpq == SMALLER or cmpxpq == EQUAL)
and (cmpxqr == LARGER or cmpxqr == EQUAL) ){
px_max = q;
px_min = (cmpxpr == LARGER or cmpxpr == EQUAL) ? r : p;
}
else {
px_max = r;
px_min = (cmpxpq == LARGER or cmpxpq == EQUAL) ? q : p;
}
//compute the minimum y and maximum y
if ((cmpypq == LARGER or cmpypq == EQUAL)
and (cmpypr == LARGER or cmpypr == EQUAL) ){
py_max = p;
py_min = (cmpyqr == LARGER or cmpyqr == EQUAL) ? r : q;
}
else if ((cmpypq == SMALLER or cmpypq == EQUAL)
and (cmpyqr == LARGER or cmpyqr == EQUAL) ){
py_max = q;
py_min = (cmpypr == LARGER or cmpypr == EQUAL) ? r : p;
}
else {
py_max = r;
py_min = (cmpypq == LARGER or cmpypq == EQUAL) ? q : p;
}
// check if two points have the same x or y coordinate
bool exist_two_with_same_x;
bool exist_two_with_same_y;
Point_2 s1, s2, dx, dy;
// check if two points have the same x coordinate
if (cmpxpq == EQUAL) {
exist_two_with_same_x = true;
s1 = p;
s2 = q;
dx = r;
}
else if (cmpxpr == EQUAL) {
exist_two_with_same_x = true;
s1 = p;
s2 = r;
dx = q;
}
else if (cmpxqr == EQUAL) {
exist_two_with_same_x = true;
s1 = q;
s2 = r;
dx = p;
}
else {
exist_two_with_same_x = false;
}
if (exist_two_with_same_x) {
CGAL_SDG_DEBUG(std::cout << "debug Side_of_bs two same x" << std::endl;);
if ( ( ( compare_y_2(dx, s1) == SMALLER ) and
( compare_y_2(dx, s2) == SMALLER ) ) or
( ( compare_y_2(dx, s1) == LARGER ) and
( compare_y_2(dx, s2) == LARGER ) ) ) {
Point_2 dxmirror (dx.x(), s1.y()+s2.y()-dx.y());
if (compare_y_2(dxmirror, py_min) == SMALLER) {
py_min = dxmirror;
}
if (compare_y_2(dxmirror, py_max) == LARGER) {
py_max = dxmirror;
}
}
}
// check if two points have the same y coordinate
if (cmpypq == EQUAL) {
exist_two_with_same_y = true;
s1 = p;
s2 = q;
dy = r;
}
else if (cmpypr == EQUAL) {
exist_two_with_same_y = true;
s1 = p;
s2 = r;
dy = q;
}
else if (cmpyqr == EQUAL) {
exist_two_with_same_y = true;
s1 = q;
s2 = r;
dy = p;
}
else {
exist_two_with_same_y = false;
}
if (exist_two_with_same_y) {
CGAL_SDG_DEBUG(std::cout << "debug Side_of_bs two same y" << std::endl;);
if ( ( ( compare_x_2(dy, s1) == SMALLER ) and
( compare_x_2(dy, s2) == SMALLER ) ) or
( ( compare_x_2(dy, s1) == LARGER ) and
( compare_x_2(dy, s2) == LARGER ) ) ) {
Point_2 dymirror (s1.x()+s2.x()-dy.x(), dy.y());
if (compare_x_2(dymirror, px_min) == SMALLER) {
px_min = dymirror;
}
if (compare_x_2(dymirror, px_max) == LARGER) {
px_max = dymirror;
}
}
}
Point_2 pmin, pmax;
//pmin and pmax define the bounded square by p,q,r
if (px_max.x() - px_min.x() == py_max.y() - py_min.y())
{ //diff x == diff y forms a square
pmin = Point_2(px_min.x(), py_min.y());
pmax = Point_2(px_max.x(), py_max.y());
}
else if (px_max.x() - px_min.x() > py_max.y() - py_min.y())
{ //diff x > diff y forms a rectangle
//need to find the movable side of rectangle
if (compare_x_2(px_min,py_max)==SMALLER &&
compare_x_2(py_max,px_max)==SMALLER ) {
//move the lower side
pmin = Point_2(px_min.x(),py_max.y() - px_max.x() + px_min.x());
pmax = Point_2(px_max.x(),py_max.y());
}
else if (compare_x_2(px_min,py_min)==SMALLER &&
compare_x_2(py_min,px_max)==SMALLER ){
//move the upper side
pmin = Point_2(px_min.x(),py_min.y());
pmax = Point_2(px_max.x(),py_min.y() + px_max.x() - px_min.x());
}
else {
//move both sides
CGAL_SDG_DEBUG(std::cout << "debug Side_of_bs move both sides" << std::endl;);
pmin = Point_2(
px_min.x(),
(py_max.y() + py_min.y() - px_max.x() + px_min.x())*FT(0.5));
pmax = Point_2(
px_max.x(),
(py_max.y() + py_min.y() + px_max.x() - px_min.x())*FT(0.5));
}
}
else
{//px_max.x() - px_min.x() < py_max.y() - py_min.y())
// diff x < diff y forms a rectangle
//need to find the movable side of rectangle
if (compare_y_2(px_min,py_min)==LARGER &&
compare_y_2(px_min,py_max)==SMALLER ) {
//move the right side
pmin = Point_2(px_min.x(),py_min.y());
pmax = Point_2(px_min.x() + py_max.y() - py_min.y(),py_max.y());
}
else if (compare_y_2(px_max,py_min)==LARGER &&
compare_y_2(px_max,py_max)==SMALLER ){
//move the left side
pmin = Point_2(px_max.x() - py_max.y() + py_min.y(),py_min.y());
pmax = Point_2(px_max.x(),py_max.y());
}
else {
//move both sides
CGAL_SDG_DEBUG(std::cout << "debug Side_of_bs move both sides" << std::endl;);
pmin = Point_2(
(px_min.x() + px_max.x() - py_max.y() + py_min.y())*FT(0.5),
py_min.y() );
pmax = Point_2(
(px_min.x() + px_max.x() + py_max.y() - py_min.y())*FT(0.5),
py_max.y() );
}
}
CGAL_SDG_DEBUG(std::cout << "debug Side_of_bs pmin=" << pmin
<< " pmax=" << pmax << " t=" << t << std::endl;);
//Now we answer the predicate bounded side of square
if( compare_x_2(pmin, t) == SMALLER &&
compare_x_2(t, pmax) == SMALLER &&
compare_y_2(pmin, t) == SMALLER &&
compare_y_2(t, pmax) == SMALLER ) {
CGAL_SDG_DEBUG(std::cout << "debug Side_of_bs return ON_BOUNDED_SIDE" << std::endl;);
return ON_BOUNDED_SIDE;
}
else if (compare_x_2(pmin, t) == LARGER ||
compare_x_2(t, pmax) == LARGER ||
compare_y_2(pmin, t) == LARGER ||
compare_y_2(t, pmax) == LARGER ) {
CGAL_SDG_DEBUG(std::cout << "debug Side_of_bs return ON_UNBOUNDED_SIDE" << std::endl;);
return ON_UNBOUNDED_SIDE;
}
else {
CGAL_SDG_DEBUG(std::cout << "debug Side_of_bs return ON_BOUNDARY" << std::endl;);
return ON_BOUNDARY;
}
}
public:
Bounded_side operator()(const Point_2 &p, const Point_2 &q,
const Point_2 &r, const Point_2 &t) const
{
return predicate(p, q, r, t);
}
};
} //namespace CGAL
#endif // CGAL_SIDE_OF_BOUNDED_SQUARE_2_H