cgal/Packages/Trapezoidal_decomposition/include/CGAL/Td_X_trapezoid.h

651 lines
24 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) : Oren Nechushtan <theoren@math.tau.ac.il>
#ifndef CGAL_TD_X_TRAPEZOID_H
#define CGAL_TD_X_TRAPEZOID_H
/* ------------------------------------------------------------------------
class CGAL::TD_X_trapezoid.
parameters Td_traits, implementation of a trapezoid traits.
inherited from CGAL::Handle.
description Implements a trapezoid as two curves(top,bottom)
and two points(left,right).
------------------------------------------------------------------------ */
#include <CGAL/Trapezoidal_decomposition_2.h>
CGAL_BEGIN_NAMESPACE
template < class Td_traits_>
class Td_X_trapezoid : public Handle
{
public:
typedef Td_traits_ Traits;
typedef typename Traits::Point Point;
typedef typename Traits::X_curve X_curve;
typedef typename Traits::X_curve_ptr curve_pointer;
typedef typename Traits::X_curve_ref curve_ref;
typedef typename Traits::X_curve_const_ref curve_const_ref;
typedef typename Traits::X_trapezoid X_trapezoid;
typedef typename Traits::X_trapezoid_ptr pointer;
typedef typename Traits::X_trapezoid_ref reference;
typedef typename Traits::X_trapezoid_const_ref const_ref;
typedef Td_ninetuple<Point,Point,X_curve,X_curve,unsigned char,
pointer,pointer,pointer,pointer> Boundary_type;
typedef Trapezoidal_decomposition_2<Traits> TD;
typedef typename TD::Unbounded Unbounded;
typedef typename TD::Around_point_circulator
Around_point_circulator;
typedef typename TD::In_face_iterator In_face_iterator;
friend class Trapezoidal_decomposition_2<Traits>;
#ifdef CGAL_PM_FRIEND_CLASS
#if defined(__SUNPRO_CC)
friend class Trapezoidal_decomposition_2<Traits>::Around_point_circulator;
friend class Trapezoidal_decomposition_2<Traits>::In_face_iterator;
#elif defined(__GNUC__)
#if ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ <= 2)))
friend typename Trapezoidal_decomposition_2<Traits>::Around_point_circulator;
friend typename Trapezoidal_decomposition_2<Traits>::In_face_iterator;
#else
friend class Trapezoidal_decomposition_2<Traits>::Around_point_circulator;
friend class Trapezoidal_decomposition_2<Traits>::In_face_iterator;
#endif
#else
friend class Around_point_circulator;
friend class In_face_iterator;
#endif
#endif
typedef typename TD::Data_structure Data_structure;
// implementation for trapezoids with two sides parallel to y axis
/* X_trapezoid abbriviates Planar trapezoid with vertical parallel
left and right sides.
Trapezoids are represented as two points called right and left and
two curves called top and bottom. The points lie on the right and left
boundaries of the trapezoid respectively and the curves bound the
trapezoid
from above and below.
There are degenerate trapezoids called infinite trapezoid; this happens
when one of the four sides degenerates into a point/X_curve at infinity.
Trapezoids are created as active and become inactive when Remove() member
function called.
Each X_trapezoid has at most four neighbouring trapezoids.
*/
private:
Boundary_type* ptr() const {return (Boundary_type*)(PTR);}
#ifndef CGAL_TD_DEBUG
#ifdef CGAL_PM_FRIEND_CLASS
protected:
#else
public: // workaround
#endif
#else //CGAL_TD_DEBUG
public:
#endif //CGAL_TD_DEBUG
Data_structure* node;
void init_neighbours(pointer lb_=0,pointer lt_=0,pointer rb_=0,pointer rt_=0)
{set_lb(lb_);set_lt(lt_);set_rb(rb_);set_rt(rt_);}
void set_node(Data_structure* p) {node=p;
#ifdef CGAL_TD_DEBUG
CGAL_assertion(!p || **p==*this);
#endif
}
void set_left(const Point& p)
{ptr()->e0=p;ptr()->e4&=~CGAL_TRAPEZOIDAL_DECOMPOSITION_2_LEFT_UNBOUNDED;}
void set_right(const Point& p)
{ptr()->e1=p;ptr()->e4&=~CGAL_TRAPEZOIDAL_DECOMPOSITION_2_RIGHT_UNBOUNDED;}
void set_bottom(const X_curve& cv)
{ptr()->e2=cv;ptr()->e4&=~CGAL_TRAPEZOIDAL_DECOMPOSITION_2_BOTTOM_UNBOUNDED;}
void set_top(const X_curve& cv)
{ptr()->e3=cv;ptr()->e4&=~CGAL_TRAPEZOIDAL_DECOMPOSITION_2_TOP_UNBOUNDED;}
void set_left_unbounded()
{ptr()->e4|=CGAL_TRAPEZOIDAL_DECOMPOSITION_2_LEFT_UNBOUNDED;}
void set_right_unbounded()
{ptr()->e4|=CGAL_TRAPEZOIDAL_DECOMPOSITION_2_RIGHT_UNBOUNDED;}
void set_bottom_unbounded()
{ptr()->e4|=CGAL_TRAPEZOIDAL_DECOMPOSITION_2_BOTTOM_UNBOUNDED;}
void set_top_unbounded()
{ptr()->e4|=CGAL_TRAPEZOIDAL_DECOMPOSITION_2_TOP_UNBOUNDED;}
void set_lb(X_trapezoid* lb) {ptr()->e5=lb;}
void set_lt(X_trapezoid* lt) {ptr()->e6=lt;}
void set_rb(X_trapezoid* rb) {ptr()->e7=rb;}
void set_rt(X_trapezoid* rt) {ptr()->e8=rt;}
public:
Td_X_trapezoid(void)
{
PTR = new Boundary_type(Traits::get_point_at_left_top_infinity(),
Traits::get_point_at_right_bottom_infinity(),
Traits::get_curve_at_infinity(),
Traits::get_curve_at_infinity(),
CGAL_TRAPEZOIDAL_DECOMPOSITION_2_TOTALLY_UNBOUNDED,
0, 0, 0, 0);
node = 0;
}
Td_X_trapezoid(const Point &l, const Point &r,
const X_curve &b, const X_curve &t,
unsigned char c = CGAL_TRAPEZOIDAL_DECOMPOSITION_2_BOUNDED,
X_trapezoid *lb = 0, X_trapezoid *lt = 0,
X_trapezoid *rb = 0, X_trapezoid *rt = 0,
Data_structure *p = 0)
{
PTR = new Boundary_type(l, r, b, t, c, lb, lt, rb, rt);
node = p;
}
Td_X_trapezoid(const Point *l, const Point *r ,
const X_curve *b, const X_curve *t,
X_trapezoid *lb = 0, X_trapezoid *lt = 0,
X_trapezoid *rb = 0, X_trapezoid *rt = 0,
Data_structure *p = 0)
{
PTR = new Boundary_type
(l ? *l : Traits::get_point_at_left_top_infinity(),
r ? *r : Traits::get_point_at_right_bottom_infinity(),
b ? *b : Traits::get_curve_at_infinity(),
t ? *t : Traits::get_curve_at_infinity(),
((l ? 0 : CGAL_TRAPEZOIDAL_DECOMPOSITION_2_LEFT_UNBOUNDED) |
(r ? 0 : CGAL_TRAPEZOIDAL_DECOMPOSITION_2_RIGHT_UNBOUNDED) |
(b ? 0 : CGAL_TRAPEZOIDAL_DECOMPOSITION_2_BOTTOM_UNBOUNDED) |
(t ? 0 : CGAL_TRAPEZOIDAL_DECOMPOSITION_2_TOP_UNBOUNDED)),
lb, lt, rb, rt);
node = p;
}
Td_X_trapezoid (const X_trapezoid &tr) :
Handle(tr)
{
node = tr.node;
}
/*
remark:
operator= should not copy node (or otherwise update
Data_structure::replace)
*/
X_trapezoid& operator=(const X_trapezoid& t2)
{
Handle::operator=(t2);
return *this;
}
unsigned long id() const
{
return (unsigned long) PTR;
}
bool operator==(const X_trapezoid& t2) const
{
return identical(*this,t2);
}
bool operator!=(const X_trapezoid& t2) const
{
return !(operator==(t2));
}
const Point &left(void) const
{
return !is_left_unbounded() ?
ptr()->e0 : Traits::get_point_at_left_top_infinity();
}
const Point &right(void) const
{
return !is_right_unbounded() ?
ptr()->e1 : Traits::get_point_at_right_bottom_infinity();
}
// filters out the infinite case where at returns predefined dummy values
const X_curve &bottom(void) const
{
return !is_bottom_unbounded() ?
ptr()->e2 : Traits::get_curve_at_infinity();
}
const X_curve &top(void) const
{
return !is_top_unbounded() ?
ptr()->e3 : Traits::get_curve_at_infinity();
}
unsigned char boundedness() const {return ptr()->e4;}
bool is_left_unbounded() const {
return (ptr()->e4&CGAL_TRAPEZOIDAL_DECOMPOSITION_2_LEFT_UNBOUNDED)!=0;}
bool is_right_unbounded() const {
return (ptr()->e4&CGAL_TRAPEZOIDAL_DECOMPOSITION_2_RIGHT_UNBOUNDED)!=0;}
bool is_bottom_unbounded() const {
return (ptr()->e4&CGAL_TRAPEZOIDAL_DECOMPOSITION_2_BOTTOM_UNBOUNDED)!=0;}
bool is_top_unbounded() const {
return (ptr()->e4&CGAL_TRAPEZOIDAL_DECOMPOSITION_2_TOP_UNBOUNDED)!=0;}
bool is_unbounded() const
{
#ifdef CGAL_TD_DEBUG
CGAL_assertion(is_active());
#endif
return (ptr()->e4&CGAL_TRAPEZOIDAL_DECOMPOSITION_2_TOTALLY_UNBOUNDED)!=0;
}
pointer left_bottom_neighbour() const {return ptr()->e5;}
pointer left_top_neighbour() const {return ptr()->e6;}
pointer right_bottom_neighbour() const {return ptr()->e7;}
pointer right_top_neighbour() const {return ptr()->e8;}
Data_structure* get_node() const {return node;}
bool is_active() const
{return right_bottom_neighbour()!=
(pointer)CGAL_TRAPEZOIDAL_DECOMPOSITION_2_DELETE_SIGNATURE;}
void remove(Data_structure* left=0)
{
#ifndef CGAL_TD_DEBUG
CGAL_warning(is_active());
#else
CGAL_precondition(is_active());
#endif
// mark trapezoid as deleted,
set_rb((pointer)CGAL_TRAPEZOIDAL_DECOMPOSITION_2_DELETE_SIGNATURE);
#ifdef CGAL_TD_DEBUG
CGAL_warning(node);
#endif
// resets left son in data structure depending on input.
if (left) node->set_left(*left);
}
/* precondition:
both trapezoidal are active and have the same
bounding edges from above and below and the trapezoids are adjacent to one
another with the first to the left
postcondition:
this trapezoid is the union of the old this trapezoid
and the input trapezoids
*/
void merge_trapezoid(X_trapezoid& right)
{
#ifdef CGAL_TD_DEBUG
CGAL_assertion(!is_right_unbounded());
#endif
bool right_unbounded = right.is_right_unbounded();
*this=X_trapezoid(
!is_left_unbounded() ? &left() : 0,
!right_unbounded ? &right.right() : 0,
!is_bottom_unbounded() ? &bottom() : 0,
!is_top_unbounded() ? &top() : 0,
left_bottom_neighbour(),left_top_neighbour(),
right.right_bottom_neighbour(),
right.right_top_neighbour());
// if (right_unbounded) set_right_unbounded();
if (right_bottom_neighbour()) right_bottom_neighbour()->set_lb(this);
if (right_top_neighbour()) right_top_neighbour()->set_lt(this);
#ifdef CGAL_TD_DEBUG
CGAL_assertion(is_right_unbounded()==right.is_right_unbounded());
#endif
}
#ifdef CGAL_TD_DEBUG
bool is_valid(const Traits* traits) const
{
Comparison_result t;
bool b;
if (is_active())
{
if (get_node() && **get_node()!=*this)
{
std::cerr << "\nthis=";
write(std::cerr,*this,*traits,false);
std::cerr << "\nget_node= ";
write(std::cerr,**get_node(),*traits,false) << std::flush;
CGAL_warning(**get_node()==*this);
return false;
}
if (!is_left_unbounded() && !is_right_unbounded() &&
traits->point_is_left_low(right(),left()))
{
std::cerr << "\nthis=";
write(std::cerr,*this,*traits,false) << std::flush;
CGAL_warning(!traits->point_is_left_low(right(),left()));
return false;
}
if (!is_bottom_unbounded())
{
if (is_left_unbounded() || is_right_unbounded())
{
std::cerr << "\nthis=";
write(std::cerr,*this,*traits,false) << std::flush;
CGAL_warning(!(is_left_unbounded() ||is_right_unbounded()));
return false;
}
b = traits->point_in_x_range(bottom(),left());
if (b) {
t = traits->curve_compare_y_at_x(left(), bottom());
if (t == LARGER) t = SMALLER;
if (t == SMALLER) t = LARGER;
}
if (!b || t == LARGER)
{
std::cerr << "\nthis=";
write(std::cerr,*this,*traits,false) << std::flush;
std::cerr << "\nt==" << t << std::flush;
CGAL_warning(!b || t == LARGER);
return false;
}
b=traits->point_in_x_range(bottom(),right());
if (b) {
t = traits->curve_compare_y_at_x(right(), bottom());
if (t == LARGER) t = SMALLER;
if (t == SMALLER) t = LARGER;
}
if (!b || t == LARGER)
{
std::cerr << "\nthis=";
write(std::cerr,*this,*traits,false) << std::flush;
std::cerr << "\nt==" << t << std::flush;
CGAL_warning(!b || t == LARGER);
return false;
}
}
if (!is_top_unbounded())
{
if (is_left_unbounded() || is_right_unbounded())
{
std::cerr << "\nthis=";
write(std::cerr,*this,*traits,false) << std::flush;
CGAL_warning(!(is_left_unbounded() || is_right_unbounded()));
return false;
}
b=traits->point_in_x_range(top(),left());
if (b) {
t = traits->curve_compare_y_at_x(left(), top());
if (t == LARGER) t = SMALLER;
if (t == SMALLER) t = LARGER;
}
if (!b || t == SMALLER)
{
std::cerr << "\nthis=";
write(std::cerr,*this,*traits,false) << std::flush;
std::cerr << "\nt==" << t << std::flush;
CGAL_warning(!b || t == SMALLER);
return false;
}
b=traits->point_in_x_range(top(),right());
if (b) {
t = traits->curve_compare_y_at_x(right(), top());
if (t == LARGER) t = SMALLER;
if (t == SMALLER) t = LARGER;
}
if (!b || t == SMALLER)
{
std::cerr << "\nthis=";
write(std::cerr,*this,*traits,false) << std::flush;
std::cerr << "\nt==" << t << std::flush;
CGAL_warning(!b || t == SMALLER);
return false;
}
}
if (!traits->is_degenerate(*this))
{
if (right_top_neighbour() && right_top_neighbour()->top()!=top() ||
left_top_neighbour() && left_top_neighbour()->top() != top() ||
right_bottom_neighbour() &&
right_bottom_neighbour()->bottom() != bottom() ||
left_bottom_neighbour() &&
left_bottom_neighbour()->bottom() != bottom() ||
right_top_neighbour() &&
traits->is_degenerate(*right_top_neighbour()) ||
left_top_neighbour() &&
traits->is_degenerate(*left_top_neighbour()) ||
right_bottom_neighbour() &&
traits->is_degenerate(*right_bottom_neighbour()) ||
left_bottom_neighbour() &&
traits->is_degenerate(*left_bottom_neighbour())
)
{
std::cerr << "\nthis=";
write(std::cerr,*this,*traits,false) << std::flush;
CGAL_warning(!(right_top_neighbour() &&
right_top_neighbour()->top()!=top()));
CGAL_warning(!(left_top_neighbour() &&
left_top_neighbour()->top() != top()));
CGAL_warning(!(right_bottom_neighbour() &&
right_bottom_neighbour()->bottom()!=bottom()));
CGAL_warning(!(left_bottom_neighbour() &&
left_bottom_neighbour()->bottom() != bottom()));
CGAL_warning(!(right_top_neighbour() &&
traits->is_degenerate(*right_top_neighbour())));
CGAL_warning(!(left_top_neighbour() &&
traits->is_degenerate(*left_top_neighbour())));
CGAL_warning(!(right_bottom_neighbour() &&
traits->is_degenerate(*right_bottom_neighbour())));
CGAL_warning(!(left_bottom_neighbour() &&
traits->is_degenerate(*left_bottom_neighbour())));
return false;
}
if (right_top_neighbour()&&!right_top_neighbour()->is_active()||
left_top_neighbour()&&!left_top_neighbour()->is_active()||
right_bottom_neighbour()&&!right_bottom_neighbour()->is_active()||
left_bottom_neighbour()&&!left_bottom_neighbour()->is_active()
)
{
std::cerr << "\nleft=" << left() << " right=" << right()
<< " bottom=" << bottom() << " top=" << top()
<< std::flush;
CGAL_warning(!(right_top_neighbour() &&
!right_top_neighbour()->is_active()));
CGAL_warning(!(left_top_neighbour() &&
!left_top_neighbour()->is_active()));
CGAL_warning(!(right_bottom_neighbour() &&
!right_bottom_neighbour()->is_active()));
CGAL_warning(!(left_bottom_neighbour() &&
!left_bottom_neighbour()->is_active()));
return false;
}
}
else
{
/* if the trapezoid is degenerate, the left() and right()
points should be on the top() and bottom() curves.
In any case none of the geometric boundaries should
be unbounded */
if (is_bottom_unbounded()||
is_top_unbounded()||
is_left_unbounded()||
is_right_unbounded()
)
{
std::cerr << "\nbottom()==" << bottom() << std::flush;
std::cerr << "\ntop()==" << top() << std::flush;
std::cerr << "\nleft()==" << left() << std::flush;
std::cerr << "\nright()==" << right() << std::flush;
CGAL_warning((!is_bottom_unbounded()));
CGAL_warning((!is_top_unbounded()));
CGAL_warning((!is_left_unbounded()));
CGAL_warning((!is_right_unbounded()));
return false;
}
if (!traits->point_in_x_range(bottom(),left()) ||
traits->curve_compare_y_at_x(left(), bottom()) != EQUAL)
{
std::cerr << "\nbottom()==" << bottom() << std::flush;
std::cerr << "\nleft()==" << left() << std::flush;
CGAL_warning(traits->point_in_x_range(bottom(),left()) &&
traits->curve_compare_y_at_x(left(), bottom()) ==
EQUAL);
return false;
}
if (!traits->point_in_x_range(bottom(),right()) ||
traits->curve_compare_y_at_x(right(), bottom()) != EQUAL)
{
std::cerr << "\nbottom()==" << bottom() << std::flush;
std::cerr << "\nright()==" << right() << std::flush;
CGAL_warning(traits->point_in_x_range(bottom(),right()) &&
traits->curve_compare_y_at_x(right(), bottom()) ==
EQUAL);
return false;
}
if (!traits->point_in_x_range(top(),left()) ||
traits->curve_compare_y_at_x(left(), top()) != EQUAL)
{
std::cerr << "\ntop()==" << top() << std::flush;
std::cerr << "\nleft()==" << left() << std::flush;
CGAL_warning(!traits->point_in_x_range(top(),left()) &&
traits->curve_compare_y_at_x(left(), top()) == EQUAL);
return false;
}
if (!traits->point_in_x_range(top(),right()) ||
traits->curve_compare_y_at_x(right(), top()) != EQUAL)
{
std::cerr << "\ntop()==" << top() << std::flush;
std::cerr << "\nright()==" << right() << std::flush;
CGAL_warning(traits->point_in_x_range(top(),right()) &&
traits->curve_compare_y_at_x(right(), top()) == EQUAL);
return false;
}
if (traits->is_degenerate_curve(*this))
{
if (right_top_neighbour()&&!right_top_neighbour()->is_active()||
//!left_top_neighbour()||!left_top_neighbour()->is_active()||
right_bottom_neighbour() &&
!right_bottom_neighbour()->is_active()||
left_bottom_neighbour() && !left_bottom_neighbour()->is_active()
)
{
CGAL_warning(!right_top_neighbour() ||
right_top_neighbour()->is_active());
//CGAL_warning(!left_top_neighbour() ||
//left_top_neighbour()->is_active());
CGAL_warning(!right_bottom_neighbour() ||
right_bottom_neighbour()->is_active());
CGAL_warning(!left_bottom_neighbour() ||
left_bottom_neighbour()->is_active());
return false;
}
if (
/* if trapezoid is end relative to supporting X_curve, that is
adjacent(trapezoid's right end point,supporting X_curve right
end point) , right_top_neighbour() returns next such trapezoid
around right() point in clockwise oriented order
adjacent(trapezoid's left end point,supporting X_curve left end
point), left_bottom_neighbour() returns next such trapezoid
around left() point in clockwise oriented order */
/* right_bottom_neighbour() points to next trapezoid on
supporting X_curve, if such exist */
right_top_neighbour() &&
!traits->is_degenerate_curve(*right_top_neighbour())||
// !left_top_neighbour() ||
// !traits->is_degenerate_curve(*left_top_neighbour())||
right_bottom_neighbour() &&
!traits->is_degenerate_curve(*right_bottom_neighbour())||
left_bottom_neighbour() &&
!traits->is_degenerate_curve(*left_bottom_neighbour())
)
{
CGAL_warning(!right_top_neighbour() ||
traits->is_degenerate_curve(*right_top_neighbour()));
//CGAL_warning(!left_top_neighbour() ||
//!traits->is_degenerate_curve(*left_top_neighbour()));
CGAL_warning(!right_bottom_neighbour() ||
traits->
is_degenerate_curve(*right_bottom_neighbour()));
CGAL_warning(!left_bottom_neighbour() ||
traits->
is_degenerate_curve(*left_bottom_neighbour()));
return false;
}
}
else if (traits->is_degenerate_point(*this))
{
if (right_top_neighbour() &&
!traits->is_degenerate_curve(*right_top_neighbour())||
left_bottom_neighbour() &&
!traits->is_degenerate_curve(*left_bottom_neighbour())
)
{
CGAL_warning(!right_top_neighbour() ||
traits->is_degenerate_curve(*right_top_neighbour()));
CGAL_warning(!left_bottom_neighbour() ||
traits->
is_degenerate_curve(*left_bottom_neighbour()));
return false;
}
if (right_top_neighbour()&&!right_top_neighbour()->is_active()||
left_bottom_neighbour()&&!left_bottom_neighbour()->is_active()
)
{
CGAL_warning(!right_top_neighbour() ||
right_top_neighbour()->is_active());
CGAL_warning(!left_bottom_neighbour() ||
left_bottom_neighbour()->is_active());
return false;
}
if (!traits->point_equal(left(),right()))
{
std::cerr << "\nleft()==" << left() << std::flush;
std::cerr << "\nright()==" << right() << std::flush;
CGAL_warning(traits->point_equal(left(),right()));
return false;
}
}
}
}
return true;
}
void debug() const // instantiate ptr functions.
{
ptr();
bottom();
top();
left();
right();
}
#endif
};
CGAL_END_NAMESPACE
#endif