cgal/Packages/Matrix_search/include/CGAL/pierce_rectangles_2.h

2064 lines
64 KiB
C++

// ============================================================================
//
// Copyright (c) 1998 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 : pierce_rectangles_2.h
// chapter : $CGAL_Chapter: Geometric Optimisation $
// package : $CGAL_Package: Matrix_search $
// source : pcenter.aw
// revision : $Revision$
// revision_date : $Date$
// author(s) : Michael Hoffmann <hoffmann@inf.ethz.ch>
//
// coordinator : ETH Zurich (Bernd Gaertner <gaertner@inf.ethz.ch>)
//
// 2-4-Piercing Axis-Parallel 2D-Rectangles
// ============================================================================
#if ! (CGAL_PIERCE_RECTANGLES_2_H)
#define CGAL_PIERCE_RECTANGLES_2_H 1
#ifndef CGAL_OPTIMISATION_ASSERTIONS_H
#include <CGAL/optimisation_assertions.h>
#endif // CGAL_OPTIMISATION_ASSERTIONS_H
#ifndef CGAL_CIRCULATOR_H
#include <CGAL/circulator.h>
#endif // CGAL_CIRCULATOR_H
#ifndef CGAL_FUNCTION_OBJECTS_H
#include <CGAL/function_objects.h>
#endif // CGAL_FUNCTION_OBJECTS_H
#ifndef CGAL_TRANSFORM_ITERATOR_H
#include <CGAL/Transform_iterator.h>
#endif // CGAL_TRANSFORM_ITERATOR_H
#ifndef CGAL_ALGORITHM_H
#include <CGAL/algorithm.h>
#endif // CGAL_ALGORITHM_H
#include <algorithm>
#include <vector>
#ifdef CGAL_PCENTER_WINDOW_TRACE
#ifndef CGAL_IO_WINDOW_STREAM_H
#include <CGAL/IO/Window_stream.h>
#endif // CGAL_IO_WINDOW_STREAM_H
#ifndef CGAL_IO_OSTREAM_ITERATOR_H
#include <CGAL/IO/Ostream_iterator.h>
#endif // CGAL_IO_OSTREAM_ITERATOR_H
#endif // CGAL_PCENTER_WINDOW_TRACE
CGAL_BEGIN_NAMESPACE
//!!! to function_objects.h
template < class T1, class T2 >
struct Has_on_unbounded_side
: public CGAL_STD::binary_function< T1, T2, bool >
{
bool
operator()( const T1& a, const T2& b) const
{ return a.has_on_unbounded_side( b); }
};
template < class T1, class T2 >
struct Has_on_bounded_side
: public CGAL_STD::binary_function< T1, T2, bool >
{
bool
operator()( const T1& a, const T2& b) const
{ return a.has_on_bounded_side( b); }
};
template < class T1, class T2 >
struct Has_on_boundary
: public CGAL_STD::binary_function< T1, T2, bool >
{
bool
operator()( const T1& a, const T2& b) const
{ return a.has_on_boundary( b); }
};
//!!! STL-extensions
template < class T >
struct Wastebasket : public CGAL_STD::output_iterator
{
typedef Wastebasket< T > iterator;
iterator
operator=( const T&)
{ return *this; }
iterator
operator*()
{ return *this; }
iterator
operator++()
{ return *this; }
iterator
operator++( int)
{ return *this; }
};
template < class ForwardIterator, class OutputIterator, class Predicate >
OutputIterator
remove_copy_if_adjacent( ForwardIterator first,
ForwardIterator last,
OutputIterator result,
Predicate pred)
// copy [first, last) to result such that for all x in result
// pred( *x, *++x) is not true by dropping the second of any
// two adjacent items for which pred( *x, *++x) is true
{
if ( first == last)
return result;
ForwardIterator next = first;
while ( ++next != last)
if ( !pred( *first, *next)) {
*result++ = *first;
first = next;
}
*result++ = *first;
return result;
}
template < class ForwardIterator, class BinaryPredicate >
ForwardIterator
remove_if_adjacent( ForwardIterator first,
ForwardIterator last,
BinaryPredicate pred)
// transform [first, last) such that for all x
// pred( *x, *++x) is not true by dropping the second of
// any two adjacent items for which pred( *x, *++x) is true
{
#ifndef CGAL_CFG_NO_NAMESPACE
using std::adjacent_find;
using std::find_if;
using std::bind1st;
using std::logical_not;
using std::compose1;
#endif
first = adjacent_find( first, last, pred);
if ( first == last)
return last;
ForwardIterator save_first = first++;
// documented in CD2:
CGAL_optimisation_assertion( first != last);
ForwardIterator next =
find_if(
++first,
last,
compose1( logical_not< bool >(),
bind1st( pred, *save_first)));
return remove_copy_if_adjacent( next, last, ++save_first, pred);
}
template < class _Traits, class _RandomAccessIC >
class _Loc_domain {
public:
// ---------------------------------------------
// types:
typedef _Traits Traits;
typedef _RandomAccessIC RandomAccessIC;
typedef typename _Traits::Iso_rectangle_2 Iso_rectangle_2;
typedef typename _Traits::Point_2 Point_2;
typedef typename _Traits::FT FT;
typedef typename _Traits::Xmin Xmin;
typedef typename _Traits::Xmax Xmax;
typedef typename _Traits::Ymin Ymin;
typedef typename _Traits::Ymax Ymax;
// ---------------------------------------------
// creation:
_Loc_domain( RandomAccessIC b, RandomAccessIC e)
{
CGAL_optimisation_precondition( b != e);
RandomAccessIC i( b);
r[0] = r[1] = r[2] = r[3] = i;
while ( ++i != e) {
check_and_update_border( 0, i);
check_and_update_border( 1, i);
check_and_update_border( 2, i);
check_and_update_border( 3, i);
}
CGAL_optimisation_postcondition(
!(*r[0]).has_on_bounded_side( vertex( 0)) &&
!(*r[1]).has_on_bounded_side( vertex( 0)));
CGAL_optimisation_postcondition(
!(*r[1]).has_on_bounded_side( vertex( 1)) &&
!(*r[2]).has_on_bounded_side( vertex( 1)));
CGAL_optimisation_postcondition(
!(*r[2]).has_on_bounded_side( vertex( 2)) &&
!(*r[3]).has_on_bounded_side( vertex( 2)));
CGAL_optimisation_postcondition(
!(*r[3]).has_on_bounded_side( vertex( 3)) &&
!(*r[0]).has_on_bounded_side( vertex( 3)));
}
// ---------------------------------------------
// access operations:
RandomAccessIC
operator[]( int i) const
// return defining rectangle (0 <-> left, 1 <-> bottom)
{
CGAL_optimisation_precondition( i >= 0 && i < 4);
return r[i];
}
FT
xmin() const
// returns x-coordinate of left border
{ return Xmax()(*r[0]); }
FT
ymin() const
// returns y-coordinate of lower border
{ return Ymax()(*r[1]); }
FT
xmax() const
// returns x-coordinate of right border
{ return Xmin()(*r[2]); }
FT
ymax() const
// returns y-coordinate of upper border
{ return Ymin()(*r[3]); }
Point_2
vertex( int i) const
// PRE: 0 <= i < 4
// POST: returns one of the four vertices:
// 0 <=> lower left
// 1 <=> lower right
// 2 <=> upper right
// 3 <=> upper left
{
CGAL_optimisation_precondition( i >= 0 && i < 4);
typedef typename _Traits::Build_point Build;
switch( i) {
case 0:
return Build()( xmin(), ymin());
case 1:
return Build()( xmax(), ymin());
case 2:
return Build()( xmax(), ymax());
// case 3:
// return Point_2( xmin(), ymax());
}
return Build()( xmin(), ymax());
}
Point_2
min() const
// return lexicographically smallest vertex
// (in analogy to Iso_rectangle)
{ return vertex( 0); }
Point_2
max() const
// return lexicographically largest vertex
// (in analogy to Iso_rectangle)
{ return vertex( 2); }
// ---------------------------------------------
// update operations:
void
init( int i, RandomAccessIC f)
// PRE: 0 <= i < 4
// POST: set defining rectangle r[i] to f
{
CGAL_optimisation_precondition( i >= 0 && i < 4);
r[i] = f;
}
void
check_and_update_border( int i, RandomAccessIC a)
// PRE: 0 <= i < 4
// POST: check whether rectangle *a invalidates
// border i. if so, update defining rectangle r[i]
// to a.
{
CGAL_optimisation_precondition( i >= 0 && i < 4);
switch( i) {
case 0:
if ( Xmax()(*a) < Xmax()(*r[0]))
r[0] = a;
break;
case 1:
if ( Ymax()(*a) < Ymax()(*r[1]))
r[1] = a;
break;
case 2:
if ( Xmin()(*a) > Xmin()(*r[2]))
r[2] = a;
break;
case 3:
if ( Ymin()(*a) > Ymin()(*r[3]))
r[3] = a;
break;
}
}
private:
// pointer to defining rectangles:
RandomAccessIC r[4];
}; // class _Loc_domain
template < class _Traits, class _RandomAccessIC >
class _Rectangle_partition {
public:
typedef _Traits Traits;
typedef _RandomAccessIC RandomAccessIC;
typedef typename _Traits::Iso_rectangle_2 Iso_rectangle_2;
typedef typename _Traits::FT FT;
typedef typename _Traits::Xmin Xmin;
typedef typename _Traits::Xmax Xmax;
typedef typename _Traits::Ymin Ymin;
typedef typename _Traits::Ymax Ymax;
typedef typename _Traits::Build_point Build_point;
typedef typename _Traits::Build_rectangle Build_rectangle;
// constants to identify the eleven partition sets:
// BL and TL are sorted according to right sides
// in increasing order,
// BR, TR and BT are sorted according to left sides
// in decreasing order,
// LR is sorted according to top sides
// in increasing order and
// TR, TL, L, R, NO are not sorted
enum set_id { BL, TL, BT, BR, TR, LR, B, T, L, R, NO};
typedef std::vector< Iso_rectangle_2 > Container;
typedef typename Container::iterator iterator;
typedef typename Container::reverse_iterator reverse_iterator;
typedef typename Container::const_iterator const_iterator;
// constructor: partition the range [f,l) of rectangles
// according to d
// precondition:
// d is the location domain associated with [f, l)
_Rectangle_partition(
RandomAccessIC f,
RandomAccessIC l,
const _Loc_domain< _Traits, RandomAccessIC >& d);
// ---------------------------------------------------
// access functions to the partition sets:
const_iterator
begin( set_id i) const
{
CGAL_optimisation_precondition( i >= BL && i <= NO);
const_iterator p( s[i].begin());
if ( i <= LR)
return ++p;
else
return p;
}
const_iterator
end( set_id i) const
{
CGAL_optimisation_precondition( i >= BL && i <= NO);
const_iterator p( s[i].end());
if ( i <= LR)
return --p;
else
return p;
}
bool
is_empty( set_id i) const
{
CGAL_optimisation_precondition( i >= BL && i <= NO);
CGAL_optimisation_assertion( begin( i) <= end( i));
return begin( i) == end( i);
}
const_iterator
first_right_of( set_id i, FT v, const_iterator p) const
// PRE: i == BL or i == BT, p in [ begin(i), end(i) ] and
// i == BT ==>
// *p lies to the left of (not including) the line x = v.
// i == BL:
// returns the maximal q from [ p, end(i) ]
// such that all rectangles from [ p, q )
// lie to the left of (not including) the line x = v.
// i == BT:
// returns the minimal q from [ begin(i), p ]
// such that all rectangles from [ q, end(i) )
// lie to the left of (not including) the line x = v.
// TIME: O( #elements in set i between p and q)
{
CGAL_optimisation_precondition(
(i == BL || i == BT && xmax( *p) < v) &&
p >= begin(i) && p <= end(i));
CGAL_optimisation_postcondition_code( const_iterator pp( p);)
// s[BL] is sorted acc. to right sides incr.
if ( i == BL) {
while ( xmax( *p) < v)
++p;
CGAL_optimisation_postcondition( p >= begin(i) && p <= end(i));
CGAL_optimisation_postcondition( p == pp || xmax( *(p - 1)) < v);
} else {
// s[BT] is sorted acc. to left sides decr.
while ( xmax( *--p) < v) {}
++p;
CGAL_optimisation_postcondition( p >= begin(i) && p <= end(i));
CGAL_optimisation_postcondition( p == end(i) || xmax( *p) < v);
}
return p;
}
const_iterator
first_right_of( set_id i, FT v) const
// PRE: i == BL or i == BT
// i == BL:
// returns the maximal q from [ begin(i), end(i) ]
// such that all rectangles from [ begin(i), q )
// lie to the left of (not including) the line x = v.
// i == BT:
// returns the minimal q from [ begin(i), end(i) ]
// such that all rectangles from [ q, end(i) )
// lie to the left of (not including) the line x = v.
// TIME: O( log(#elements in set i))
{
#ifndef CGAL_CFG_NO_NAMESPACE
using std::lower_bound;
using std::less;
using std::identity;
using std::greater_equal;
#endif
CGAL_optimisation_precondition( i == BL || i == BT);
const_iterator p;
if ( i == BL) {
p = lower_bound( begin( BL),
s[BL].end(),
v,
compose2_2( less< FT >(),
xmax,
identity< FT >()));
CGAL_optimisation_postcondition(
p == begin(i) || xmax( *(p - 1)) < v);
} else {
p = lower_bound( begin( i),
s[i].end(),
v,
compose2_2( greater_equal< FT >(),
xmax,
identity< FT >()));
CGAL_optimisation_postcondition( p == end(i) || xmax( *p) < v);
}
CGAL_optimisation_postcondition( p >= begin(i) && p <= end(i));
return p;
}
const_iterator
first_left_of( set_id i, FT v, const_iterator p) const
// PRE: i == BT, p in [ begin(i), end(i) ]
// returns the maximal q from [ begin(i), p ]
// such that all rectangles from [ begin(i), q )
// lie to the right of (not including) the line x = v.
// TIME: O( #elements in set i between p and q)
{
CGAL_optimisation_precondition(
i == BT && p >= begin(i) && p <= end(i));
while ( xmin( *p) <= v)
--p;
++p;
CGAL_optimisation_postcondition( p >= begin(i) && p <= end(i));
CGAL_optimisation_postcondition(
p == begin(i) || Xmin()( *(p - 1)) > v);
CGAL_optimisation_postcondition( xmax( *p) <= v);
return p;
}
const_iterator
first_left_of( set_id i, FT v) const
// PRE: i == BR or i == BT.
// returns the maximal q from [ begin(i), end(i) ]
// such that all rectangles from [ begin(i), q )
// lie to the right of (not including) the line x = v.
// TIME: O( log(#elements in set i))
{
#ifndef CGAL_CFG_NO_NAMESPACE
using std::lower_bound;
using std::identity;
using std::greater;
#endif
CGAL_optimisation_precondition( i == BR || i == BT);
const_iterator p =
lower_bound( begin( i),
s[i].end(),
v,
compose2_2( greater< FT >(),
Xmin(),
identity< FT >()));
CGAL_optimisation_postcondition( p >= begin(i) && p <= end(i));
CGAL_optimisation_postcondition(
p == begin(i) || Xmin()( *(p - 1)) > v);
return p;
}
const_iterator
first_above_downwards( set_id i, FT v, const_iterator p) const
// PRE: i == TL or i == LR, p in [ begin(i), end(i) ] and
// *p lies above (not including) the line y = v.
// returns the minimal q from [ begin(i), p ]
// such that all rectangles from [ q, end(i) )
// lie above (not including) the line y = v.
// TIME: O( #elements in set i between p and q)
{
CGAL_optimisation_precondition( i == TL || i == LR);
CGAL_optimisation_precondition(
ymin(*p) > v && p >= begin(i) && p <= end(i));
while ( ymin( *--p) > v) {}
++p;
CGAL_optimisation_postcondition( p >= begin(i) && p <= end(i));
CGAL_optimisation_postcondition( p == end(i) || Ymin()( *p) > v);
return p;
}
const_iterator
first_above_upwards( set_id i, FT v, const_iterator p) const
// PRE: i == TR or i == LR and p in [ begin(i), end(i) ]
// returns the minimal q from [ p, end(i) ]
// such that all rectangles from [ q, end(i) )
// lie above (not including) the line y = v.
// TIME: O( #elements in set i between p and q)
{
CGAL_optimisation_precondition(
(i == TR || i == LR) && p >= begin(i) && p <= end(i));
while ( ymin( *p) <= v)
++p;
CGAL_optimisation_postcondition( p >= begin(i) && p <= end(i));
CGAL_optimisation_postcondition( p == end(i) || Ymin()( *p) > v);
return p;
}
const_iterator
first_above( set_id i, FT v) const
// PRE: i == TL or i == TR or i == LR
// returns the minimal q from [ begin(i), end(i) ]
// such that all rectangles from [ q, end(i) )
// lie above (not including) the line y = v.
// TIME: O( log(#elements in set i))
{
#ifndef CGAL_CFG_NO_NAMESPACE
using std::lower_bound;
using std::identity;
using std::less_equal;
#endif
CGAL_optimisation_precondition( i == TL || i == TR || i == LR);
const_iterator p =
lower_bound( begin( i),
s[i].end(),
v,
compose2_2( less_equal< FT >(),
Ymin(),
identity< FT >()));
CGAL_optimisation_postcondition( p >= begin(i) && p <= end(i));
CGAL_optimisation_postcondition( p == end(i) || Ymin()( *p) > v);
return p;
}
private:
void
sort_set( set_id i)
{
#ifndef CGAL_CFG_NO_NAMESPACE
using std::sort;
using std::less;
using std::greater;
#endif
CGAL_optimisation_precondition( i >= BL && i <= LR);
CGAL_optimisation_precondition( s[i].begin() + 1 == begin( i));
// NB: only used in constructor.
// using s[...].end() instead of end(...)
// since upper sentinels have not been inserted yet
if ( i <= TL)
sort( s[i].begin() + 1,
s[i].end(),
compose2_2( less< FT >(), Xmax(), Xmax()));
else if ( i <= TR)
sort( s[i].begin() + 1,
s[i].end(),
compose2_2( greater< FT >(), Xmin(), Xmin()));
else if ( i == LR)
sort( s[i].begin() + 1,
s[i].end(),
compose2_2( less< FT >(), Ymax(), Ymax()));
} // sort_set( set_id i)
void
remove_containing_rectangles()
// make sure that in any partition set there are no
// two rectangles such that if they are clipped
// against the location domain, one contains the other.
{
#ifndef CGAL_CFG_NO_NAMESPACE
using std::greater_equal;
using std::less_equal;
#endif
iterator new_end;
// NB: only used in constructor.
// using s[...].end() instead of end(...)
// since upper sentinels have not been inserted yet
// ------------------------------------------------------
// sorted according to their right sides (increasing):
// s[BL]: discard second, if its top side is above
CGAL_optimisation_assertion( s[BL].begin() + 1 == begin( BL));
new_end =
remove_if_adjacent(
s[BL].begin() + 1,
s[BL].end(),
compose2_2( less_equal< FT >(), Ymax(), Ymax()));
s[BL].erase( new_end, s[BL].end());
// s[TL]: discard second, if its bottom side is below
CGAL_optimisation_assertion( s[TL].begin() + 1 == begin( TL));
new_end =
remove_if_adjacent(
s[TL].begin() + 1,
s[TL].end(),
compose2_2( greater_equal< FT >(), Ymin(), Ymin()));
s[TL].erase( new_end, s[TL].end());
// ------------------------------------------------------
// sorted according to their left sides (decreasing):
// s[BT]: discard second, if its right side is right
CGAL_optimisation_assertion( s[BT].begin() + 1 == begin( BT));
new_end =
remove_if_adjacent(
s[BT].begin() + 1,
s[BT].end(),
compose2_2( less_equal< FT >(), Xmax(), Xmax()));
s[BT].erase( new_end, s[BT].end());
// s[BR]: discard second, if its top side is above
CGAL_optimisation_assertion( s[BR].begin() + 1 == begin( BR));
new_end =
remove_if_adjacent(
s[BR].begin() + 1,
s[BR].end(),
compose2_2( less_equal< FT >(), Ymax(), Ymax()));
s[BR].erase( new_end, s[BR].end());
// s[TR]: discard second, if its bottom side is below
CGAL_optimisation_assertion( s[TR].begin() + 1 == begin( TR));
new_end =
remove_if_adjacent(
s[TR].begin() + 1,
s[TR].end(),
compose2_2( greater_equal< FT >(), Ymin(), Ymin()));
s[TR].erase( new_end, s[TR].end());
// ------------------------------------------------------
// sorted according to their top sides (increasing):
// s[LR]: discard second, if its bottom side is below
CGAL_optimisation_assertion( s[LR].begin() + 1 == begin( LR));
new_end =
remove_if_adjacent(
s[LR].begin() + 1,
s[LR].end(),
compose2_2( greater_equal< FT >(), Ymin(), Ymin()));
s[LR].erase( new_end, s[LR].end());
} // remove_containing_rectangles()
// the partition sets:
Container s[11];
// coordinate accessors:
Xmin xmin;
Xmax xmax;
Ymin ymin;
Ymax ymax;
// point builder:
Build_point build_point;
// rectangle builder:
Build_rectangle build_rectangle;
};
template < class _Traits, class _RandomAccessIC >
_Rectangle_partition< _Traits, _RandomAccessIC>::
_Rectangle_partition(
_RandomAccessIC f,
_RandomAccessIC l,
const _Loc_domain< _Traits, _RandomAccessIC >& d)
{
//!!! reserves
// sentinel rectangles (si <-> d.vertex(i)):
FT rad = (f == l ? 0 : (*f).radius());
Iso_rectangle_2 s0(
build_rectangle(
build_point( d.xmin() - FT(1) - rad, d.ymin() - FT(1) - rad)));
Iso_rectangle_2 s1(
build_rectangle(
build_point( d.xmax() + FT(1) + rad, d.ymin() - FT(1) - rad)));
Iso_rectangle_2 s2(
build_rectangle(
build_point( d.xmax() + FT(1) + rad, d.ymax() + FT(1) + rad)));
Iso_rectangle_2 s3(
build_rectangle(
build_point( d.xmin() - FT(1) - rad, d.ymax() + FT(1) + rad)));
// insert lower sentinels:
s[BL].push_back( s3);
s[BR].push_back( s2);
s[BT].push_back( s2);
s[TL].push_back( s0);
s[TR].push_back( s1);
s[LR].push_back( s1);
while ( f != l) {
// otherwise d would not be the location domain:
CGAL_optimisation_expensive_assertion(
(*f).xmax() >= d.xmin() && (*f).ymax() >= d.ymin() &&
(*f).xmin() <= d.xmax() && (*f).ymin() <= d.ymax());
if ( (*f).xmin() > d.xmin())
if ( (*f).xmax() < d.xmax())
// *f belongs to S_b, S_t, S_bt or S_no
if ( (*f).ymin() > d.ymin())
if ( (*f).ymax() < d.ymax())
s[NO].push_back( *f);
else
s[T].push_back( *f);
else
if ( (*f).ymax() < d.ymax())
s[B].push_back( *f);
else
s[BT].push_back( *f);
else
// *f belongs to S_r, S_tr, S_br or has to be discarded
if ( (*f).ymin() > d.ymin())
if ( (*f).ymax() < d.ymax())
s[R].push_back( *f);
else
s[TR].push_back( *f);
else {
if ( (*f).ymax() < d.ymax())
s[BR].push_back( *f);
}
else
if ( (*f).xmax() < d.xmax())
// *f belongs to S_l, S_tl, S_bl or has to be discarded
if ( (*f).ymin() > d.ymin())
if ( (*f).ymax() < d.ymax())
s[L].push_back( *f);
else
s[TL].push_back( *f);
else {
if ( (*f).ymax() < d.ymax())
s[BL].push_back( *f);
}
else {
// *f belongs to S_lr or has to be discarded
if ( (*f).ymin() > d.ymin() &&
(*f).ymax() < d.ymax())
s[LR].push_back( *f);
}
++f;
} // while ( f != l)
// sort partition sets:
sort_set( BL);
sort_set( BR);
sort_set( BT);
sort_set( TL);
sort_set( TR);
sort_set( LR);
// remove the rectangles containing a following rectangle:
remove_containing_rectangles();
// insert upper sentinels:
s[BL].push_back( s1);
s[BR].push_back( s0);
s[BT].push_back( s3);
s[TL].push_back( s2);
s[TR].push_back( s3);
s[LR].push_back( s3);
} // Rectangle_partition( f, l, d)
CGAL_END_NAMESPACE
#ifdef CGAL_REP_CLASS_DEFINED
#ifndef CGAL_PIERCE_RECTANGLES_2_TRAITS_H
#include <CGAL/Pierce_rectangles_2_traits.h>
#endif // CGAL_PIERCE_RECTANGLES_2_TRAITS_H
#endif // CGAL_REP_CLASS_DEFINED
CGAL_BEGIN_NAMESPACE
template < class RandomAccessIC,
class OutputIterator,
class Traits >
OutputIterator
two_pierce_rectangles(
RandomAccessIC f,
RandomAccessIC l,
OutputIterator o,
bool& ok,
const Traits&)
{
CGAL_optimisation_precondition( f != l);
// compute location domain:
typedef _Loc_domain< Traits, RandomAccessIC > Loc_domain;
Loc_domain d( f, l);
return two_pierce_rectangles( f, l, d, o, ok);
} // two_pierce_rectangles( f, l, o, ok, i)
template < class RandomAccessIC,
class OutputIterator,
class Traits >
OutputIterator
three_pierce_rectangles(
RandomAccessIC f,
RandomAccessIC l,
OutputIterator o,
bool& ok,
const Traits&)
{
CGAL_optimisation_precondition( f != l);
// compute location domain:
typedef _Loc_domain< Traits, RandomAccessIC > Loc_domain;
Loc_domain d( f, l);
return three_pierce_rectangles( f, l, d, o, ok);
} // three_pierce_rectangles( f, l, o, ok, i)
template < class RandomAccessIC,
class OutputIterator,
class Traits >
OutputIterator
four_pierce_rectangles(
RandomAccessIC f,
RandomAccessIC l,
OutputIterator o,
bool& ok,
const Traits&)
{
CGAL_optimisation_precondition( f != l);
// compute location domain:
typedef _Loc_domain< Traits, RandomAccessIC > Loc_domain;
Loc_domain d( f, l);
return four_pierce_rectangles( f, l, d, o, ok);
} // four_pierce_rectangles( f, l, o, ok, i)
template < class RandomAccessIC,
class OutputIterator,
class Traits >
OutputIterator
two_pierce_rectangles(
RandomAccessIC f,
RandomAccessIC l,
const _Loc_domain< Traits, RandomAccessIC >& d,
OutputIterator o,
bool& ok)
{
#ifndef CGAL_CFG_NO_NAMESPACE
using std::logical_and;
using std::compose2;
using std::bind2nd;
using std::find_if;
#endif
CGAL_optimisation_precondition( f != l);
// typedefs:
typedef typename Traits::Point_2
Point_2;
typedef typename Traits::Iso_rectangle_2
Iso_rectangle_2;
typedef Has_on_unbounded_side< Iso_rectangle_2, Point_2 >
Has_on_unbounded_side;
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 2
cerr << " ++ 2 pierce start ++" << endl;
for ( RandomAccessIC u = f; u != l; ++u)
cerr << &(*u) << " : " << *u << endl;
cerr << "LocDomain is " << d.vertex( 0) << " --> " <<
d.vertex( 2) << endl;
/*
Window_stream W;
W.init( -1024 / 5, 1024 + 1024 / 5, -1024 / 5);
W << RED;
WindowOutput( W, f, l);
W << GREEN;
W << Iso_rectangle_2( d.vertex( 0), d.vertex( 2));
double x, y;
while ( W.read_mouse( x, y) != -1) {}
*/
#endif
if ( !(*d[0]).has_on_unbounded_side( d.vertex( 0)) &&
!(*d[1]).has_on_unbounded_side( d.vertex( 0)) &&
!(*d[2]).has_on_unbounded_side( d.vertex( 0)) &&
!(*d[3]).has_on_unbounded_side( d.vertex( 0))) {
// the location domain is degenerate
// and [f,l) is one-pierceable
*o++ = d.vertex( 0);
ok = true;
return o;
}
// check, if {d.vertex( 0), d.vertex( 2)}
// form a piercing set
if ( l == find_if(
f,
l,
compose2( logical_and< bool >(),
bind2nd( Has_on_unbounded_side(),
d.vertex( 0)),
bind2nd( Has_on_unbounded_side(),
d.vertex( 2)))))
{
// {d.vertex( 0), d.vertex( 2)} is a piercing set
*o++ = d.vertex( 0);
*o++ = d.vertex( 2);
ok = true;
return o;
}
// check, if {d.vertex( 1), d.vertex( 3)}
// form a piercing set
if ( l == find_if(
f,
l,
compose2( logical_and< bool >(),
bind2nd( Has_on_unbounded_side(),
d.vertex( 1)),
bind2nd( Has_on_unbounded_side(),
d.vertex( 3)))))
{
// {d.vertex( 1), d.vertex( 3)} is a piercing set
*o++ = d.vertex( 1);
*o++ = d.vertex( 3);
ok = true;
return o;
}
// no piercing set exists:
ok = false;
return o;
} // two_pierce_rectangles( f, l, d, o, ok)
template < class RandomAccessIC,
class OutputIterator,
class Traits >
OutputIterator
three_pierce_rectangles(
RandomAccessIC f,
RandomAccessIC l,
_Loc_domain< Traits, RandomAccessIC >& d,
OutputIterator o,
bool& ok)
{
#ifndef CGAL_CFG_NO_NAMESPACE
using std::find_if;
using std::bind2nd;
#endif
#ifdef CGAL_CFG_NO_ITERATOR_TRAITS
typedef ptrdiff_t difference_type;
#else // CGAL_CFG_NO_ITERATOR_TRAITS //
typedef typename std::iterator_traits< RandomAccessIC >::difference_type
difference_type;
#endif // CGAL_CFG_NO_ITERATOR_TRAITS //
difference_type number_of_points( iterator_distance( f, l));
CGAL_optimisation_precondition( number_of_points > 0);
// typedefs:
typedef typename Traits::Point_2 Point_2;
typedef typename Traits::Iso_rectangle_2 Iso_rectangle_2;
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 3
cerr << " ++ 3 pierce start ++" << endl;
for ( RandomAccessIC u = f; u != l; ++u)
cerr << &(*u) << " : " << *u << endl;
cerr << "LocDomain is " << d.vertex( 0) << " --> "
<< d.vertex( 2) << endl;
#endif
// define container to store disjoint rectangles:
// typedef vector< Iso_rectangle_2 > Rectangle_cont;
typedef vector< Iso_rectangle_2 > Rectangle_cont;
typedef Rectangle_cont::size_type size_type;
typedef Rectangle_cont::iterator Rectangle_iterator;
typedef Has_on_unbounded_side< Iso_rectangle_2, Point_2 >
Does_not_contain;
Rectangle_cont disjoint;
disjoint.reserve( number_of_points);
// test the four corners:
for ( int k( 0); k < 4; ++k) {
disjoint.erase( disjoint.begin(), disjoint.end());
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 3
cerr << "check corner nr. " << k << " ("
<< d.vertex(k) << ")" << endl;
#endif
// save changing sides of d:
RandomAccessIC save_side1( d[k]);
RandomAccessIC save_side2( d[( k + 1) % 4]);
// extract all rectangles not containing d.vertex( k)
// into rc and update d:
/*
typedef Get_address< Iso_rectangle_2 > Rect_address;
typedef Transform_iterator<
back_insert_iterator< Rectangle_cont >,
Rect_address >
Address_iterator;
*/
// find first rectangle not containing d.vertex( k):
RandomAccessIC f_not(
find_if( f, l, bind2nd( Does_not_contain(), d.vertex( k))));
// do all rectangles contain the corner?
if ( f_not == l) {
CGAL_optimisation_assertion( k == 0);
*o++ = d.vertex( k);
ok = true;
return o;
} // if ( f_not == l)
// (*f_not) does not contain the corner, so it can be used
// to initialize the two (possibly) changing sides of d:
Point_2 test_vertex( d.vertex( k));
d.init( k, f_not);
d.init( ( k + 1) % 4, f_not);
disjoint.push_back( *f_not);
// now run through it:
while ( ++f_not != l)
if ( Does_not_contain()( *f_not, test_vertex)) {
disjoint.push_back( *f_not);
d.check_and_update_border( k, f_not);
d.check_and_update_border( ( k + 1) % 4, f_not);
} // if ( Does_not_contain()( *f_not, d.vertex( k)))
// check disjoint for two-pierceability:
two_pierce_rectangles(
disjoint.begin(),
disjoint.end(),
d,
o,
ok);
// restore saved sides of d:
d.init( k, save_side1);
d.init( ( k + 1) % 4, save_side2);
if ( ok) {
// does any rectangle contain the corner?
if ( disjoint.size() < CGAL_static_cast( size_type, number_of_points))
*o++ = d.vertex( k);
return o;
} // if ( ok)
} // for ( int k( 0); k < 4; ++k)
// no piercing set exists:
ok = false;
return o;
} // three_pierce_rectangles( f, l, d, o, ok)
template < class RandomAccessIC,
class OutputIterator,
class Traits >
inline
OutputIterator
four_pierce_rectangles(
RandomAccessIC f,
RandomAccessIC l,
_Loc_domain< Traits, RandomAccessIC >& d,
OutputIterator o,
bool& ok)
{
// construct partition:
typedef _Rectangle_partition< Traits, RandomAccessIC > Partition;
Partition p( f, l, d);
return four_pierce_rectangles( f, l, d, p, o, ok);
} // four_pierce_rectangles( f, l, d, o, ok)
template < class RandomAccessIC,
class OutputIterator,
class Traits >
OutputIterator
four_pierce_rectangles(
RandomAccessIC f,
RandomAccessIC l,
_Loc_domain< Traits, RandomAccessIC >& d,
_Rectangle_partition< Traits, RandomAccessIC >& p,
OutputIterator o,
bool& ok)
{
int number_of_points( iterator_distance( f, l));
CGAL_optimisation_precondition( number_of_points > 0);
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 4
cerr << " ** 4 pierce start **" << endl;
for ( RandomAccessIC u = f; u != l; ++u)
cerr << &(*u) << " : " << *u << endl;
cerr << "LocDomain is " << d.vertex( 0) << " --> "
<< d.vertex( 2) << endl;
#endif
#ifndef CGAL_CFG_NO_NAMESPACE
using std::pair;
using std::min;
using std::max;
using std::greater;
using std::less;
using std::find_if;
using std::bind2nd;
#endif
typedef typename Traits::Iso_rectangle_2 Iso_rectangle_2;
typedef typename Traits::Point_2 Point_2;
typedef typename Traits::FT FT;
typedef typename Traits::Xmin Xmin;
typedef typename Traits::Xmax Xmax;
typedef typename Traits::Ymin Ymin;
typedef typename Traits::Ymax Ymax;
typedef typename Traits::Build_point Build_point;
typedef typename Traits::Build_rectangle Build_rectangle;
typedef pair< FT, FT > Intervall;
typedef _Rectangle_partition< Traits, RandomAccessIC > RP;
typedef typename RP::const_iterator iterator;
typedef pair< iterator, iterator > iterator_pair;
// point builder:
Build_point build_point;
// coordinate accessors:
Xmin xmin;
Xmax xmax;
Ymin ymin;
Ymax ymax;
// define container to store disjoint rectangles:
// typedef vector< Iso_rectangle_2 > Rectangle_cont;
typedef vector< Iso_rectangle_2 > Rectangle_cont;
typedef Rectangle_cont::size_type size_type;
typedef Rectangle_cont::iterator Rectangle_iterator;
typedef Has_on_unbounded_side< Iso_rectangle_2, Point_2 >
Does_not_contain;
Rectangle_cont disjoint;
disjoint.reserve( number_of_points);
// test the four corners:
for ( int k( 0); k < 4; ++k) {
disjoint.erase( disjoint.begin(), disjoint.end());
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 3
cerr << "check corner nr. " << k << " ("
<< d.vertex(k) << ")" << endl;
#endif
// save changing sides of d:
RandomAccessIC save_side1( d[k]);
RandomAccessIC save_side2( d[( k + 1) % 4]);
// extract all rectangles not containing d.vertex( k)
// into rc and update d:
/*
typedef Get_address< Iso_rectangle_2 > Rect_address;
typedef Transform_iterator<
back_insert_iterator< Rectangle_cont >,
Rect_address >
Address_iterator;
*/
// find first rectangle not containing d.vertex( k):
RandomAccessIC f_not(
find_if( f, l, bind2nd( Does_not_contain(), d.vertex( k))));
// do all rectangles contain the corner?
if ( f_not == l) {
CGAL_optimisation_assertion( k == 0);
*o++ = d.vertex( k);
ok = true;
return o;
} // if ( f_not == l)
// (*f_not) does not contain the corner, so it can be used
// to initialize the two (possibly) changing sides of d:
Point_2 test_vertex( d.vertex( k));
d.init( k, f_not);
d.init( ( k + 1) % 4, f_not);
disjoint.push_back( *f_not);
// now run through it:
while ( ++f_not != l)
if ( Does_not_contain()( *f_not, test_vertex)) {
disjoint.push_back( *f_not);
d.check_and_update_border( k, f_not);
d.check_and_update_border( ( k + 1) % 4, f_not);
} // if ( Does_not_contain()( *f_not, d.vertex( k)))
// check disjoint for two-pierceability:
three_pierce_rectangles(
disjoint.begin(),
disjoint.end(),
d,
o,
ok);
// restore saved sides of d:
d.init( k, save_side1);
d.init( ( k + 1) % 4, save_side2);
if ( ok) {
// does any rectangle contain the corner?
if ( disjoint.size() < CGAL_static_cast( size_type, number_of_points))
*o++ = d.vertex( k);
return o;
} // if ( ok)
} // for ( int k( 0); k < 4; ++k)
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 4
cerr << "traversing boundary ..." << endl;
#endif
// test if four p'points can be placed on the boundary of d,
// one on each side
// if there is any rectangle completely contained in d,
// there is no hope for a four-piercing in this way
if ( p.is_empty( RP::NO)) {
#if defined(CGAL_PCENTER_WINDOW_TRACE)
// graphic debug window:
Window_stream Wd;
const int XYSIZE( 1024);
double dummy_x, dummy_y;
Ostream_iterator< Point_2, Window_stream > Witer;
Witer wout;
#endif
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 4
cerr << "compute one-piercing intervalls ..." << endl;
#endif
iterator_pair ip;
// compute the intervall I_B where s[B] is (potentially)
// one-pierced:
// I_B is defined by the smallest maxpoint and the
// largest minpoint of the rectangles in s[B]
Intervall I_B;
if ( p.is_empty( RP::B))
I_B = Intervall( d.xmin(), d.xmax());
else {
ip = min_max_element( p.begin( RP::B),
p.end( RP::B),
compose2_2(
less< FT >(), Xmax(), Xmax()),
compose2_2(
less< FT >(), Xmin(), Xmin()));
I_B = Intervall( Xmin()(*(ip.second)), Xmax()(*(ip.first)));
CGAL_optimisation_assertion(
I_B.first >= d.xmin() && I_B.second <= d.xmax());
}
// compute the intervall I_L where s[L] is (potentially)
// one-pierced:
// I_L is defined by the smallest maxpoint and the
// largest minpoint of the rectangles in s[L]
Intervall I_L;
if ( p.is_empty( RP::L))
I_L = Intervall( d.ymin(), d.ymax());
else {
ip = min_max_element( p.begin( RP::L),
p.end( RP::L),
compose2_2(
less< FT >(), Ymax(), Ymax()),
compose2_2(
less< FT >(), Ymin(), Ymin()));
I_L = Intervall( Ymin()(*(ip.second)), Ymax()(*(ip.first)));
CGAL_optimisation_assertion(
I_L.first >= d.ymin() && I_L.second <= d.ymax());
}
// compute the intervall I_T where s[T] is (potentially)
// one-pierced:
// I_T is defined by the smallest maxpoint and the
// largest minpoint of the rectangles in s[T]
Intervall I_T;
if ( p.is_empty( RP::T))
I_T = Intervall( d.xmin(), d.xmax());
else {
ip = min_max_element( p.begin( RP::T),
p.end( RP::T),
compose2_2(
less< FT >(), Xmax(), Xmax()),
compose2_2(
less< FT >(), Xmin(), Xmin()));
I_T = Intervall( Xmin()(*(ip.second)), Xmax()(*(ip.first)));
CGAL_optimisation_assertion(
I_T.first >= d.xmin() && I_T.second <= d.xmax());
}
// compute the intervall I_R where s[R] is (potentially)
// one-pierced:
// I_R is defined by the smallest maxpoint and the
// largest minpoint of the rectangles in s[R]
Intervall I_R;
if ( p.is_empty( RP::R))
I_R = Intervall( d.ymin(), d.ymax());
else {
ip = min_max_element( p.begin( RP::R),
p.end( RP::R),
compose2_2(
less< FT >(), Ymax(), Ymax()),
compose2_2(
less< FT >(), Ymin(), Ymin()));
I_R = Intervall( Ymin()(*(ip.second)), Ymax()(*(ip.first)));
CGAL_optimisation_assertion(
I_R.first >= d.ymin() && I_R.second <= d.ymax());
}
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 4
cerr << "one piercing intervalls pierce ..." << endl;
#endif
#if defined(CGAL_PCENTER_WINDOW_TRACE)
Wd.init( -XYSIZE / 5, XYSIZE + XYSIZE / 5, -XYSIZE / 5);
Wd << RED;
copy( f, l, wout);
Wd << GREEN
<< Iso_rectangleC2<FT>( d.min(), d.max())
<< ORANGE
<< build_point( I_B.first, d.ymin())
<< build_point( I_B.second, d.ymin())
<< build_point( d.xmin(), I_L.first)
<< build_point( d.xmin(), I_L.second)
<< build_point( I_T.first, d.ymax())
<< build_point( I_T.second, d.ymax())
<< build_point( d.xmax(), I_R.first)
<< build_point( d.xmax(), I_R.second);
while ( Wd.read_mouse( dummy_x, dummy_y) != -1) {}
#endif
// now try to position the bottom piercing point in each
// of the intervalls formed by S_bt and S_br
// (no need to consider S_bl, since we move from left
// to right and leaving a rectangle won't make piercing easier)
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 4
cerr << "round trip ..." << endl;
#endif
// x coordinate of bottom piercing point:
FT bot( I_B.first);
// first rectangle in s[BL] pierced by bot
// ( ==> predecessor gives an upper bound for lef):
iterator first_pierced_in_BL( p.first_right_of( RP::BL, bot));
// upper bound for y coordinate of left piercing point:
FT lef( min( ymax(*(first_pierced_in_BL - 1)), I_L.second));
// first rectangle in s[BR] pierced by bot
// ( ==> predecessor gives an upper bound for rig):
iterator first_pierced_in_BR( p.first_left_of( RP::BR, bot));
// upper bound for y coordinate of right piercing point:
FT rig( min( ymax(*(first_pierced_in_BR - 1)), I_R.second));
// first rectangle in s[BT] pierced by bot
// ( ==> predecessor gives an upper bound for top):
iterator first_pierced_in_BT( p.first_left_of( RP::BT, bot));
// first rectangle in s[BT] after first_pierced_in_BT
// not pierced by bot ( ==> gives a lower bound for top):
iterator first_unpierced_in_BT( p.first_right_of( RP::BT, bot));
// x coordinate of top piercing point:
FT top;
// first rectangle in s[TL] not pierced by lef
// ( ==> gives an upper bound for top):
iterator first_unpierced_in_TL( p.first_above( RP::TL, lef));
// first rectangle in s[TR] not pierced by rig
// ( ==> gives a lower bound for top):
iterator first_unpierced_in_TR( p.first_above( RP::TR, rig));
// first rectangle in s[LR] not pierced by lef:
iterator first_unpierced_by_lef_in_LR( p.first_above( RP::LR, lef));
// corresponding upper bound for top:
iterator top_upper_bound_by_lef_in_LR(
p.first_above( RP::TL,
min( ymax( *first_unpierced_by_lef_in_LR),
d.ymax())));
// first rectangle in s[LR] not pierced by rig:
iterator first_unpierced_by_rig_in_LR( p.first_above( RP::LR, rig));
// corresponding lower bound for top:
iterator top_lower_bound_by_rig_in_LR(
p.first_above( RP::TR,
min( ymax( *first_unpierced_by_rig_in_LR),
d.ymax())));
// top side of the first rectangle in s[LR]
// ( > d.ymax, iff s[LR] is empty)
FT top_side_of_lr( ymax( *(p.begin( RP::LR))));
CGAL_optimisation_assertion(
p.is_empty( RP::LR) && top_side_of_lr > d.ymax() ||
!p.is_empty( RP::LR) && top_side_of_lr <= d.ymax());
// top side of the
// first rectangle in s[LR] above (not including)
// the line y = top_side_of_lr
// ( possibly > d.ymax())
FT top_side_above_top_side_of_lr(
ymax( *p.first_above( RP::LR,
min( top_side_of_lr, d.ymax()))));
CGAL_optimisation_assertion( top_side_above_top_side_of_lr >= d.ymin());
// right side of the
// first rectangle in s[TL] above (not including)
// the line y = top_side_of_lr
// ( possibly > d.xmax())
FT upper_bound_top_from_slr(
xmax( *p.first_above( RP::TL,
min( top_side_above_top_side_of_lr, d.ymax()))));
CGAL_optimisation_assertion( upper_bound_top_from_slr >= d.xmin());
// left side of the
// first rectangle in s[TR] above (not including)
// the line y = top_side_of_lr
// ( possibly < d.xmin())
FT lower_bound_top_from_slr(
xmin( *p.first_above( RP::TR,
min( top_side_above_top_side_of_lr, d.ymax()))));
CGAL_optimisation_assertion( top_side_above_top_side_of_lr >= d.ymin());
// one-piercing intervall of s[BT]:
Intervall I_BT;
// piercing intervall of s[T] with respect to lef and rig:
Intervall I_TLR;
// make sure, lef and rig are in I_L (I_R resp.):
if ( lef < I_L.first || rig < I_R.first)
goto next_iteration;
for (;;) {
#if defined(CGAL_PCENTER_WINDOW_TRACE)
Wd << RED;
copy( f, l, wout);
Wd << GREEN
<< Iso_rectangleC2<FT>( d.min(), d.max())
<< BLUE
<< build_point( bot, d.ymin()));
cerr << "** show bottom point" << endl;
while ( Wd.read_mouse( dummy_x, dummy_y) != -1) {}
#endif
// ----------------------------------------------------------
// compute subintervall I_BT of top side where s[BT] is pierced
// (this is determined by the choice of bot)
if ( p.begin( RP::BT) == first_pierced_in_BT) {
// bot pierces the first rectangle from s[BT]
// or no rectangle from s[BT] at all
CGAL_optimisation_assertion(
p.is_empty( RP::BT) ||
!(*(first_pierced_in_BT)).has_on_unbounded_side(
build_point( bot, d.ymin())) ||
Xmax()( *first_pierced_in_BT) < bot);
if ( p.end( RP::BT) == first_unpierced_in_BT) {
// bot pierces the last rectangle from s[BT]
// (if s[BT] is not empty)
CGAL_optimisation_assertion(
p.is_empty( RP::BT) ||
!(*(p.end( RP::BT) - 1)).has_on_unbounded_side(
build_point( bot, d.ymin())));
// there is nothing left to pierce:
I_BT = I_T;
} else {
// we have to pierce the first unpierced rectangle
// as well as the last one:
I_BT =
Intervall( max( xmin( *(first_unpierced_in_BT)),
xmin( *(p.end( RP::BT) - 1))),
min( xmax( *(first_unpierced_in_BT)),
xmax( *(p.end( RP::BT) - 1))));
}
} else {
// bot does not pierce the first rectangle from s[BT]:
CGAL_optimisation_assertion(
( *(p.begin( RP::BT))).has_on_unbounded_side(
build_point( bot, d.ymin())));
if ( p.end( RP::BT) != first_unpierced_in_BT) {
// now way to pierce both with a single point:
goto next_iteration;
}
// we have to pierce the first rectangle
// as well as the last unpierced one:
/*
I_BT =
Intervall( max( xmin( *--(first_pierced_in_BT)),
xmin( *(p.begin( RP::BT)))),
min( xmax( *--(first_pierced_in_BT)),
xmax( *(p.begin( RP::BT)))));
*/
I_BT =
Intervall( max( xmin( *(first_pierced_in_BT - 1)),
xmin( *(p.begin( RP::BT)))),
min( xmax( *(first_pierced_in_BT - 1)),
xmax( *(p.begin( RP::BT)))));
}
// ----------------------------------------------------------
// test if the intersection of I_T and I_BT is not empty
// and contains a point that pierces the remaining rectangles
// from s[TL] and s[TR]:
I_BT.first = max( I_T.first, I_BT.first);
I_BT.second = min( I_T.second, I_BT.second);
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 4
cerr << "update bounds for top" << endl;
#endif
first_unpierced_in_TL =
p.first_above_downwards( RP::TL, lef, first_unpierced_in_TL);
first_unpierced_in_TR =
p.first_above_upwards( RP::TR, rig, first_unpierced_in_TR);
I_TLR = Intervall( xmin( *first_unpierced_in_TR),
xmax( *first_unpierced_in_TL));
I_TLR.first = max( I_BT.first, I_TLR.first);
I_TLR.second = min( I_BT.second, I_TLR.second);
if ( I_TLR.first > I_TLR.second)
goto next_iteration;
// ----------------------------------------------------------
// to pierce s[LR] there are at most two possible ways:
// the lowest rectangle of s[LR] can either be pierced by
// Point_2( ... lef ...) or Point_2( ... rig ...)
// so we just try both:
if ( !p.is_empty( RP::LR)) {
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 4
cerr << "update bounds for s[LR]" << endl;
#endif
first_unpierced_by_lef_in_LR =
p.first_above_downwards( RP::LR, lef, first_unpierced_by_lef_in_LR);
top_upper_bound_by_lef_in_LR =
p.first_above_downwards( RP::TL,
ymax( *first_unpierced_by_lef_in_LR),
top_upper_bound_by_lef_in_LR);
first_unpierced_by_rig_in_LR =
p.first_above_upwards( RP::LR, rig, first_unpierced_by_rig_in_LR);
top_lower_bound_by_rig_in_LR =
p.first_above_upwards( RP::TR,
ymax( *first_unpierced_by_rig_in_LR),
top_lower_bound_by_rig_in_LR);
// ------------------------------------------------------
// try to pierce the first rectangle from s[LR] with lef:
if ( lef >= ymin( *p.begin( RP::LR)) &&
I_L.first <= ymax( *p.begin( RP::LR))) {
FT lef_save( lef);
FT rig_save( rig);
for (;;) {
// top side of the first rectangle in s[LR] not pierced by lef:
FT first_unpierced;
// its bound for top:
FT top_bound_first_unpierced;
if ( lef > top_side_of_lr) {
// lef has to be moved down
// in order to pierce the first rectangle from s[LR]:
lef = top_side_of_lr;
I_TLR.second = upper_bound_top_from_slr;
if ( I_TLR.first > I_TLR.second)
// cannot move down lef without making it impossible
// to place the top piercing point
break;
first_unpierced = top_side_above_top_side_of_lr;
top_bound_first_unpierced = upper_bound_top_from_slr;
} else {
// no need to move lef down
first_unpierced = ymax( *first_unpierced_by_lef_in_LR);
top_bound_first_unpierced =
Xmax()( *top_upper_bound_by_lef_in_LR);
}
// try to position rig:
if ( rig > first_unpierced) {
// rig has to be moved down
rig = first_unpierced;
if ( I_R.first > rig ||
top_bound_first_unpierced > I_TLR.second)
// cannot move down rig without either leaving I_R
// or making it impossible
// to place the top piercing point
break;
} // if ( rig > first_unpierced)
// check, if the last rectangle from s[LR] is pierced
// hack: sentinel <=> first_unpierced > d.ymax()
// (in this case we do not have to check anything
if ( first_unpierced <= d.ymax() &&
ymin( *(p.end( RP::LR) - 1)) > rig)
break;
top = I_TLR.second;
// ----------------------------------------------------------
// We finally found a piercing set!
*o++ = build_point( bot, d.ymin());
*o++ = build_point( top, d.ymax());
*o++ = build_point( d.xmin(), lef);
*o++ = build_point( d.xmax(), rig);
#if defined(CGAL_PCENTER_WINDOW_TRACE)
Wd << RED;
copy( f, l, wout);
Wd << GREEN
<< Iso_rectangle_2< R >( d.min(), d.max())
<< BLACK
<< build_point( bot, d.ymin())
<< build_point( top, d.ymax())
<< build_point( d.xmin(), lef)
<< build_point( d.xmax(), rig);
cerr << "** show piercing set" << endl;
while ( Wd.read_mouse( dummy_x, dummy_y) != -1) {}
#endif
ok = true;
return o;
} // for (;;)
lef = lef_save;
rig = rig_save;
} // if ( lef >= ymin( *p.begin( RP::LR)) && ... )
// ------------------------------------------------------
// try to pierce the first rectangle from s[LR] with rig:
if ( rig >= ymin( *p.begin( RP::LR)) &&
I_R.first <= ymax( *p.begin( RP::LR))) {
// top side of the first rectangle in s[LR] not pierced by rig:
FT first_unpierced;
// its bound for top:
FT top_bound_first_unpierced;
if ( rig > top_side_of_lr) {
// rig has to be moved down
// in order to pierce the first rectangle from s[LR]:
rig = top_side_of_lr;
I_TLR.first = lower_bound_top_from_slr;
if ( I_TLR.first > I_TLR.second)
// cannot move down rig without making it impossible
// to place the top piercing point
goto next_iteration;
first_unpierced = top_side_above_top_side_of_lr;
top_bound_first_unpierced = lower_bound_top_from_slr;
} else {
// no need to move rig down
first_unpierced = ymax( *first_unpierced_by_rig_in_LR);
top_bound_first_unpierced =
Xmin()( *top_lower_bound_by_rig_in_LR);
}
// try to position lef:
if ( lef > first_unpierced) {
// lef has to be moved down
lef = first_unpierced;
if ( I_L.first > lef ||
top_bound_first_unpierced < I_TLR.first)
// cannot move down lef without either leaving I_L
// or making it impossible
// to place the top piercing point
goto next_iteration;
} // if ( lef > first_unpierced)
// check, if the last rectangle from s[LR] is pierced
// hack: sentinel <=> first_unpierced > d.ymax()
// (in this case we do not have to check anything
if ( first_unpierced <= d.ymax() &&
ymin( *(p.end( RP::LR) - 1)) > lef)
goto next_iteration;
top = I_TLR.first;
} // if ( rig >= ymin( *p.begin( RP::LR)) && ... )
} // if ( !p.is_empty( RP::LR))
else
top = I_TLR.first;
// ----------------------------------------------------------
// We finally found a piercing set!
*o++ = build_point( bot, d.ymin());
*o++ = build_point( top, d.ymax());
*o++ = build_point( d.xmin(), lef);
*o++ = build_point( d.xmax(), rig);
#if defined(CGAL_PCENTER_WINDOW_TRACE)
Wd << RED;
copy( f, l, wout);
Wd << GREEN
<< Iso_rectangle_2< R >( d.min(), d.max())
<< BLACK
<< build_point( bot, d.ymin())
<< build_point( top, d.ymax())
<< build_point( d.xmin(), lef)
<< build_point( d.xmax(), rig);
cerr << "** show piercing set" << endl;
while ( Wd.read_mouse( dummy_x, dummy_y) != -1) {}
#endif
ok = true;
return o;
// ----------------------------------------------------------
// test the next intervall:
next_iteration:
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 4
cerr << "!!! next iteration" << endl;
#endif
if ( xmin( *(first_pierced_in_BR - 1)) <
xmin( *(first_pierced_in_BT - 1)))
bot = xmin( *(--first_pierced_in_BR));
else
bot = xmin( *(--first_pierced_in_BT));
if ( bot > I_B.second)
break;
CGAL_optimisation_assertion(
first_pierced_in_BR >= p.begin( RP::BR) &&
first_pierced_in_BT >= p.begin( RP::BT));
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 4
cerr << "compute rig" << endl;
#endif
CGAL_optimisation_assertion( first_pierced_in_BR >= p.begin( RP::BR));
rig = min( ymax( *(first_pierced_in_BR - 1)), I_R.second);
// if that does not fit together with I_R --> continue
// !!! in case of lef we can abort here
if ( rig < I_R.first)
goto next_iteration;
// update first_pierced_in_BL:
first_pierced_in_BL =
p.first_right_of( RP::BL, bot, first_pierced_in_BL);
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 4
cerr << "compute lef" << endl;
#endif
CGAL_optimisation_assertion( first_pierced_in_BL >= p.begin( RP::BL));
lef = min( ymax( *(first_pierced_in_BL - 1)), I_L.second);
// if that does not fit together with I_L --> continue
// !!! in case of lef we can abort here
if ( lef < I_L.first)
goto next_iteration;
#if defined(CGAL_PCENTER_WINDOW_TRACE)
Wd << BLUE
<< build_point( d.xmin(), lef)
<< build_point( d.xmax(), rig);
cerr << "** show lef and rig" << endl;
while ( Wd.read_mouse( dummy_x, dummy_y) != -1) {}
#endif
#if defined(CGAL_PCENTER_TRACE) && CGAL_PCENTER_TRACE <= 4
cerr << "update bounds for s[BT]" << endl;
#endif
first_unpierced_in_BT =
p.first_right_of( RP::BT, bot, first_unpierced_in_BT);
} // for (;;)
} // if ( p.is_empty( RP::NO))
ok = false;
return o;
} // four_pierce_rectangles( f, l, d, p, o, ok)
template < class _Traits >
class Two_piercing_algorithm {
public:
// don't touch these typedefs ;)
// Traits is not enough for sunpro ...
typedef _Traits Traits;
typedef typename _Traits::Iso_rectangle_2 Iso_rectangle_2;
typedef typename _Traits::Point_2 Point_2;
typedef typename _Traits::FT FT;
typedef typename _Traits::X X;
typedef typename _Traits::Y Y;
typedef typename _Traits::Xmin Xmin;
typedef typename _Traits::Xmax Xmax;
typedef typename _Traits::Ymin Ymin;
typedef typename _Traits::Ymax Ymax;
typedef typename _Traits::Build_point Build_point;
typedef typename _Traits::Build_rectangle Build_rectangle;
#ifndef CGAL_CFG_NO_MEMBER_TEMPLATES
template < class RandomAccessIC, class OutputIterator >
#else
typedef vector< Iso_rectangle_2 >::iterator
RandomAccessIC;
typedef back_insert_iterator< vector< Point_2 > >
OutputIterator;
Wastebasket< Point_2 >
operator()(
RandomAccessIC f,
RandomAccessIC l,
Wastebasket< Point_2 > o,
bool& ok)
{
return two_pierce_rectangles( f, l, o, ok, Traits());
}
#endif // CGAL_CFG_NO_MEMBER_TEMPLATES
OutputIterator
operator()(
RandomAccessIC f,
RandomAccessIC l,
OutputIterator o,
bool& ok)
{
return two_pierce_rectangles( f, l, o, ok, Traits());
}
#ifndef CGAL_CFG_NO_MEMBER_TEMPLATES
template < class RandomAccessIC, class OutputIterator >
#endif // CGAL_CFG_NO_MEMBER_TEMPLATES
OutputIterator
operator()(
RandomAccessIC f,
RandomAccessIC l,
const _Loc_domain< Traits, RandomAccessIC >& d,
OutputIterator o,
bool& ok)
{ return two_pierce_rectangles( f, l, d, o, ok); }
}; // class Two_piercing_algorithm
template < class _Traits >
class Three_piercing_algorithm {
public:
// don't touch these typedefs ;)
// Traits is not enough for sunpro ...
typedef _Traits Traits;
typedef typename _Traits::Iso_rectangle_2 Iso_rectangle_2;
typedef typename _Traits::Point_2 Point_2;
typedef typename _Traits::FT FT;
typedef typename _Traits::X X;
typedef typename _Traits::Y Y;
typedef typename _Traits::Xmin Xmin;
typedef typename _Traits::Xmax Xmax;
typedef typename _Traits::Ymin Ymin;
typedef typename _Traits::Ymax Ymax;
typedef typename _Traits::Build_point Build_point;
typedef typename _Traits::Build_rectangle Build_rectangle;
#ifndef CGAL_CFG_NO_MEMBER_TEMPLATES
template < class RandomAccessIC, class OutputIterator >
#else
typedef vector< Iso_rectangle_2 >::iterator
RandomAccessIC;
typedef back_insert_iterator< vector< Point_2 > >
OutputIterator;
Wastebasket< Point_2 >
operator()(
RandomAccessIC f,
RandomAccessIC l,
Wastebasket< Point_2 > o,
bool& ok)
{
return three_pierce_rectangles( f, l, o, ok, Traits());
}
#endif // CGAL_CFG_NO_MEMBER_TEMPLATES
OutputIterator
operator()(
RandomAccessIC f,
RandomAccessIC l,
OutputIterator o,
bool& ok)
{
return three_pierce_rectangles( f, l, o, ok, Traits());
}
#ifndef CGAL_CFG_NO_MEMBER_TEMPLATES
template < class RandomAccessIC, class OutputIterator >
#endif // CGAL_CFG_NO_MEMBER_TEMPLATES
OutputIterator
operator()(
RandomAccessIC f,
RandomAccessIC l,
const _Loc_domain< Traits, RandomAccessIC >& d,
OutputIterator o,
bool& ok)
{ return three_pierce_rectangles( f, l, d, o, ok); }
}; // class Three_piercing_algorithm
template < class _Traits >
class Four_piercing_algorithm {
public:
// don't touch these typedefs ;)
// Traits is not enough for sunpro ...
typedef _Traits Traits;
typedef typename _Traits::Iso_rectangle_2 Iso_rectangle_2;
typedef typename _Traits::Point_2 Point_2;
typedef typename _Traits::FT FT;
typedef typename _Traits::X X;
typedef typename _Traits::Y Y;
typedef typename _Traits::Xmin Xmin;
typedef typename _Traits::Xmax Xmax;
typedef typename _Traits::Ymin Ymin;
typedef typename _Traits::Ymax Ymax;
typedef typename _Traits::Build_point Build_point;
typedef typename _Traits::Build_rectangle Build_rectangle;
#ifndef CGAL_CFG_NO_MEMBER_TEMPLATES
template < class RandomAccessIC, class OutputIterator >
#else
typedef vector< Iso_rectangle_2 >::iterator
RandomAccessIC;
typedef back_insert_iterator< vector< Point_2 > >
OutputIterator;
Wastebasket< Point_2 >
operator()(
RandomAccessIC f,
RandomAccessIC l,
Wastebasket< Point_2 > o,
bool& ok)
{
return four_pierce_rectangles( f, l, o, ok, Traits());
}
#endif // CGAL_CFG_NO_MEMBER_TEMPLATES
OutputIterator
operator()(
RandomAccessIC f,
RandomAccessIC l,
OutputIterator o,
bool& ok)
{
return four_pierce_rectangles( f, l, o, ok, Traits());
}
#ifndef CGAL_CFG_NO_MEMBER_TEMPLATES
template < class RandomAccessIC, class OutputIterator >
#endif // CGAL_CFG_NO_MEMBER_TEMPLATES
OutputIterator
operator()(
RandomAccessIC f,
RandomAccessIC l,
const _Loc_domain< Traits, RandomAccessIC >& d,
OutputIterator o,
bool& ok)
{ return four_pierce_rectangles( f, l, d, o, ok); }
}; // class Four_piercing_algorithm
CGAL_END_NAMESPACE
#endif // ! (CGAL_PIERCE_RECTANGLES_2_H)
// ----------------------------------------------------------------------------
// ** EOF
// ----------------------------------------------------------------------------