dust3d/thirdparty/cgal/CGAL-4.13/include/CGAL/pierce_rectangles_2.h

1034 lines
33 KiB
C++
Executable File

// Copyright (c) 1998-2003 ETH Zurich (Switzerland).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// 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.
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0+
//
//
// Author(s) : Michael Hoffmann <hoffmann@inf.ethz.ch>
#ifndef CGAL_PIERCE_RECTANGLES_2_H
#define CGAL_PIERCE_RECTANGLES_2_H 1
#include <CGAL/license/Bounding_volumes.h>
#include <CGAL/Optimisation/assertions.h>
#include <CGAL/circulator.h>
#include <CGAL/algorithm.h>
#include <algorithm>
#include <iterator>
#include <vector>
#include <boost/bind.hpp>
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4355) // complaint about using 'this' to
#endif // initialize a member
namespace CGAL {
//!!! STL-extensions
template < class T >
struct Wastebasket {
typedef std::output_iterator_tag iterator_category;
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 Traits_ >
struct Loc_domain {
// ---------------------------------------------
// types:
typedef Traits_ Traits;
typedef typename Traits::FT FT;
typedef typename Traits::Point_2 Point_2;
typedef std::vector< Point_2 > Container;
typedef typename Container::iterator Iterator;
typedef typename Container::const_iterator Citerator;
typedef typename Container::reverse_iterator Riterator;
typedef typename Container::const_reference Creference;
typedef typename Container::size_type size_type;
// ---------------------------------------------
// creation:
void
update(int j, Citerator i)
{
CGAL_optimisation_precondition(j >= 0 && j < 4);
if (j < 2)
if (j == 0) {
if (traits.less_x_2_object()(*i, minx)) minx = *i;
if (traits.less_y_2_object()(*i, miny)) miny = *i;
}
else {
if (traits.less_y_2_object()(*i, miny)) miny = *i;
if (traits.less_x_2_object()(maxx, *i)) maxx = *i;
}
else
if (j == 2) {
if (traits.less_x_2_object()(maxx, *i)) maxx = *i;
if (traits.less_y_2_object()(maxy, *i)) maxy = *i;
}
else {
if (traits.less_y_2_object()(maxy, *i)) maxy = *i;
if (traits.less_x_2_object()(*i, minx)) minx = *i;
}
}
template < class InputIC >
Loc_domain(InputIC b, InputIC e, Traits t)
: pts(b, e),
end_(pts.end()),
minx(pts.front()),
miny(pts.front()),
maxx(pts.front()),
maxy(pts.front()),
traits(t)
{
CGAL_optimisation_precondition(b != e);
Iterator i = pts.begin();
CGAL_optimisation_assertion(i != pts.end());
while (++i != pts.end()) {
if (traits.less_x_2_object()(*i, minx)) minx = *i;
if (traits.less_x_2_object()(maxx, *i)) maxx = *i;
if (traits.less_y_2_object()(*i, miny)) miny = *i;
if (traits.less_y_2_object()(maxy, *i)) maxy = *i;
}
}
// ---------------------------------------------
// access operations:
Point_2
operator[](int i) const
// return corner points (0 <-> bottom-left, 1 <-> bottom-right)
{
CGAL_optimisation_precondition(i >= 0 && i < 4);
if (i == 0)
return traits.construct_point_2_above_right_implicit_point_2_object()(
minx, miny, r);
else if (i == 1)
return traits.construct_point_2_above_left_implicit_point_2_object()(
maxx, miny, r);
else if (i == 2)
return traits.construct_point_2_below_left_implicit_point_2_object()(
maxx, maxy, r);
return traits.construct_point_2_below_right_implicit_point_2_object()(
minx, maxy, r);
}
Point_2
extreme(int i) const
// return extreme points (0 <-> left, 1 <-> bottom)
{
CGAL_optimisation_precondition(i >= 0 && i < 4);
if (i > 1) return i == 2 ? maxx : maxy;
return i == 0 ? minx : miny;
}
Point_2&
extreme(int i)
// return extreme points (0 <-> left, 1 <-> bottom)
{
CGAL_optimisation_precondition(i >= 0 && i < 4);
if (i > 1) return i == 2 ? maxx : maxy;
return i == 0 ? minx : miny;
}
Citerator begin() const { return pts.begin(); }
Iterator begin() { return pts.begin(); }
#ifndef _MSC_VER
Citerator end() const { return end_; }
#else
// Yet another really great MSVC feature ...
// without that static_cast to itself it does not compile :-)
Citerator end() const { return static_cast<Iterator>(end_); }
#endif
Iterator& end() { return end_; }
Iterator real_end() { return pts.end(); }
bool empty() const { return begin() == end(); }
size_type size() const { return end() - begin(); }
Creference front() const { return pts.front(); }
// ---------------------------------------------
// check operation:
void
check() const {
CGAL_optimisation_expensive_assertion_code(
Iterator i = pts.begin();
do {
CGAL_optimisation_assertion(!traits.less_x_2_object()(*i, minx));
CGAL_optimisation_assertion(!traits.less_x_2_object()(maxx, *i));
CGAL_optimisation_assertion(!traits.less_y_2_object()(*i, miny));
CGAL_optimisation_assertion(!traits.less_y_2_object()(maxy, *i));
} while (++i != end);
)
}
protected:
// points container
Container pts;
// const iterator to past-the-end
Iterator end_;
public:
// actual center radius
FT r;
// (copies of) elements with minimal/maximal x/y coordinate
Point_2 minx, miny, maxx, maxy;
// Traits class
Traits traits;
}; // class Loc_domain
template < class Traits_ >
struct Staircases : public Loc_domain< Traits_ > {
typedef Traits_ Traits;
typedef Loc_domain< Traits > Base;
typedef typename Base::Container Container;
typedef typename Base::Iterator Iterator;
typedef typename Base::Citerator Citerator;
typedef typename Base::Riterator Riterator;
typedef typename Traits::Point_2 Point_2;
typedef typename Traits::FT FT;
typedef std::pair< Point_2, Point_2 > Intervall;
template < class InputIC >
Staircases(InputIC b, InputIC e, Traits t)
: Base(b, e, t),
sorted(this->pts),
xgy(t.signed_x_distance_2_object()(this->maxx, this->minx) >
t.signed_y_distance_2_object()(this->maxy, this->miny))
{
using std::sort;
using std::find_if;
Container& xsort = xgy ? sorted : this->pts;
Container& ysort = xgy ? this->pts : sorted;
// build top-left and bottom-right staircases
sort(ysort.begin(), ysort.end(), this->traits.less_y_2_object());
// bottom-right
Iterator i = ysort.begin();
do {
brstc.push_back(*i++);
i = find_if(i, ysort.end(),
boost::bind(this->traits.less_x_2_object(), brstc.back(), _1));
} while (i != ysort.end());
// top-left
Riterator j = ysort.rbegin();
do {
tlstc.push_back(*j++);
j = find_if(j, ysort.rend(),
boost::bind(this->traits.less_x_2_object(), _1, tlstc.back()));
} while (j != ysort.rend());
// build left-bottom and right-top staircases
sort(xsort.begin(), xsort.end(), this->traits.less_x_2_object());
// left-bottom
i = xsort.begin();
do {
lbstc.push_back(*i++);
i = find_if(i, xsort.end(),
boost::bind(this->traits.less_y_2_object(), _1, lbstc.back()));
} while (i != xsort.end());
// right-top
j = xsort.rbegin();
do {
rtstc.push_back(*j++);
j = find_if(j, xsort.rend(),
boost::bind(this->traits.less_y_2_object(), rtstc.back(), _1));
} while (j != xsort.rend());
} // Staircases(b, e, t)
bool is_middle_empty() const {
//!!! the "middle" point could be precomputed in advance
Citerator i = this->pts.begin();
FT rr = FT(2) * this->r;
do
if (this->traits.signed_x_distance_2_object()(this->maxx, *i) > rr &&
this->traits.signed_x_distance_2_object()(*i, this->minx) > rr &&
this->traits.signed_y_distance_2_object()(*i, this->miny) > rr &&
this->traits.signed_y_distance_2_object()(this->maxy, *i) > rr)
return false;
while (++i != this->pts.end());
return true;
} // is_middle()
bool is_x_greater_y() const { return xgy; }
Citerator tlstc_begin() const { return tlstc.begin(); }
Citerator tlstc_end() const { return tlstc.end(); }
Citerator lbstc_begin() const { return lbstc.begin(); }
Citerator lbstc_end() const { return lbstc.end(); }
Citerator brstc_begin() const { return brstc.begin(); }
Citerator brstc_end() const { return brstc.end(); }
Citerator rtstc_begin() const { return rtstc.begin(); }
Citerator rtstc_end() const { return rtstc.end(); }
Intervall top_intervall() const {
Point_2 p =
this->traits.construct_point_2_above_right_implicit_point_2_object()(
this->minx, this->miny, FT(2) * this->r);
Point_2 q =
this->traits.construct_point_2_above_left_implicit_point_2_object()(
this->maxx, this->miny, FT(2) * this->r);
Citerator i =
min_element_if(
this->pts.begin(), this->pts.end(),
this->traits.less_x_2_object(),
boost::bind(std::logical_and< bool >(),
boost::bind(this->traits.less_x_2_object(), p, _1),
boost::bind(this->traits.less_y_2_object(), p, _1)));
Citerator j =
max_element_if(
this->pts.begin(), this->pts.end(),
this->traits.less_x_2_object(),
boost::bind(std::logical_and< bool >(),
boost::bind(this->traits.less_x_2_object(), _1, q),
boost::bind(this->traits.less_y_2_object(), q, _1)));
return Intervall(i == this->pts.end() ? this->maxx : *i,
j == this->pts.end() ? this->minx : *j);
} // top_intervall()
Intervall bottom_intervall() const {
Point_2 p =
this->traits.construct_point_2_below_right_implicit_point_2_object()(
this->minx, this->maxy, FT(2) * this->r);
Point_2 q =
this->traits.construct_point_2_below_left_implicit_point_2_object()(
this->maxx, this->maxy, FT(2) * this->r);
Citerator i =
min_element_if(
this->pts.begin(), this->pts.end(),
this->traits.less_x_2_object(),
boost::bind(std::logical_and< bool >(),
boost::bind(this->traits.less_x_2_object(), p, _1),
boost::bind(this->traits.less_y_2_object(), _1, p)));
Citerator j =
max_element_if(
this->pts.begin(), this->pts.end(),
this->traits.less_x_2_object(),
boost::bind(std::logical_and< bool >(),
boost::bind(this->traits.less_x_2_object(), _1, q),
boost::bind(this->traits.less_y_2_object(), _1, q)));
return Intervall(i == this->pts.end() ? this->maxx : *i,
j == this->pts.end() ? this->minx : *j);
} // bottom_intervall()
Intervall left_intervall() const {
Point_2 p =
this->traits.construct_point_2_above_left_implicit_point_2_object()(
this->maxx, this->miny, FT(2) * this->r);
Point_2 q =
this->traits.construct_point_2_below_left_implicit_point_2_object()(
this->maxx, this->maxy, FT(2) * this->r);
Citerator i =
min_element_if(
this->pts.begin(), this->pts.end(),
this->traits.less_y_2_object(),
boost::bind(std::logical_and< bool >(),
boost::bind(this->traits.less_x_2_object(), _1, p),
boost::bind(this->traits.less_y_2_object(), p, _1)));
Citerator j =
max_element_if(
this->pts.begin(), this->pts.end(),
this->traits.less_y_2_object(),
boost::bind(std::logical_and< bool >(),
boost::bind(this->traits.less_x_2_object(), _1, q),
boost::bind(this->traits.less_y_2_object(), _1, q)));
return Intervall(i == this->pts.end() ? this->maxy : *i,
j == this->pts.end() ? this->miny : *j);
} // left_intervall()
Intervall right_intervall() const {
Point_2 p =
this->traits.construct_point_2_above_right_implicit_point_2_object()(
this->minx, this->miny, FT(2) * this->r);
Point_2 q =
this->traits.construct_point_2_below_right_implicit_point_2_object()(
this->minx, this->maxy, FT(2) * this->r);
Citerator i =
min_element_if(
this->pts.begin(), this->pts.end(),
this->traits.less_y_2_object(),
boost::bind(std::logical_and< bool >(),
boost::bind(this->traits.less_x_2_object(), p, _1),
boost::bind(this->traits.less_y_2_object(), p, _1)));
Citerator j =
max_element_if(
this->pts.begin(), this->pts.end(),
this->traits.less_y_2_object(),
boost::bind(std::logical_and< bool >(),
boost::bind(this->traits.less_x_2_object(), q, _1),
boost::bind(this->traits.less_y_2_object(), _1, q)));
return Intervall(i == this->pts.end() ? this->maxy : *i,
j == this->pts.end() ? this->miny : *j);
} // right_intervall()
template < class OutputIterator >
OutputIterator shared_intervall(OutputIterator o) const {
if (xgy) {
if (this->traits.signed_y_distance_2_object()(
this->maxy, this->miny) > FT(4) * this->r)
return o;
Point_2 p =
this->traits.construct_point_2_below_right_implicit_point_2_object()(
this->minx, this->maxy, FT(2) * this->r);
Point_2 q =
this->traits.construct_point_2_above_left_implicit_point_2_object()(
this->maxx, this->miny, FT(2) * this->r);
//!!! start with binary search
for (Citerator i = sorted.begin(); i != sorted.end(); ++i)
if (this->traits.less_x_2_object()(p, *i) &&
this->traits.less_x_2_object()(*i, q) &&
!this->traits.less_y_2_object()(*i, p) &&
!this->traits.less_y_2_object()(q, *i))
*o++ = *i;
} else {
if (this->traits.signed_x_distance_2_object()(
this->maxx, this->minx) > FT(4) * this->r)
return o;
Point_2 p =
this->traits.construct_point_2_above_left_implicit_point_2_object()(
this->maxx, this->miny, FT(2) * this->r);
Point_2 q =
this->traits.construct_point_2_below_right_implicit_point_2_object()(
this->minx, this->maxy, FT(2) * this->r);
//!!! start with binary search
for (Citerator i = sorted.begin(); i != sorted.end(); ++i)
if (!this->traits.less_x_2_object()(*i, p) &&
!this->traits.less_x_2_object()(q, *i) &&
this->traits.less_y_2_object()(p, *i) &&
this->traits.less_y_2_object()(*i, q))
*o++ = *i;
}
return o;
} // shared_intervall(o)
private:
Container tlstc, lbstc, brstc, rtstc, sorted;
// exceeds the x-dimension of the location domain its y-dimension?
bool xgy;
};
template < class InputIC, class OutputIterator, class Traits >
inline OutputIterator
two_cover_points(
InputIC f, InputIC l, OutputIterator o, bool& ok, const Traits& t)
{
CGAL_optimisation_precondition(f != l);
// compute location domain:
Loc_domain< Traits > d(f, l, t);
return two_cover_points(d, o, ok, t);
} // two_cover_points(f, l, o, ok, t)
template < class InputIC, class OutputIterator, class Traits >
inline OutputIterator
three_cover_points(
InputIC f, InputIC l, OutputIterator o, bool& ok, const Traits& t)
{
CGAL_optimisation_precondition(f != l);
// compute location domain:
Loc_domain< Traits > d(f, l, t);
return three_cover_points(d, o, ok, t);
} // three_cover_points(f, l, o, ok, t)
template < class InputIC, class OutputIterator, class Traits >
inline OutputIterator
four_cover_points(
InputIC f, InputIC l, OutputIterator o, bool& ok, const Traits& t)
{
CGAL_optimisation_precondition(f != l);
// compute location domain:
Loc_domain< Traits > d(f, l, t);
return four_cover_points(d, o, ok, t);
} // four_cover_points(f, l, o, ok, t)
template < class OutputIterator, class Traits >
OutputIterator
two_cover_points(
const Loc_domain< Traits >& d,
OutputIterator o,
bool& ok)
{
using std::find_if;
using std::less;
typedef typename Traits::FT FT;
typename Traits::Infinity_distance_2 dist =
d.traits.infinity_distance_2_object();
typename Traits::Signed_infinity_distance_2 sdist =
d.traits.signed_infinity_distance_2_object();
if (sdist(d[2], d[0]) <= FT(0)) {
// the location domain is degenerate and [f,l) is one-pierceable
*o++ = d[0];
ok = true;
return o;
}
// check whether {d[0], d[2]} forms a piercing set
if (d.end() ==
find_if(d.begin(),
d.end(),
boost::bind(less<FT>(),
d.r,
boost::bind(Min<FT>(),
boost::bind(dist, d[0], _1),
boost::bind(dist, d[2], _1)))))
{
*o++ = d[0];
*o++ = d[2];
ok = true;
return o;
}
// check whether {d[1], d[3]} forms a piercing set
if (d.end() ==
find_if(d.begin(),
d.end(),
boost::bind(less<FT>(),
d.r,
boost::bind(Min<FT>(),
boost::bind(dist, d[1], _1),
boost::bind(dist, d[3], _1)))))
{
*o++ = d[1];
*o++ = d[3];
ok = true;
return o;
}
// no piercing set exists:
ok = false;
return o;
} // two_cover_points(d, o, ok, t)
template < class OutputIterator, class Traits >
OutputIterator
three_cover_points(
Loc_domain< Traits >& d,
OutputIterator o,
bool& ok)
{
using std::find_if;
using std::less;
using std::iter_swap;
CGAL_optimisation_precondition(!d.empty());
// typedefs:
typedef typename Traits::FT FT;
typedef typename Traits::Point_2 Point_2;
typedef typename Loc_domain< Traits >::Iterator Iterator;
typename Traits::Infinity_distance_2 dist =
d.traits.infinity_distance_2_object();
// test the four corners:
for (int k = 0; k < 4; ++k) {
// extract all points which are close enough to d[k]
Point_2 corner = d[k];
// find first point not covered by the rectangle at d[k]
Iterator i = find_if(d.begin(), d.end(),
boost::bind(less<FT>(), d.r, boost::bind(dist, corner, _1)));
// are all points already covered?
if (i == d.end()) {
CGAL_optimisation_assertion(k == 0);
*o++ = d[0];
ok = true;
return o;
} // if (i == d.end())
// save changing sides of d:
Point_2 save_side1 = d.extreme(k);
Point_2 save_side2 = d.extreme((k+1) % 4);
Iterator save_end = d.end();
// now run through it:
// initialize the two (possibly) changing sides of d
d.extreme(k) = d.extreme((k+1) % 4) = *i;
// is there any point covered?
if (i == d.begin()) {
while (++i != d.end() && dist(corner, *i) > d.r)
d.update(k, i);
d.end() = i;
} else {
// move *i to the begin of pts
iter_swap(i, d.begin());
d.end() = d.begin() + 1;
}
// [d.begin(), d.end()) shall be the range of uncovered points
if (i != save_end)
while (++i != save_end)
if (dist(corner, *i) > d.r) {
d.update(k, i);
iter_swap(i, d.end());
++d.end();
} // if (dist(corner, *i) > d.r)
// check disjoint for two-pierceability:
CGAL_optimisation_expensive_assertion(
save_end == find_if(d.end(), save_end,
boost::bind(less<FT>(), d.r, boost::bind(dist, corner, _1))));
CGAL_optimisation_expensive_assertion(
d.end() == find_if(d.begin(), d.end(),
boost::bind(std::greater_equal<FT>(),
d.r,
boost::bind(dist, corner, _1))));
two_cover_points(d, o, ok);
// restore saved sides of d:
d.extreme(k) = save_side1;
d.extreme((k+1) % 4) = save_side2;
if (ok) {
// does any rectangle contain the corner?
if (d.end() != save_end) {
*o++ = corner;
d.end() = save_end;
}
return o;
} // if (ok)
d.end() = save_end;
} // for (int k = 0; k < 4; ++k)
// no piercing set exists:
ok = false;
return o;
} // three_cover_points(d, o, ok)
} //namespace CGAL
namespace CGAL {
template < class OutputIterator, class Traits >
OutputIterator
four_cover_points(Staircases< Traits >& d, OutputIterator o, bool& ok)
{
using std::less;
using std::iter_swap;
using std::find_if;
using std::back_inserter;
typedef typename Traits::Point_2 Point_2;
typedef typename Traits::FT FT;
typedef typename Traits::Less_x_2 Less_x_2;
typedef typename Traits::Less_y_2 Less_y_2;
typedef typename Traits::Signed_x_distance_2 Signed_x_distance_2;
typedef typename Traits::Signed_y_distance_2 Signed_y_distance_2;
typedef typename Traits::Infinity_distance_2 Infinity_distance_2;
typedef typename Staircases< Traits >::Container Container;
typedef typename Staircases< Traits >::Iterator Iterator;
typedef typename Staircases< Traits >::Citerator Citerator;
typedef typename Staircases< Traits >::Intervall Intervall;
Infinity_distance_2 dist = d.traits.infinity_distance_2_object();
Less_x_2 lessx = d.traits.less_x_2_object();
Less_y_2 lessy = d.traits.less_y_2_object();
Signed_x_distance_2 sdistx = d.traits.signed_x_distance_2_object();
Signed_y_distance_2 sdisty = d.traits.signed_y_distance_2_object();
typename Traits::Construct_point_2_above_right_implicit_point_2
cparip =
d.traits.construct_point_2_above_right_implicit_point_2_object();
typename Traits::Construct_point_2_above_left_implicit_point_2
cpalip =
d.traits.construct_point_2_above_left_implicit_point_2_object();
typename Traits::Construct_point_2_below_right_implicit_point_2
cpbrip =
d.traits.construct_point_2_below_right_implicit_point_2_object();
// test the four corners:
for (int j = 0; j < 5; ++j) {
const int k = j < 4 ? j : 3;
// extract all points which are close enough to this point
Point_2 corner = d[k];
if (j >= 3) {
if (j == 3) {
Citerator i = d.tlstc_begin();
while (sdistx(*i, d.minx) > FT(2) * d.r)
++i;
corner = cpbrip(d.minx, *i, d.r);
} else {
Citerator i = d.tlstc_end();
while (sdisty(d.maxy, *--i) > FT(2) * d.r) {}
corner = cpbrip(*i, d.maxy, d.r);
}
}
// find first point not covered by the rectangle at d[k]
Iterator i = find_if(d.begin(), d.end(),
boost::bind(less<FT>(), d.r, boost::bind(dist, corner, _1)));
// are all points already covered?
if (i == d.end()) {
CGAL_optimisation_assertion(k == 0);
*o++ = d[0];
ok = true;
return o;
} // if (i == d.end())
// save changing sides of d:
Point_2 save_side1 = d.extreme(k);
Point_2 save_side2 = d.extreme((k+1) % 4);
Iterator save_end = d.end();
// now run through it:
// initialize the two (possibly) changing sides of d
d.extreme(k) = d.extreme((k+1) % 4) = *i;
// is there any point covered?
if (i == d.begin()) {
while (++i != d.end() && dist(corner, *i) > d.r)
d.update(k, i);
d.end() = i;
} else {
// move *i to the begin of pts
iter_swap(i, d.begin());
d.end() = d.begin() + 1;
}
// [d.begin(), d.end()) shall be the range of uncovered points
if (i != save_end)
while (++i != save_end)
if (dist(corner, *i) > d.r) {
d.update(k, i);
iter_swap(i, d.end());
++d.end();
} // if (dist(corner, *i) > d.r)
// check disjoint for two-pierceability:
CGAL_optimisation_expensive_assertion(
save_end == find_if(d.end(), save_end,
boost::bind(less<FT>(), d.r, boost::bind(dist, corner, _1))));
CGAL_optimisation_expensive_assertion(
d.end() == find_if(d.begin(), d.end(),
boost::bind(std::greater_equal<FT>(),
d.r,
boost::bind(dist, corner, _1))));
three_cover_points(d, o, ok);
// restore saved sides of d:
d.extreme(k) = save_side1;
d.extreme((k+1) % 4) = save_side2;
if (ok) {
// does any rectangle contain the corner?
if (d.end() != save_end) {
*o++ = corner;
d.end() = save_end;
}
return o;
} // if (ok)
d.end() = save_end;
} // for (int k = 0; k < 4; ++k)
// test if four covering rectangles can be placed
// on the boundary of d, one on each side
// if there is any point that cannot be covered in this way, stop here
if (d.is_middle_empty()) {
// 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)
Intervall top_i = d.top_intervall();
Intervall left_i = d.left_intervall();
Intervall bottom_i = d.bottom_intervall();
Intervall right_i = d.right_intervall();
Container share;
d.shared_intervall(back_inserter(share));
Citerator shf = share.end();
Citerator shl = share.end();
Citerator tl = d.tlstc_begin();
Citerator lb = d.lbstc_begin();
Citerator br = d.brstc_begin();
Citerator rt = d.rtstc_begin();
// make sure the top intervall is covered (left endpoint)
// (it might be that top_i.first determines the placement of
// the top square)
Point_2 top = top_i.first;
if (lessx(top, *tl))
while (++tl != d.tlstc_end() && !lessx(*tl, top)) {}
else
top = *tl++;
if (tl != d.tlstc_end()) {
for (;;) {
// make sure the top intervall is covered (right endpoint)
if (sdistx(top_i.second, top) > FT(2) * d.r)
break;
// compute position of left square
Point_2 left = lessy(left_i.second, *tl) ? *tl : left_i.second;
// make sure the left intervall is covered
if (sdisty(left, left_i.first) <= FT(2) * d.r) {
// compute position of bottom square
while (lb != d.lbstc_end() && sdisty(left, *lb) <= FT(2) * d.r)
++lb;
// has the left square reached the bottom-left corner?
if (lb == d.lbstc_end())
break;
Point_2 bottom = lessx(bottom_i.first, *lb) ? bottom_i.first : *lb;
// check the shared x-intervall
if (!share.empty() && d.is_x_greater_y()) {
// compute position of top in share
#ifndef _MSC_VER
while (shf != share.begin() && !lessx(*(shf - 1), top))
#else
while (shf != Citerator(share.begin()) &&
!lessx(*(shf - 1), top))
#endif
--shf;
#ifndef _MSC_VER
while (shl != share.begin() &&
#else
while (shl != Citerator(share.begin()) &&
#endif
sdistx(*(shl - 1), top) > FT(2) * d.r)
--shl;
// make sure shared intervall is covered (left endpoint)
#ifndef _MSC_VER
if ((shf != share.begin() || shl == share.end()) &&
lessx(share.front(), bottom))
bottom = share.front();
else if (shl != share.end() && lessx(*shl, bottom))
bottom = *shl;
#else
if ((shf != Citerator(share.begin()) ||
shl == Citerator(share.end())) &&
lessx(share.front(), bottom))
bottom = share.front();
else if (shl != Citerator(share.end()) && lessx(*shl, bottom))
bottom = *shl;
#endif
}
// make sure the bottom and the shared intervall (right endpoint)
// are covered
#ifndef _MSC_VER
if (sdistx(bottom_i.second, bottom) <= FT(2) * d.r &&
(!d.is_x_greater_y() ||
((shl == share.end() ||
sdistx(share.back(), bottom) <= FT(2) * d.r) &&
(shf == share.begin() ||
sdistx(*(shf - 1), bottom) <= FT(2) * d.r))))
#else
if (sdistx(bottom_i.second, bottom) <= FT(2) * d.r &&
((!d.is_x_greater_y() ||
(shl == Citerator(share.end()) ||
sdistx(share.back(), bottom) <= FT(2) * d.r) &&
(shf == Citerator(share.begin()) ||
sdistx(*(shf - 1), bottom) <= FT(2) * d.r))))
#endif
{
// compute position of right square
while (br != d.brstc_end() && sdistx(*br, bottom) <= FT(2) * d.r)
++br;
// has the bottom square reached the bottom-right corner?
if (br == d.brstc_end())
break;
Point_2 right = lessy(right_i.first, *br) ? right_i.first : *br;
// check the shared y-intervall
if (!share.empty() && !d.is_x_greater_y()) {
// compute position of left in share
#ifndef _MSC_VER
while (shf != share.begin() &&
sdisty(left, *(shf - 1)) <= FT(2) * d.r)
#else
while (shf != Citerator(share.begin()) &&
sdisty(left, *(shf - 1)) <= FT(2) * d.r)
#endif
--shf;
#ifndef _MSC_VER
while (shl != share.begin() &&
#else
while (shl != Citerator(share.begin()) &&
#endif
lessy(left, *(shl - 1)))
--shl;
// make sure shared intervall is covered (bottom endpoint)
#ifndef _MSC_VER
if ((shf != share.begin() || shl == share.end()) &&
lessy(share.front(), right))
right = share.front();
else if (shl != share.end() && lessy(*shl, right))
right = *shl;
#else
if ((shf != Citerator(share.begin()) ||
shl == Citerator(share.end())) &&
lessy(share.front(), right))
right = share.front();
else if (shl != Citerator(share.end()) && lessy(*shl, right))
right = *shl;
#endif
}
// make sure the right intervall and the shared intervall
// (top endpoint) are covered
#ifndef _MSC_VER
if (sdisty(right_i.second, right) <= FT(2) * d.r &&
(d.is_x_greater_y() ||
((shl == share.end() ||
sdisty(share.back(), right) <= FT(2) * d.r) &&
(shf == share.begin() ||
sdisty(*(shf - 1), right) <= FT(2) * d.r))))
#else
if (sdisty(right_i.second, right) <= FT(2) * d.r &&
(d.is_x_greater_y() ||
((shl == Citerator(share.end()) ||
sdisty(share.back(), right) <= FT(2) * d.r) &&
(shf == Citerator(share.begin()) ||
sdisty(*(shf - 1), right) <= FT(2) * d.r))))
#endif
{
// compute right bound for top square
while (rt != d.rtstc_end() &&
sdisty(*rt, right) <= FT(2) * d.r)
++rt;
// has the right square reached the top-right corner?
if (rt == d.rtstc_end())
break;
// Finally: Do we have a covering?
if (sdistx(*rt, top) <= FT(2) * d.r) {
*o++ = cpbrip(d.minx, left, d.r);
*o++ = cparip(bottom, d.miny, d.r);
*o++ = cpalip(d.maxx, right, d.r);
*o++ = cpbrip(top, d.maxy, d.r);
ok = true;
return o;
} // if (covering)
} // if (sdisty(right_i.second, right) <= FT(2) * d.r)
} // if (bottom and shared intervall are covered)
} // if (sdisty(left, left_i.first) <= FT(2) * d.r)
top = *tl;
if (!lessy(left_i.second, *tl) || ++tl == d.tlstc_end() ||
lessx(bottom_i.first, *lb) || lessy(right_i.first, *br))
break;
} // for (;;)
} // if (tl != d.tlstc_end())
} // if (!d.is_middle_empty())
ok = false;
return o;
} // four_cover_points(d, o, ok)
struct Two_covering_algorithm {
template < class Traits, class OutputIterator >
OutputIterator
operator()(Staircases< Traits >& d,
OutputIterator o,
bool& ok) const
{ return two_cover_points(d, o, ok); }
}; // class Two_covering_algorithm
struct Three_covering_algorithm {
template < class Traits, class OutputIterator >
OutputIterator
operator()(Staircases< Traits >& d,
OutputIterator o,
bool& ok) const
{ return three_cover_points(d, o, ok); }
}; // class Three_covering_algorithm
struct Four_covering_algorithm {
template < class Traits, class OutputIterator >
OutputIterator
operator()(Staircases< Traits >& d,
OutputIterator o,
bool& ok) const
{ return four_cover_points(d, o, ok); }
}; // class Four_covering_algorithm
} //namespace CGAL
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
#endif // ! (CGAL_PIERCE_RECTANGLES_2_H)