Initial work for G-code sender and more intensive usage of Boost

This commit is contained in:
Alessandro Ranellucci 2014-11-26 22:30:25 +01:00
parent 43cbad8867
commit 11dd67ab34
1649 changed files with 1860 additions and 1642 deletions

View file

@ -0,0 +1,448 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_BOOLEAN_OP_HPP
#define BOOST_POLYGON_BOOLEAN_OP_HPP
namespace boost { namespace polygon{
namespace boolean_op {
//BooleanOp is the generic boolean operation scanline algorithm that provides
//all the simple boolean set operations on manhattan data. By templatizing
//the intersection count of the input and algorithm internals it is extensible
//to multi-layer scans, properties and other advanced scanline operations above
//and beyond simple booleans.
//T must cast to int
template <class T, typename Unit>
class BooleanOp {
public:
typedef std::map<Unit, T> ScanData;
typedef std::pair<Unit, T> ElementType;
protected:
ScanData scanData_;
typename ScanData::iterator nextItr_;
T nullT_;
public:
inline BooleanOp () : scanData_(), nextItr_(), nullT_() { nextItr_ = scanData_.end(); nullT_ = 0; }
inline BooleanOp (T nullT) : scanData_(), nextItr_(), nullT_(nullT) { nextItr_ = scanData_.end(); }
inline BooleanOp (const BooleanOp& that) : scanData_(that.scanData_), nextItr_(),
nullT_(that.nullT_) { nextItr_ = scanData_.begin(); }
inline BooleanOp& operator=(const BooleanOp& that);
//moves scanline forward
inline void advanceScan() { nextItr_ = scanData_.begin(); }
//proceses the given interval and T data
//appends output edges to cT
template <class cT>
inline void processInterval(cT& outputContainer, interval_data<Unit> ivl, T deltaCount);
private:
inline typename ScanData::iterator lookup_(Unit pos){
if(nextItr_ != scanData_.end() && nextItr_->first >= pos) {
return nextItr_;
}
return nextItr_ = scanData_.lower_bound(pos);
}
inline typename ScanData::iterator insert_(Unit pos, T count){
return nextItr_ = scanData_.insert(nextItr_, ElementType(pos, count));
}
template <class cT>
inline void evaluateInterval_(cT& outputContainer, interval_data<Unit> ivl, T beforeCount, T afterCount);
};
class BinaryAnd {
public:
inline BinaryAnd() {}
inline bool operator()(int a, int b) { return (a > 0) & (b > 0); }
};
class BinaryOr {
public:
inline BinaryOr() {}
inline bool operator()(int a, int b) { return (a > 0) | (b > 0); }
};
class BinaryNot {
public:
inline BinaryNot() {}
inline bool operator()(int a, int b) { return (a > 0) & !(b > 0); }
};
class BinaryXor {
public:
inline BinaryXor() {}
inline bool operator()(int a, int b) { return (a > 0) ^ (b > 0); }
};
//BinaryCount is an array of two deltaCounts coming from two different layers
//of scan event data. It is the merged count of the two suitable for consumption
//as the template argument of the BooleanOp algorithm because BinaryCount casts to int.
//T is a binary functor object that evaluates the array of counts and returns a logical
//result of some operation on those values.
//BinaryCount supports many of the operators that work with int, particularly the
//binary operators, but cannot support less than or increment.
template <class T>
class BinaryCount {
public:
inline BinaryCount()
#ifndef BOOST_POLYGON_MSVC
: counts_()
#endif
{ counts_[0] = counts_[1] = 0; }
// constructs from two integers
inline BinaryCount(int countL, int countR)
#ifndef BOOST_POLYGON_MSVC
: counts_()
#endif
{ counts_[0] = countL, counts_[1] = countR; }
inline BinaryCount& operator=(int count) { counts_[0] = count, counts_[1] = count; return *this; }
inline BinaryCount& operator=(const BinaryCount& that);
inline BinaryCount(const BinaryCount& that)
#ifndef BOOST_POLYGON_MSVC
: counts_()
#endif
{ *this = that; }
inline bool operator==(const BinaryCount& that) const;
inline bool operator!=(const BinaryCount& that) const { return !((*this) == that);}
inline BinaryCount& operator+=(const BinaryCount& that);
inline BinaryCount& operator-=(const BinaryCount& that);
inline BinaryCount operator+(const BinaryCount& that) const;
inline BinaryCount operator-(const BinaryCount& that) const;
inline BinaryCount operator-() const;
inline int& operator[](bool index) { return counts_[index]; }
//cast to int operator evaluates data using T binary functor
inline operator int() const { return T()(counts_[0], counts_[1]); }
private:
int counts_[2];
};
class UnaryCount {
public:
inline UnaryCount() : count_(0) {}
// constructs from two integers
inline explicit UnaryCount(int count) : count_(count) {}
inline UnaryCount& operator=(int count) { count_ = count; return *this; }
inline UnaryCount& operator=(const UnaryCount& that) { count_ = that.count_; return *this; }
inline UnaryCount(const UnaryCount& that) : count_(that.count_) {}
inline bool operator==(const UnaryCount& that) const { return count_ == that.count_; }
inline bool operator!=(const UnaryCount& that) const { return !((*this) == that);}
inline UnaryCount& operator+=(const UnaryCount& that) { count_ += that.count_; return *this; }
inline UnaryCount& operator-=(const UnaryCount& that) { count_ -= that.count_; return *this; }
inline UnaryCount operator+(const UnaryCount& that) const { UnaryCount tmp(*this); tmp += that; return tmp; }
inline UnaryCount operator-(const UnaryCount& that) const { UnaryCount tmp(*this); tmp -= that; return tmp; }
inline UnaryCount operator-() const { UnaryCount tmp; return tmp - *this; }
//cast to int operator evaluates data using T binary functor
inline operator int() const { return count_ % 2; }
private:
int count_;
};
template <class T, typename Unit>
inline BooleanOp<T, Unit>& BooleanOp<T, Unit>::operator=(const BooleanOp& that) {
scanData_ = that.scanData_;
nextItr_ = scanData_.begin();
nullT_ = that.nullT_;
return *this;
}
//appends output edges to cT
template <class T, typename Unit>
template <class cT>
inline void BooleanOp<T, Unit>::processInterval(cT& outputContainer, interval_data<Unit> ivl, T deltaCount) {
typename ScanData::iterator lowItr = lookup_(ivl.low());
typename ScanData::iterator highItr = lookup_(ivl.high());
//add interval to scan data if it is past the end
if(lowItr == scanData_.end()) {
lowItr = insert_(ivl.low(), deltaCount);
highItr = insert_(ivl.high(), nullT_);
evaluateInterval_(outputContainer, ivl, nullT_, deltaCount);
return;
}
//ensure that highItr points to the end of the ivl
if(highItr == scanData_.end() || (*highItr).first > ivl.high()) {
T value = nullT_;
if(highItr != scanData_.begin()) {
--highItr;
value = highItr->second;
}
nextItr_ = highItr;
highItr = insert_(ivl.high(), value);
}
//split the low interval if needed
if(lowItr->first > ivl.low()) {
if(lowItr != scanData_.begin()) {
--lowItr;
nextItr_ = lowItr;
lowItr = insert_(ivl.low(), lowItr->second);
} else {
nextItr_ = lowItr;
lowItr = insert_(ivl.low(), nullT_);
}
}
//process scan data intersecting interval
for(typename ScanData::iterator itr = lowItr; itr != highItr; ){
T beforeCount = itr->second;
T afterCount = itr->second += deltaCount;
Unit low = itr->first;
++itr;
Unit high = itr->first;
evaluateInterval_(outputContainer, interval_data<Unit>(low, high), beforeCount, afterCount);
}
//merge the bottom interval with the one below if they have the same count
if(lowItr != scanData_.begin()){
typename ScanData::iterator belowLowItr = lowItr;
--belowLowItr;
if(belowLowItr->second == lowItr->second) {
scanData_.erase(lowItr);
}
}
//merge the top interval with the one above if they have the same count
if(highItr != scanData_.begin()) {
typename ScanData::iterator beforeHighItr = highItr;
--beforeHighItr;
if(beforeHighItr->second == highItr->second) {
scanData_.erase(highItr);
highItr = beforeHighItr;
++highItr;
}
}
nextItr_ = highItr;
}
template <class T, typename Unit>
template <class cT>
inline void BooleanOp<T, Unit>::evaluateInterval_(cT& outputContainer, interval_data<Unit> ivl,
T beforeCount, T afterCount) {
bool before = (int)beforeCount > 0;
bool after = (int)afterCount > 0;
int value = (!before & after) - (before & !after);
if(value) {
outputContainer.insert(outputContainer.end(), std::pair<interval_data<Unit>, int>(ivl, value));
}
}
template <class T>
inline BinaryCount<T>& BinaryCount<T>::operator=(const BinaryCount<T>& that) {
counts_[0] = that.counts_[0];
counts_[1] = that.counts_[1];
return *this;
}
template <class T>
inline bool BinaryCount<T>::operator==(const BinaryCount<T>& that) const {
return counts_[0] == that.counts_[0] &&
counts_[1] == that.counts_[1];
}
template <class T>
inline BinaryCount<T>& BinaryCount<T>::operator+=(const BinaryCount<T>& that) {
counts_[0] += that.counts_[0];
counts_[1] += that.counts_[1];
return *this;
}
template <class T>
inline BinaryCount<T>& BinaryCount<T>::operator-=(const BinaryCount<T>& that) {
counts_[0] += that.counts_[0];
counts_[1] += that.counts_[1];
return *this;
}
template <class T>
inline BinaryCount<T> BinaryCount<T>::operator+(const BinaryCount<T>& that) const {
BinaryCount retVal(*this);
retVal += that;
return retVal;
}
template <class T>
inline BinaryCount<T> BinaryCount<T>::operator-(const BinaryCount<T>& that) const {
BinaryCount retVal(*this);
retVal -= that;
return retVal;
}
template <class T>
inline BinaryCount<T> BinaryCount<T>::operator-() const {
return BinaryCount<T>() - *this;
}
template <class T, typename Unit, typename iterator_type_1, typename iterator_type_2>
inline void applyBooleanBinaryOp(std::vector<std::pair<Unit, std::pair<Unit, int> > >& output,
//const std::vector<std::pair<Unit, std::pair<Unit, int> > >& input1,
//const std::vector<std::pair<Unit, std::pair<Unit, int> > >& input2,
iterator_type_1 itr1, iterator_type_1 itr1_end,
iterator_type_2 itr2, iterator_type_2 itr2_end,
T defaultCount) {
BooleanOp<T, Unit> boolean(defaultCount);
//typename std::vector<std::pair<Unit, std::pair<Unit, int> > >::const_iterator itr1 = input1.begin();
//typename std::vector<std::pair<Unit, std::pair<Unit, int> > >::const_iterator itr2 = input2.begin();
std::vector<std::pair<interval_data<Unit>, int> > container;
//output.reserve((std::max)(input1.size(), input2.size()));
//consider eliminating dependecy on limits with bool flag for initial state
Unit UnitMax = (std::numeric_limits<Unit>::max)();
Unit prevCoord = UnitMax;
Unit prevPosition = UnitMax;
T count(defaultCount);
//define the starting point
if(itr1 != itr1_end) {
prevCoord = (*itr1).first;
prevPosition = (*itr1).second.first;
count[0] += (*itr1).second.second;
}
if(itr2 != itr2_end) {
if((*itr2).first < prevCoord ||
((*itr2).first == prevCoord && (*itr2).second.first < prevPosition)) {
prevCoord = (*itr2).first;
prevPosition = (*itr2).second.first;
count = defaultCount;
count[1] += (*itr2).second.second;
++itr2;
} else if((*itr2).first == prevCoord && (*itr2).second.first == prevPosition) {
count[1] += (*itr2).second.second;
++itr2;
if(itr1 != itr1_end) ++itr1;
} else {
if(itr1 != itr1_end) ++itr1;
}
} else {
if(itr1 != itr1_end) ++itr1;
}
while(itr1 != itr1_end || itr2 != itr2_end) {
Unit curCoord = UnitMax;
Unit curPosition = UnitMax;
T curCount(defaultCount);
if(itr1 != itr1_end) {
curCoord = (*itr1).first;
curPosition = (*itr1).second.first;
curCount[0] += (*itr1).second.second;
}
if(itr2 != itr2_end) {
if((*itr2).first < curCoord ||
((*itr2).first == curCoord && (*itr2).second.first < curPosition)) {
curCoord = (*itr2).first;
curPosition = (*itr2).second.first;
curCount = defaultCount;
curCount[1] += (*itr2).second.second;
++itr2;
} else if((*itr2).first == curCoord && (*itr2).second.first == curPosition) {
curCount[1] += (*itr2).second.second;
++itr2;
if(itr1 != itr1_end) ++itr1;
} else {
if(itr1 != itr1_end) ++itr1;
}
} else {
++itr1;
}
if(prevCoord != curCoord) {
boolean.advanceScan();
prevCoord = curCoord;
prevPosition = curPosition;
count = curCount;
continue;
}
if(curPosition != prevPosition && count != defaultCount) {
interval_data<Unit> ivl(prevPosition, curPosition);
container.clear();
boolean.processInterval(container, ivl, count);
for(std::size_t i = 0; i < container.size(); ++i) {
std::pair<interval_data<Unit>, int>& element = container[i];
if(!output.empty() && output.back().first == prevCoord &&
output.back().second.first == element.first.low() &&
output.back().second.second == element.second * -1) {
output.pop_back();
} else {
output.push_back(std::pair<Unit, std::pair<Unit, int> >(prevCoord, std::pair<Unit, int>(element.first.low(),
element.second)));
}
output.push_back(std::pair<Unit, std::pair<Unit, int> >(prevCoord, std::pair<Unit, int>(element.first.high(),
element.second * -1)));
}
}
prevPosition = curPosition;
count += curCount;
}
}
template <class T, typename Unit>
inline void applyBooleanBinaryOp(std::vector<std::pair<Unit, std::pair<Unit, int> > >& inputOutput,
const std::vector<std::pair<Unit, std::pair<Unit, int> > >& input2,
T defaultCount) {
std::vector<std::pair<Unit, std::pair<Unit, int> > > output;
applyBooleanBinaryOp(output, inputOutput, input2, defaultCount);
if(output.size() < inputOutput.size() / 2) {
inputOutput = std::vector<std::pair<Unit, std::pair<Unit, int> > >();
} else {
inputOutput.clear();
}
inputOutput.insert(inputOutput.end(), output.begin(), output.end());
}
template <typename Unit>
inline void applyUnaryXOr(std::vector<std::pair<Unit, std::pair<Unit, int> > >& input) {
BooleanOp<UnaryCount, Unit> booleanXOr;
}
template <typename count_type = int>
struct default_arg_workaround {
template <typename Unit>
static inline void applyBooleanOr(std::vector<std::pair<Unit, std::pair<Unit, int> > >& input) {
BooleanOp<count_type, Unit> booleanOr;
std::vector<std::pair<interval_data<Unit>, int> > container;
std::vector<std::pair<Unit, std::pair<Unit, int> > > output;
output.reserve(input.size());
//consider eliminating dependecy on limits with bool flag for initial state
Unit UnitMax = (std::numeric_limits<Unit>::max)();
Unit prevPos = UnitMax;
Unit prevY = UnitMax;
int count = 0;
for(typename std::vector<std::pair<Unit, std::pair<Unit, int> > >::iterator itr = input.begin();
itr != input.end(); ++itr) {
Unit pos = (*itr).first;
Unit y = (*itr).second.first;
if(pos != prevPos) {
booleanOr.advanceScan();
prevPos = pos;
prevY = y;
count = (*itr).second.second;
continue;
}
if(y != prevY && count != 0) {
interval_data<Unit> ivl(prevY, y);
container.clear();
booleanOr.processInterval(container, ivl, count_type(count));
for(std::size_t i = 0; i < container.size(); ++i) {
std::pair<interval_data<Unit>, int>& element = container[i];
if(!output.empty() && output.back().first == prevPos &&
output.back().second.first == element.first.low() &&
output.back().second.second == element.second * -1) {
output.pop_back();
} else {
output.push_back(std::pair<Unit, std::pair<Unit, int> >(prevPos, std::pair<Unit, int>(element.first.low(),
element.second)));
}
output.push_back(std::pair<Unit, std::pair<Unit, int> >(prevPos, std::pair<Unit, int>(element.first.high(),
element.second * -1)));
}
}
prevY = y;
count += (*itr).second.second;
}
if(output.size() < input.size() / 2) {
input = std::vector<std::pair<Unit, std::pair<Unit, int> > >();
} else {
input.clear();
}
input.insert(input.end(), output.begin(), output.end());
}
};
}
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,68 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_ITERATOR_COMPACT_TO_POINTS_HPP
#define BOOST_POLYGON_ITERATOR_COMPACT_TO_POINTS_HPP
namespace boost { namespace polygon{
template <typename iterator_type, typename point_type>
class iterator_compact_to_points {
private:
iterator_type iter_;
iterator_type iter_end_;
point_type pt_;
typename point_traits<point_type>::coordinate_type firstX_;
orientation_2d orient_;
public:
typedef std::forward_iterator_tag iterator_category;
typedef point_type value_type;
typedef std::ptrdiff_t difference_type;
typedef const point_type* pointer; //immutable
typedef const point_type& reference; //immutable
inline iterator_compact_to_points() : iter_(), iter_end_(), pt_(), firstX_(), orient_() {}
inline iterator_compact_to_points(iterator_type iter, iterator_type iter_end) :
iter_(iter), iter_end_(iter_end), pt_(), firstX_(), orient_(HORIZONTAL) {
if(iter_ != iter_end_) {
firstX_ = *iter_;
x(pt_, firstX_);
++iter_;
if(iter_ != iter_end_) {
y(pt_, *iter_);
}
}
}
//use bitwise copy and assign provided by the compiler
inline iterator_compact_to_points& operator++() {
iterator_type prev_iter = iter_;
++iter_;
if(iter_ == iter_end_) {
if(x(pt_) != firstX_) {
iter_ = prev_iter;
x(pt_, firstX_);
}
} else {
set(pt_, orient_, *iter_);
orient_.turn_90();
}
return *this;
}
inline const iterator_compact_to_points operator++(int) {
iterator_compact_to_points tmp(*this);
++(*this);
return tmp;
}
inline bool operator==(const iterator_compact_to_points& that) const {
return (iter_ == that.iter_);
}
inline bool operator!=(const iterator_compact_to_points& that) const {
return (iter_ != that.iter_);
}
inline reference operator*() const { return pt_; }
};
}
}
#endif

View file

@ -0,0 +1,314 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_ITERATOR_GEOMETRY_TO_SET_HPP
#define BOOST_POLYGON_ITERATOR_GEOMETRY_TO_SET_HPP
namespace boost { namespace polygon{
template <typename concept_type, typename geometry_type>
class iterator_geometry_to_set {};
template <typename rectangle_type>
class iterator_geometry_to_set<rectangle_concept, rectangle_type> {
public:
typedef typename rectangle_traits<rectangle_type>::coordinate_type coordinate_type;
typedef std::forward_iterator_tag iterator_category;
typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type;
typedef std::ptrdiff_t difference_type;
typedef const value_type* pointer; //immutable
typedef const value_type& reference; //immutable
private:
rectangle_data<coordinate_type> rectangle_;
mutable value_type vertex_;
unsigned int corner_;
orientation_2d orient_;
bool is_hole_;
public:
iterator_geometry_to_set() : rectangle_(), vertex_(), corner_(4), orient_(), is_hole_() {}
iterator_geometry_to_set(const rectangle_type& rectangle, direction_1d dir,
orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) :
rectangle_(), vertex_(), corner_(0), orient_(orient), is_hole_(is_hole) {
assign(rectangle_, rectangle);
if(dir == HIGH) corner_ = 4;
}
inline iterator_geometry_to_set& operator++() {
++corner_;
return *this;
}
inline const iterator_geometry_to_set operator++(int) {
iterator_geometry_to_set tmp(*this);
++(*this);
return tmp;
}
inline bool operator==(const iterator_geometry_to_set& that) const {
return corner_ == that.corner_;
}
inline bool operator!=(const iterator_geometry_to_set& that) const {
return !(*this == that);
}
inline reference operator*() const {
if(corner_ == 0) {
vertex_.first = get(get(rectangle_, orient_.get_perpendicular()), LOW);
vertex_.second.first = get(get(rectangle_, orient_), LOW);
vertex_.second.second = 1;
if(is_hole_) vertex_.second.second *= -1;
} else if(corner_ == 1) {
vertex_.second.first = get(get(rectangle_, orient_), HIGH);
vertex_.second.second = -1;
if(is_hole_) vertex_.second.second *= -1;
} else if(corner_ == 2) {
vertex_.first = get(get(rectangle_, orient_.get_perpendicular()), HIGH);
vertex_.second.first = get(get(rectangle_, orient_), LOW);
} else {
vertex_.second.first = get(get(rectangle_, orient_), HIGH);
vertex_.second.second = 1;
if(is_hole_) vertex_.second.second *= -1;
}
return vertex_;
}
};
template <typename polygon_type>
class iterator_geometry_to_set<polygon_90_concept, polygon_type> {
public:
typedef typename polygon_traits<polygon_type>::coordinate_type coordinate_type;
typedef std::forward_iterator_tag iterator_category;
typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type;
typedef std::ptrdiff_t difference_type;
typedef const value_type* pointer; //immutable
typedef const value_type& reference; //immutable
typedef typename polygon_traits<polygon_type>::iterator_type coord_iterator_type;
private:
value_type vertex_;
typename polygon_traits<polygon_type>::iterator_type itrb, itre;
bool last_vertex_;
bool is_hole_;
int multiplier_;
point_data<coordinate_type> first_pt, second_pt, pts[3];
bool use_wrap;
orientation_2d orient_;
int polygon_index;
public:
iterator_geometry_to_set() : vertex_(), itrb(), itre(), last_vertex_(), is_hole_(), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), orient_(), polygon_index(-1) {}
iterator_geometry_to_set(const polygon_type& polygon, direction_1d dir, orientation_2d orient = HORIZONTAL, bool is_hole = false, bool winding_override = false, direction_1d w = CLOCKWISE) :
vertex_(), itrb(), itre(), last_vertex_(),
is_hole_(is_hole), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(),
orient_(orient), polygon_index(0) {
itrb = begin_points(polygon);
itre = end_points(polygon);
use_wrap = false;
if(itrb == itre || dir == HIGH || size(polygon) < 4) {
polygon_index = -1;
} else {
direction_1d wdir = w;
if(!winding_override)
wdir = winding(polygon);
multiplier_ = wdir == LOW ? -1 : 1;
if(is_hole_) multiplier_ *= -1;
first_pt = pts[0] = *itrb;
++itrb;
second_pt = pts[1] = *itrb;
++itrb;
pts[2] = *itrb;
evaluate_();
}
}
iterator_geometry_to_set(const iterator_geometry_to_set& that) :
vertex_(), itrb(), itre(), last_vertex_(), is_hole_(), multiplier_(), first_pt(),
second_pt(), pts(), use_wrap(), orient_(), polygon_index(-1) {
vertex_ = that.vertex_;
itrb = that.itrb;
itre = that.itre;
last_vertex_ = that.last_vertex_;
is_hole_ = that.is_hole_;
multiplier_ = that.multiplier_;
first_pt = that.first_pt;
second_pt = that.second_pt;
pts[0] = that.pts[0];
pts[1] = that.pts[1];
pts[2] = that.pts[2];
use_wrap = that.use_wrap;
orient_ = that.orient_;
polygon_index = that.polygon_index;
}
inline iterator_geometry_to_set& operator++() {
++polygon_index;
if(itrb == itre) {
if(first_pt == pts[1]) polygon_index = -1;
else {
pts[0] = pts[1];
pts[1] = pts[2];
if(first_pt == pts[2]) {
pts[2] = second_pt;
} else {
pts[2] = first_pt;
}
}
} else {
++itrb;
pts[0] = pts[1];
pts[1] = pts[2];
if(itrb == itre) {
if(first_pt == pts[2]) {
pts[2] = second_pt;
} else {
pts[2] = first_pt;
}
} else {
pts[2] = *itrb;
}
}
evaluate_();
return *this;
}
inline const iterator_geometry_to_set operator++(int) {
iterator_geometry_to_set tmp(*this);
++(*this);
return tmp;
}
inline bool operator==(const iterator_geometry_to_set& that) const {
return polygon_index == that.polygon_index;
}
inline bool operator!=(const iterator_geometry_to_set& that) const {
return !(*this == that);
}
inline reference operator*() const {
return vertex_;
}
inline void evaluate_() {
vertex_.first = pts[1].get(orient_.get_perpendicular());
vertex_.second.first =pts[1].get(orient_);
if(pts[1] == pts[2]) {
vertex_.second.second = 0;
} else if(pts[0].get(HORIZONTAL) != pts[1].get(HORIZONTAL)) {
vertex_.second.second = -1;
} else if(pts[0].get(VERTICAL) != pts[1].get(VERTICAL)) {
vertex_.second.second = 1;
} else {
vertex_.second.second = 0;
}
vertex_.second.second *= multiplier_;
}
};
template <typename polygon_with_holes_type>
class iterator_geometry_to_set<polygon_90_with_holes_concept, polygon_with_holes_type> {
public:
typedef typename polygon_90_traits<polygon_with_holes_type>::coordinate_type coordinate_type;
typedef std::forward_iterator_tag iterator_category;
typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type;
typedef std::ptrdiff_t difference_type;
typedef const value_type* pointer; //immutable
typedef const value_type& reference; //immutable
private:
iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type> itrb, itre;
iterator_geometry_to_set<polygon_90_concept, typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type> itrhib, itrhie;
typename polygon_with_holes_traits<polygon_with_holes_type>::iterator_holes_type itrhb, itrhe;
orientation_2d orient_;
bool is_hole_;
bool started_holes;
public:
iterator_geometry_to_set() : itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() {}
iterator_geometry_to_set(const polygon_with_holes_type& polygon, direction_1d dir,
orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) :
itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(orient), is_hole_(is_hole), started_holes() {
itre = iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type>(polygon, HIGH, orient, is_hole_);
itrhe = end_holes(polygon);
if(dir == HIGH) {
itrb = itre;
itrhb = itrhe;
started_holes = true;
} else {
itrb = iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type>(polygon, LOW, orient, is_hole_);
itrhb = begin_holes(polygon);
started_holes = false;
}
}
iterator_geometry_to_set(const iterator_geometry_to_set& that) :
itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() {
itrb = that.itrb;
itre = that.itre;
if(that.itrhib != that.itrhie) {
itrhib = that.itrhib;
itrhie = that.itrhie;
}
itrhb = that.itrhb;
itrhe = that.itrhe;
orient_ = that.orient_;
is_hole_ = that.is_hole_;
started_holes = that.started_holes;
}
inline iterator_geometry_to_set& operator++() {
//this code can be folded with flow control factoring
if(itrb == itre) {
if(itrhib == itrhie) {
if(itrhb != itrhe) {
itrhib = iterator_geometry_to_set<polygon_90_concept,
typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_);
itrhie = iterator_geometry_to_set<polygon_90_concept,
typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_);
++itrhb;
} else {
//in this case we have no holes so we just need the iterhib == itrhie, which
//is always true if they were default initialized in the initial case or
//both point to end of the previous hole processed
//no need to explicitly reset them, and it causes an stl debug assertion to use
//the default constructed iterator this way
//itrhib = itrhie = iterator_geometry_to_set<polygon_90_concept,
// typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>();
}
} else {
++itrhib;
if(itrhib == itrhie) {
if(itrhb != itrhe) {
itrhib = iterator_geometry_to_set<polygon_90_concept,
typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_);
itrhie = iterator_geometry_to_set<polygon_90_concept,
typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_);
++itrhb;
} else {
//this is the same case as above
//itrhib = itrhie = iterator_geometry_to_set<polygon_90_concept,
// typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>();
}
}
}
} else {
++itrb;
if(itrb == itre) {
if(itrhb != itrhe) {
itrhib = iterator_geometry_to_set<polygon_90_concept,
typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_);
itrhie = iterator_geometry_to_set<polygon_90_concept,
typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_);
++itrhb;
}
}
}
return *this;
}
inline const iterator_geometry_to_set operator++(int) {
iterator_geometry_to_set tmp(*this);
++(*this);
return tmp;
}
inline bool operator==(const iterator_geometry_to_set& that) const {
return itrb == that.itrb && itrhb == that.itrhb && itrhib == that.itrhib;
}
inline bool operator!=(const iterator_geometry_to_set& that) const {
return !(*this == that);
}
inline reference operator*() const {
if(itrb != itre) return *itrb;
return *itrhib;
}
};
}
}
#endif

View file

@ -0,0 +1,60 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_ITERATOR_POINTS_TO_COMPACT_HPP
#define BOOST_POLYGON_ITERATOR_POINTS_TO_COMPACT_HPP
namespace boost { namespace polygon{
template <typename iT, typename point_type>
class iterator_points_to_compact {
private:
iT iter_, iterEnd_;
orientation_2d orient_;
mutable typename point_traits<point_type>::coordinate_type coord_;
public:
typedef typename point_traits<point_type>::coordinate_type coordinate_type;
typedef std::forward_iterator_tag iterator_category;
typedef coordinate_type value_type;
typedef std::ptrdiff_t difference_type;
typedef const coordinate_type* pointer; //immutable
typedef const coordinate_type& reference; //immutable
inline iterator_points_to_compact() : iter_(), iterEnd_(), orient_(), coord_() {}
inline iterator_points_to_compact(iT iter, iT iterEnd) :
iter_(iter), iterEnd_(iterEnd), orient_(HORIZONTAL), coord_() {}
inline iterator_points_to_compact(const iterator_points_to_compact& that) :
iter_(that.iter_), iterEnd_(that.iterEnd_), orient_(that.orient_), coord_(that.coord_) {}
//use bitwise copy and assign provided by the compiler
inline iterator_points_to_compact& operator++() {
//iT tmp = iter_;
++iter_;
//iT tmp2 = iter_;
orient_.turn_90();
//while(tmp2 != iterEnd_ && get(*tmp2, orient_) == get(*tmp, orient_)) {
// iter_ = tmp2;
// ++tmp2;
//}
return *this;
}
inline const iterator_points_to_compact operator++(int) {
iT tmp(*this);
++(*this);
return tmp;
}
inline bool operator==(const iterator_points_to_compact& that) const {
return (iter_ == that.iter_);
}
inline bool operator!=(const iterator_points_to_compact& that) const {
return (iter_ != that.iter_);
}
inline reference operator*() const { coord_ = get(*iter_, orient_);
return coord_;
}
};
}
}
#endif

View file

@ -0,0 +1,278 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_MAX_COVER_HPP
#define BOOST_POLYGON_MAX_COVER_HPP
namespace boost { namespace polygon{
template <typename Unit>
struct MaxCover {
typedef interval_data<Unit> Interval;
typedef rectangle_data<Unit> Rectangle;
class Node {
private:
std::vector<Node*> children_;
std::set<Interval> tracedPaths_;
public:
Rectangle rect;
Node() : children_(), tracedPaths_(), rect() {}
Node(const Rectangle rectIn) : children_(), tracedPaths_(), rect(rectIn) {}
typedef typename std::vector<Node*>::iterator iterator;
inline iterator begin() { return children_.begin(); }
inline iterator end() { return children_.end(); }
inline void add(Node* child) { children_.push_back(child); }
inline bool tracedPath(const Interval& ivl) const {
return tracedPaths_.find(ivl) != tracedPaths_.end();
}
inline void addPath(const Interval& ivl) {
tracedPaths_.insert(tracedPaths_.end(), ivl);
}
};
typedef std::pair<std::pair<Unit, Interval>, Node* > EdgeAssociation;
class lessEdgeAssociation : public std::binary_function<const EdgeAssociation&, const EdgeAssociation&, bool> {
public:
inline lessEdgeAssociation() {}
inline bool operator () (const EdgeAssociation& elem1, const EdgeAssociation& elem2) const {
if(elem1.first.first < elem2.first.first) return true;
if(elem1.first.first > elem2.first.first) return false;
return elem1.first.second < elem2.first.second;
}
};
template <class cT>
static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient) {
Interval rectIvl = node->rect.get(orient);
if(node->tracedPath(rectIvl)) {
return;
}
node->addPath(rectIvl);
if(node->begin() == node->end()) {
//std::cout << "WRITE OUT 3: " << node->rect << std::endl;
outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(node->rect));
return;
}
bool writeOut = true;
for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) {
getMaxCover(outputContainer, *itr, orient, node->rect); //get rectangles down path
Interval nodeIvl = (*itr)->rect.get(orient);
if(contains(nodeIvl, rectIvl, true)) writeOut = false;
}
if(writeOut) {
//std::cout << "WRITE OUT 2: " << node->rect << std::endl;
outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(node->rect));
}
}
struct stack_element {
inline stack_element() :
node(), rect(), itr() {}
inline stack_element(Node* n,
const Rectangle& r,
typename Node::iterator i) :
node(n), rect(r), itr(i) {}
Node* node;
Rectangle rect;
typename Node::iterator itr;
};
template <class cT>
static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient,
Rectangle rect) {
//std::cout << "New Root\n";
std::vector<stack_element> stack;
typename Node::iterator itr = node->begin();
do {
//std::cout << "LOOP\n";
//std::cout << node->rect << std::endl;
Interval rectIvl = rect.get(orient);
Interval nodeIvl = node->rect.get(orient);
bool iresult = intersect(rectIvl, nodeIvl, false);
bool tresult = !node->tracedPath(rectIvl);
//std::cout << (itr != node->end()) << " " << iresult << " " << tresult << std::endl;
Rectangle nextRect1 = Rectangle(rectIvl, rectIvl);
Unit low = rect.get(orient.get_perpendicular()).low();
Unit high = node->rect.get(orient.get_perpendicular()).high();
nextRect1.set(orient.get_perpendicular(), Interval(low, high));
if(iresult && tresult) {
node->addPath(rectIvl);
bool writeOut = true;
//check further visibility beyond this node
for(typename Node::iterator itr2 = node->begin(); itr2 != node->end(); ++itr2) {
Interval nodeIvl3 = (*itr2)->rect.get(orient);
//if a child of this node can contain the interval then we can extend through
if(contains(nodeIvl3, rectIvl, true)) writeOut = false;
//std::cout << "child " << (*itr2)->rect << std::endl;
}
Rectangle nextRect2 = Rectangle(rectIvl, rectIvl);
Unit low2 = rect.get(orient.get_perpendicular()).low();
Unit high2 = node->rect.get(orient.get_perpendicular()).high();
nextRect2.set(orient.get_perpendicular(), Interval(low2, high2));
if(writeOut) {
//std::cout << "write out " << nextRect << std::endl;
outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(nextRect2));
} else {
//std::cout << "supress " << nextRect << std::endl;
}
}
if(itr != node->end() && iresult && tresult) {
//std::cout << "recurse into child\n";
stack.push_back(stack_element(node, rect, itr));
rect = nextRect1;
node = *itr;
itr = node->begin();
} else {
if(!stack.empty()) {
//std::cout << "recurse out of child\n";
node = stack.back().node;
rect = stack.back().rect;
itr = stack.back().itr;
stack.pop_back();
} else {
//std::cout << "empty stack\n";
//if there were no children of the root node
// Rectangle nextRect = Rectangle(rectIvl, rectIvl);
// Unit low = rect.get(orient.get_perpendicular()).low();
// Unit high = node->rect.get(orient.get_perpendicular()).high();
// nextRect.set(orient.get_perpendicular(), Interval(low, high));
// outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(nextRect));
}
//std::cout << "increment " << (itr != node->end()) << std::endl;
if(itr != node->end()) {
++itr;
if(itr != node->end()) {
//std::cout << "recurse into next child.\n";
stack.push_back(stack_element(node, rect, itr));
Interval rectIvl2 = rect.get(orient);
Interval nodeIvl2 = node->rect.get(orient);
/*bool iresult =*/ intersect(rectIvl2, nodeIvl2, false);
Rectangle nextRect2 = Rectangle(rectIvl2, rectIvl2);
Unit low2 = rect.get(orient.get_perpendicular()).low();
Unit high2 = node->rect.get(orient.get_perpendicular()).high();
nextRect2.set(orient.get_perpendicular(), Interval(low2, high2));
rect = nextRect2;
//std::cout << "rect for next child" << rect << std::endl;
node = *itr;
itr = node->begin();
}
}
}
} while(!stack.empty() || itr != node->end());
}
/* Function recursive version of getMaxCover
Because the code is so much simpler than the loop algorithm I retain it for clarity
template <class cT>
static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient,
const Rectangle& rect) {
Interval rectIvl = rect.get(orient);
Interval nodeIvl = node->rect.get(orient);
if(!intersect(rectIvl, nodeIvl, false)) {
return;
}
if(node->tracedPath(rectIvl)) {
return;
}
node->addPath(rectIvl);
Rectangle nextRect(rectIvl, rectIvl);
Unit low = rect.get(orient.get_perpendicular()).low();
Unit high = node->rect.get(orient.get_perpendicular()).high();
nextRect.set(orient.get_perpendicular(), Interval(low, high));
bool writeOut = true;
rectIvl = nextRect.get(orient);
for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) {
nodeIvl = (*itr)->rect.get(orient);
if(contains(nodeIvl, rectIvl, true)) writeOut = false;
}
if(writeOut) {
outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(nextRect));
}
for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) {
getMaxCover(outputContainer, *itr, orient, nextRect);
}
}
*/
//iterator range is assummed to be in topological order meaning all node's trailing
//edges are in sorted order
template <class iT>
static inline void computeDag(iT beginNode, iT endNode, orientation_2d orient,
std::size_t size) {
std::vector<EdgeAssociation> leadingEdges;
leadingEdges.reserve(size);
for(iT iter = beginNode; iter != endNode; ++iter) {
Node* nodep = &(*iter);
Unit leading = nodep->rect.get(orient.get_perpendicular()).low();
Interval rectIvl = nodep->rect.get(orient);
leadingEdges.push_back(EdgeAssociation(std::pair<Unit, Interval>(leading, rectIvl), nodep));
}
polygon_sort(leadingEdges.begin(), leadingEdges.end(), lessEdgeAssociation());
typename std::vector<EdgeAssociation>::iterator leadingBegin = leadingEdges.begin();
iT trailingBegin = beginNode;
while(leadingBegin != leadingEdges.end()) {
EdgeAssociation& leadingSegment = (*leadingBegin);
Unit trailing = (*trailingBegin).rect.get(orient.get_perpendicular()).high();
Interval ivl = (*trailingBegin).rect.get(orient);
std::pair<Unit, Interval> trailingSegment(trailing, ivl);
if(leadingSegment.first.first < trailingSegment.first) {
++leadingBegin;
continue;
}
if(leadingSegment.first.first > trailingSegment.first) {
++trailingBegin;
continue;
}
if(leadingSegment.first.second.high() <= trailingSegment.second.low()) {
++leadingBegin;
continue;
}
if(trailingSegment.second.high() <= leadingSegment.first.second.low()) {
++trailingBegin;
continue;
}
//leading segment intersects trailing segment
(*trailingBegin).add((*leadingBegin).second);
if(leadingSegment.first.second.high() > trailingSegment.second.high()) {
++trailingBegin;
continue;
}
if(trailingSegment.second.high() > leadingSegment.first.second.high()) {
++leadingBegin;
continue;
}
++leadingBegin;
++trailingBegin;
}
}
template <class cT>
static inline void getMaxCover(cT& outputContainer,
const std::vector<Rectangle>& rects, orientation_2d orient) {
if(rects.empty()) return;
std::vector<Node> nodes;
{
if(rects.size() == 1) {
outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(rects[0]));
return;
}
nodes.reserve(rects.size());
for(std::size_t i = 0; i < rects.size(); ++i) { nodes.push_back(Node(rects[i])); }
}
computeDag(nodes.begin(), nodes.end(), orient, nodes.size());
for(std::size_t i = 0; i < nodes.size(); ++i) {
getMaxCover(outputContainer, &(nodes[i]), orient);
}
}
};
}
}
#endif

View file

@ -0,0 +1,131 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
namespace boost { namespace polygon { namespace detail {
template <typename coordinate_type>
struct minkowski_offset {
typedef point_data<coordinate_type> point;
typedef polygon_set_data<coordinate_type> polygon_set;
typedef polygon_with_holes_data<coordinate_type> polygon;
typedef std::pair<point, point> edge;
static void convolve_two_segments(std::vector<point>& figure, const edge& a, const edge& b) {
figure.clear();
figure.push_back(point(a.first));
figure.push_back(point(a.first));
figure.push_back(point(a.second));
figure.push_back(point(a.second));
convolve(figure[0], b.second);
convolve(figure[1], b.first);
convolve(figure[2], b.first);
convolve(figure[3], b.second);
}
template <typename itrT1, typename itrT2>
static void convolve_two_point_sequences(polygon_set& result, itrT1 ab, itrT1 ae, itrT2 bb, itrT2 be) {
if(ab == ae || bb == be)
return;
point first_a = *ab;
point prev_a = *ab;
std::vector<point> vec;
polygon poly;
++ab;
for( ; ab != ae; ++ab) {
point first_b = *bb;
point prev_b = *bb;
itrT2 tmpb = bb;
++tmpb;
for( ; tmpb != be; ++tmpb) {
convolve_two_segments(vec, std::make_pair(prev_b, *tmpb), std::make_pair(prev_a, *ab));
set_points(poly, vec.begin(), vec.end());
result.insert(poly);
prev_b = *tmpb;
}
prev_a = *ab;
}
}
template <typename itrT>
static void convolve_point_sequence_with_polygons(polygon_set& result, itrT b, itrT e, const std::vector<polygon>& polygons) {
for(std::size_t i = 0; i < polygons.size(); ++i) {
convolve_two_point_sequences(result, b, e, begin_points(polygons[i]), end_points(polygons[i]));
for(typename polygon_with_holes_traits<polygon>::iterator_holes_type itrh = begin_holes(polygons[i]);
itrh != end_holes(polygons[i]); ++itrh) {
convolve_two_point_sequences(result, b, e, begin_points(*itrh), end_points(*itrh));
}
}
}
static void convolve_two_polygon_sets(polygon_set& result, const polygon_set& a, const polygon_set& b) {
result.clear();
std::vector<polygon> a_polygons;
std::vector<polygon> b_polygons;
a.get(a_polygons);
b.get(b_polygons);
for(std::size_t ai = 0; ai < a_polygons.size(); ++ai) {
convolve_point_sequence_with_polygons(result, begin_points(a_polygons[ai]),
end_points(a_polygons[ai]), b_polygons);
for(typename polygon_with_holes_traits<polygon>::iterator_holes_type itrh = begin_holes(a_polygons[ai]);
itrh != end_holes(a_polygons[ai]); ++itrh) {
convolve_point_sequence_with_polygons(result, begin_points(*itrh),
end_points(*itrh), b_polygons);
}
for(std::size_t bi = 0; bi < b_polygons.size(); ++bi) {
polygon tmp_poly = a_polygons[ai];
result.insert(convolve(tmp_poly, *(begin_points(b_polygons[bi]))));
tmp_poly = b_polygons[bi];
result.insert(convolve(tmp_poly, *(begin_points(a_polygons[ai]))));
}
}
}
};
}
template<typename T>
inline polygon_set_data<T>&
polygon_set_data<T>::resize(coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments) {
using namespace ::boost::polygon::operators;
if(!corner_fill_arc) {
if(resizing < 0)
return shrink(-resizing);
if(resizing > 0)
return bloat(resizing);
return *this;
}
if(resizing == 0) return *this;
if(empty()) return *this;
if(num_circle_segments < 3) num_circle_segments = 4;
rectangle_data<coordinate_type> rect;
extents(rect);
if(resizing < 0) {
::boost::polygon::bloat(rect, 10);
(*this) = rect - (*this); //invert
}
//make_arc(std::vector<point_data< T> >& return_points,
//point_data< double> start, point_data< double> end,
//point_data< double> center, double r, unsigned int num_circle_segments)
std::vector<point_data<coordinate_type> > circle;
point_data<double> center(0.0, 0.0), start(0.0, (double)resizing);
make_arc(circle, start, start, center, std::abs((double)resizing),
num_circle_segments);
polygon_data<coordinate_type> poly;
set_points(poly, circle.begin(), circle.end());
polygon_set_data<coordinate_type> offset_set;
offset_set += poly;
polygon_set_data<coordinate_type> result;
detail::minkowski_offset<coordinate_type>::convolve_two_polygon_sets
(result, *this, offset_set);
if(resizing < 0) {
result = result & rect;//eliminate overhang
result = result ^ rect;//invert
}
*this = result;
return *this;
}
}}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,380 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_45_SET_VIEW_HPP
#define BOOST_POLYGON_POLYGON_45_SET_VIEW_HPP
namespace boost { namespace polygon{
template <typename ltype, typename rtype, int op_type>
class polygon_45_set_view;
template <typename ltype, typename rtype, int op_type>
struct polygon_45_set_traits<polygon_45_set_view<ltype, rtype, op_type> > {
typedef typename polygon_45_set_view<ltype, rtype, op_type>::coordinate_type coordinate_type;
typedef typename polygon_45_set_view<ltype, rtype, op_type>::iterator_type iterator_type;
typedef typename polygon_45_set_view<ltype, rtype, op_type>::operator_arg_type operator_arg_type;
static inline iterator_type begin(const polygon_45_set_view<ltype, rtype, op_type>& polygon_45_set);
static inline iterator_type end(const polygon_45_set_view<ltype, rtype, op_type>& polygon_45_set);
template <typename input_iterator_type>
static inline void set(polygon_45_set_view<ltype, rtype, op_type>& polygon_45_set,
input_iterator_type input_begin, input_iterator_type input_end);
static inline bool clean(const polygon_45_set_view<ltype, rtype, op_type>& polygon_45_set);
};
template <typename value_type, typename ltype, typename rtype, int op_type>
struct compute_45_set_value {
static
void value(value_type& output_, const ltype& lvalue_, const rtype& rvalue_) {
output_.set(polygon_45_set_traits<ltype>::begin(lvalue_),
polygon_45_set_traits<ltype>::end(lvalue_));
value_type rinput_;
rinput_.set(polygon_45_set_traits<rtype>::begin(rvalue_),
polygon_45_set_traits<rtype>::end(rvalue_));
#ifdef BOOST_POLYGON_MSVC
#pragma warning (push)
#pragma warning (disable: 4127)
#endif
if(op_type == 0)
output_ |= rinput_;
else if(op_type == 1)
output_ &= rinput_;
else if(op_type == 2)
output_ ^= rinput_;
else
output_ -= rinput_;
#ifdef BOOST_POLYGON_MSVC
#pragma warning (pop)
#endif
}
};
template <typename value_type, typename ltype, typename rcoord, int op_type>
struct compute_45_set_value<value_type, ltype, polygon_45_set_data<rcoord>, op_type> {
static
void value(value_type& output_, const ltype& lvalue_, const polygon_45_set_data<rcoord>& rvalue_) {
output_.set(polygon_45_set_traits<ltype>::begin(lvalue_),
polygon_45_set_traits<ltype>::end(lvalue_));
#ifdef BOOST_POLYGON_MSVC
#pragma warning (push)
#pragma warning (disable: 4127)
#endif
if(op_type == 0)
output_ |= rvalue_;
else if(op_type == 1)
output_ &= rvalue_;
else if(op_type == 2)
output_ ^= rvalue_;
else
output_ -= rvalue_;
#ifdef BOOST_POLYGON_MSVC
#pragma warning (pop)
#endif
}
};
template <typename ltype, typename rtype, int op_type>
class polygon_45_set_view {
public:
typedef typename polygon_45_set_traits<ltype>::coordinate_type coordinate_type;
typedef polygon_45_set_data<coordinate_type> value_type;
typedef typename value_type::iterator_type iterator_type;
typedef polygon_45_set_view operator_arg_type;
private:
const ltype& lvalue_;
const rtype& rvalue_;
mutable value_type output_;
mutable bool evaluated_;
polygon_45_set_view& operator=(const polygon_45_set_view&);
public:
polygon_45_set_view(const ltype& lvalue,
const rtype& rvalue ) :
lvalue_(lvalue), rvalue_(rvalue), output_(), evaluated_(false) {}
// get iterator to begin vertex data
public:
const value_type& value() const {
if(!evaluated_) {
evaluated_ = true;
compute_45_set_value<value_type, ltype, rtype, op_type>::value(output_, lvalue_, rvalue_);
}
return output_;
}
public:
iterator_type begin() const { return value().begin(); }
iterator_type end() const { return value().end(); }
bool dirty() const { return value().dirty(); } //result of a boolean is clean
bool sorted() const { return value().sorted(); } //result of a boolean is sorted
// template <typename input_iterator_type>
// void set(input_iterator_type input_begin, input_iterator_type input_end,
// orientation_2d orient) const {
// orient_ = orient;
// output_.clear();
// output_.insert(output_.end(), input_begin, input_end);
// polygon_sort(output_.begin(), output_.end());
// }
};
template <typename ltype, typename rtype, int op_type>
typename polygon_45_set_traits<polygon_45_set_view<ltype, rtype, op_type> >::iterator_type
polygon_45_set_traits<polygon_45_set_view<ltype, rtype, op_type> >::
begin(const polygon_45_set_view<ltype, rtype, op_type>& polygon_45_set) {
return polygon_45_set.begin();
}
template <typename ltype, typename rtype, int op_type>
typename polygon_45_set_traits<polygon_45_set_view<ltype, rtype, op_type> >::iterator_type
polygon_45_set_traits<polygon_45_set_view<ltype, rtype, op_type> >::
end(const polygon_45_set_view<ltype, rtype, op_type>& polygon_45_set) {
return polygon_45_set.end();
}
template <typename ltype, typename rtype, int op_type>
bool polygon_45_set_traits<polygon_45_set_view<ltype, rtype, op_type> >::
clean(const polygon_45_set_view<ltype, rtype, op_type>& polygon_45_set) {
return polygon_45_set.value().clean(); }
template <typename geometry_type_1, typename geometry_type_2, int op_type>
geometry_type_1& self_assignment_boolean_op_45(geometry_type_1& lvalue_, const geometry_type_2& rvalue_) {
typedef geometry_type_1 ltype;
typedef geometry_type_2 rtype;
typedef typename polygon_45_set_traits<ltype>::coordinate_type coordinate_type;
typedef polygon_45_set_data<coordinate_type> value_type;
value_type output_;
value_type rinput_;
output_.set(polygon_45_set_traits<ltype>::begin(lvalue_),
polygon_45_set_traits<ltype>::end(lvalue_));
rinput_.set(polygon_45_set_traits<rtype>::begin(rvalue_),
polygon_45_set_traits<rtype>::end(rvalue_));
#ifdef BOOST_POLYGON_MSVC
#pragma warning (push)
#pragma warning (disable: 4127)
#endif
if(op_type == 0)
output_ |= rinput_;
else if(op_type == 1)
output_ &= rinput_;
else if(op_type == 2)
output_ ^= rinput_;
else
output_ -= rinput_;
#ifdef BOOST_POLYGON_MSVC
#pragma warning (pop)
#endif
polygon_45_set_mutable_traits<geometry_type_1>::set(lvalue_, output_.begin(), output_.end());
return lvalue_;
}
template <typename concept_type>
struct fracture_holes_option_by_type {
static const bool value = true;
};
template <>
struct fracture_holes_option_by_type<polygon_45_with_holes_concept> {
static const bool value = false;
};
template <>
struct fracture_holes_option_by_type<polygon_with_holes_concept> {
static const bool value = false;
};
template <typename ltype, typename rtype, int op_type>
struct geometry_concept<polygon_45_set_view<ltype, rtype, op_type> > { typedef polygon_45_set_concept type; };
namespace operators {
struct y_ps45_b : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_4< y_ps45_b,
typename is_polygon_45_or_90_set_type<geometry_type_1>::type,
typename is_polygon_45_or_90_set_type<geometry_type_2>::type,
typename is_either_polygon_45_set_type<geometry_type_1, geometry_type_2>::type>::type,
polygon_45_set_view<geometry_type_1, geometry_type_2, 0> >::type
operator|(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_45_set_view<geometry_type_1, geometry_type_2, 0>
(lvalue, rvalue);
}
struct y_ps45_p : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_4< y_ps45_p,
typename gtl_if<typename is_polygon_45_or_90_set_type<geometry_type_1>::type>::type,
typename gtl_if<typename is_polygon_45_or_90_set_type<geometry_type_2>::type>::type,
typename gtl_if<typename is_either_polygon_45_set_type<geometry_type_1, geometry_type_2>::type>::type>::type,
polygon_45_set_view<geometry_type_1, geometry_type_2, 0> >::type
operator+(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_45_set_view<geometry_type_1, geometry_type_2, 0>
(lvalue, rvalue);
}
struct y_ps45_s : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_4< y_ps45_s, typename is_polygon_45_or_90_set_type<geometry_type_1>::type,
typename is_polygon_45_or_90_set_type<geometry_type_2>::type,
typename is_either_polygon_45_set_type<geometry_type_1, geometry_type_2>::type>::type,
polygon_45_set_view<geometry_type_1, geometry_type_2, 1> >::type
operator*(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_45_set_view<geometry_type_1, geometry_type_2, 1>
(lvalue, rvalue);
}
struct y_ps45_a : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_4< y_ps45_a, typename is_polygon_45_or_90_set_type<geometry_type_1>::type,
typename is_polygon_45_or_90_set_type<geometry_type_2>::type,
typename is_either_polygon_45_set_type<geometry_type_1, geometry_type_2>::type>::type,
polygon_45_set_view<geometry_type_1, geometry_type_2, 1> >::type
operator&(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_45_set_view<geometry_type_1, geometry_type_2, 1>
(lvalue, rvalue);
}
struct y_ps45_x : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_4< y_ps45_x, typename is_polygon_45_or_90_set_type<geometry_type_1>::type,
typename is_polygon_45_or_90_set_type<geometry_type_2>::type,
typename is_either_polygon_45_set_type<geometry_type_1, geometry_type_2>::type>::type,
polygon_45_set_view<geometry_type_1, geometry_type_2, 2> >::type
operator^(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_45_set_view<geometry_type_1, geometry_type_2, 2>
(lvalue, rvalue);
}
struct y_ps45_m : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_4< y_ps45_m,
typename gtl_if<typename is_polygon_45_or_90_set_type<geometry_type_1>::type>::type,
typename gtl_if<typename is_polygon_45_or_90_set_type<geometry_type_2>::type>::type,
typename gtl_if<typename is_either_polygon_45_set_type<geometry_type_1, geometry_type_2>::type>::type>::type,
polygon_45_set_view<geometry_type_1, geometry_type_2, 3> >::type
operator-(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_45_set_view<geometry_type_1, geometry_type_2, 3>
(lvalue, rvalue);
}
struct y_ps45_pe : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_4<y_ps45_pe, typename is_mutable_polygon_45_set_type<geometry_type_1>::type, gtl_yes,
typename is_polygon_45_or_90_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator+=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op_45<geometry_type_1, geometry_type_2, 0>(lvalue, rvalue);
}
struct y_ps45_be : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3<y_ps45_be, typename is_mutable_polygon_45_set_type<geometry_type_1>::type,
typename is_polygon_45_or_90_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator|=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op_45<geometry_type_1, geometry_type_2, 0>(lvalue, rvalue);
}
struct y_ps45_se : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3< y_ps45_se,
typename is_mutable_polygon_45_set_type<geometry_type_1>::type,
typename is_polygon_45_or_90_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator*=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op_45<geometry_type_1, geometry_type_2, 1>(lvalue, rvalue);
}
struct y_ps45_ae : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3<y_ps45_ae, typename is_mutable_polygon_45_set_type<geometry_type_1>::type,
typename is_polygon_45_or_90_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator&=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op_45<geometry_type_1, geometry_type_2, 1>(lvalue, rvalue);
}
struct y_ps45_xe : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if<
typename gtl_and_3<y_ps45_xe, typename is_mutable_polygon_45_set_type<geometry_type_1>::type,
typename is_polygon_45_or_90_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator^=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op_45<geometry_type_1, geometry_type_2, 2>(lvalue, rvalue);
}
struct y_ps45_me : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3<y_ps45_me, typename is_mutable_polygon_45_set_type<geometry_type_1>::type,
typename is_polygon_45_or_90_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator-=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op_45<geometry_type_1, geometry_type_2, 3>(lvalue, rvalue);
}
struct y_ps45_rpe : gtl_yes {};
template <typename geometry_type_1, typename coordinate_type_1>
typename enable_if< typename gtl_and_3< y_ps45_rpe, typename is_mutable_polygon_45_set_type<geometry_type_1>::type,
typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type,
coordinate_concept>::type>::type,
geometry_type_1>::type &
operator+=(geometry_type_1& lvalue, coordinate_type_1 rvalue) {
return resize(lvalue, rvalue);
}
struct y_ps45_rme : gtl_yes {};
template <typename geometry_type_1, typename coordinate_type_1>
typename enable_if< typename gtl_and_3<y_ps45_rme, typename gtl_if<typename is_mutable_polygon_45_set_type<geometry_type_1>::type>::type,
typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type,
coordinate_concept>::type>::type,
geometry_type_1>::type &
operator-=(geometry_type_1& lvalue, coordinate_type_1 rvalue) {
return resize(lvalue, -rvalue);
}
struct y_ps45_rp : gtl_yes {};
template <typename geometry_type_1, typename coordinate_type_1>
typename enable_if< typename gtl_and_3<y_ps45_rp, typename gtl_if<typename is_mutable_polygon_45_set_type<geometry_type_1>::type>::type,
typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type,
coordinate_concept>::type>
::type, geometry_type_1>::type
operator+(const geometry_type_1& lvalue, coordinate_type_1 rvalue) {
geometry_type_1 retval(lvalue);
retval += rvalue;
return retval;
}
struct y_ps45_rm : gtl_yes {};
template <typename geometry_type_1, typename coordinate_type_1>
typename enable_if< typename gtl_and_3<y_ps45_rm, typename gtl_if<typename is_mutable_polygon_45_set_type<geometry_type_1>::type>::type,
typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type,
coordinate_concept>::type>
::type, geometry_type_1>::type
operator-(const geometry_type_1& lvalue, coordinate_type_1 rvalue) {
geometry_type_1 retval(lvalue);
retval -= rvalue;
return retval;
}
}
}
}
#endif

View file

@ -0,0 +1,238 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_45_TOUCH_HPP
#define BOOST_POLYGON_POLYGON_45_TOUCH_HPP
namespace boost { namespace polygon{
template <typename Unit>
struct polygon_45_touch {
typedef point_data<Unit> Point;
typedef typename coordinate_traits<Unit>::manhattan_area_type LongUnit;
template <typename property_map>
static inline void merge_property_maps(property_map& mp, const property_map& mp2, bool subtract = false) {
property_map newmp;
newmp.reserve(mp.size() + mp2.size());
std::size_t i = 0;
std::size_t j = 0;
while(i != mp.size() && j != mp2.size()) {
if(mp[i].first < mp2[j].first) {
newmp.push_back(mp[i]);
++i;
} else if(mp[i].first > mp2[j].first) {
newmp.push_back(mp2[j]);
if(subtract) newmp.back().second *= -1;
++j;
} else {
int count = mp[i].second;
if(subtract) count -= mp2[j].second;
else count += mp2[j].second;
if(count) {
newmp.push_back(mp[i]);
newmp.back().second = count;
}
++i;
++j;
}
}
while(i != mp.size()) {
newmp.push_back(mp[i]);
++i;
}
while(j != mp2.size()) {
newmp.push_back(mp2[j]);
if(subtract) newmp.back().second *= -1;
++j;
}
mp.swap(newmp);
}
class CountTouch {
public:
inline CountTouch() : counts() {}
//inline CountTouch(int count) { counts[0] = counts[1] = count; }
//inline CountTouch(int count1, int count2) { counts[0] = count1; counts[1] = count2; }
inline CountTouch(const CountTouch& count) : counts(count.counts) {}
inline bool operator==(const CountTouch& count) const { return counts == count.counts; }
inline bool operator!=(const CountTouch& count) const { return !((*this) == count); }
//inline CountTouch& operator=(int count) { counts[0] = counts[1] = count; return *this; }
inline CountTouch& operator=(const CountTouch& count) { counts = count.counts; return *this; }
inline int& operator[](int index) {
std::vector<std::pair<int, int> >::iterator itr =
std::lower_bound(counts.begin(), counts.end(),
std::make_pair(index, int(0)));
if(itr != counts.end() && itr->first == index) {
return itr->second;
}
itr = counts.insert(itr, std::make_pair(index, int(0)));
return itr->second;
}
// inline int operator[](int index) const {
// std::vector<std::pair<int, int> >::const_iterator itr = counts.begin();
// for( ; itr != counts.end() && itr->first <= index; ++itr) {
// if(itr->first == index) {
// return itr->second;
// }
// }
// return 0;
// }
inline CountTouch& operator+=(const CountTouch& count){
merge_property_maps(counts, count.counts, false);
return *this;
}
inline CountTouch& operator-=(const CountTouch& count){
merge_property_maps(counts, count.counts, true);
return *this;
}
inline CountTouch operator+(const CountTouch& count) const {
return CountTouch(*this)+=count;
}
inline CountTouch operator-(const CountTouch& count) const {
return CountTouch(*this)-=count;
}
inline CountTouch invert() const {
CountTouch retval;
retval -= *this;
return retval;
}
std::vector<std::pair<int, int> > counts;
};
typedef std::pair<std::pair<Unit, std::map<Unit, std::set<int> > >, std::map<int, std::set<int> > > map_graph_o;
typedef std::pair<std::pair<Unit, std::map<Unit, std::set<int> > >, std::vector<std::set<int> > > vector_graph_o;
template <typename cT>
static void process_previous_x(cT& output) {
std::map<Unit, std::set<int> >& y_prop_map = output.first.second;
for(typename std::map<Unit, std::set<int> >::iterator itr = y_prop_map.begin();
itr != y_prop_map.end(); ++itr) {
for(std::set<int>::iterator inner_itr = itr->second.begin();
inner_itr != itr->second.end(); ++inner_itr) {
std::set<int>& output_edges = (*(output.second))[*inner_itr];
std::set<int>::iterator inner_inner_itr = inner_itr;
++inner_inner_itr;
for( ; inner_inner_itr != itr->second.end(); ++inner_inner_itr) {
output_edges.insert(output_edges.end(), *inner_inner_itr);
std::set<int>& output_edges_2 = (*(output.second))[*inner_inner_itr];
output_edges_2.insert(output_edges_2.end(), *inner_itr);
}
}
}
y_prop_map.clear();
}
struct touch_45_output_functor {
template <typename cT>
void operator()(cT& output, const CountTouch& count1, const CountTouch& count2,
const Point& pt, int , direction_1d ) {
Unit& x = output.first.first;
std::map<Unit, std::set<int> >& y_prop_map = output.first.second;
if(pt.x() != x) process_previous_x(output);
x = pt.x();
std::set<int>& output_set = y_prop_map[pt.y()];
for(std::vector<std::pair<int, int> >::const_iterator itr1 = count1.counts.begin();
itr1 != count1.counts.end(); ++itr1) {
if(itr1->second > 0) {
output_set.insert(output_set.end(), itr1->first);
}
}
for(std::vector<std::pair<int, int> >::const_iterator itr2 = count2.counts.begin();
itr2 != count2.counts.end(); ++itr2) {
if(itr2->second > 0) {
output_set.insert(output_set.end(), itr2->first);
}
}
}
};
typedef typename std::pair<Point,
typename boolean_op_45<Unit>::template Scan45CountT<CountTouch> > Vertex45Compact;
typedef std::vector<Vertex45Compact> TouchSetData;
struct lessVertex45Compact {
bool operator()(const Vertex45Compact& l, const Vertex45Compact& r) {
return l.first < r.first;
}
};
// template <typename TSD>
// static void print_tsd(TSD& tsd) {
// for(std::size_t i = 0; i < tsd.size(); ++i) {
// std::cout << tsd[i].first << ": ";
// for(unsigned int r = 0; r < 4; ++r) {
// std::cout << r << " { ";
// for(std::vector<std::pair<int, int> >::iterator itr = tsd[i].second[r].counts.begin();
// itr != tsd[i].second[r].counts.end(); ++itr) {
// std::cout << itr->first << "," << itr->second << " ";
// } std::cout << "} ";
// }
// } std::cout << std::endl;
// }
// template <typename T>
// static void print_scanline(T& t) {
// for(typename T::iterator itr = t.begin(); itr != t.end(); ++itr) {
// std::cout << itr->x << "," << itr->y << " " << itr->rise << " ";
// for(std::vector<std::pair<int, int> >::iterator itr2 = itr->count.counts.begin();
// itr2 != itr->count.counts.end(); ++itr2) {
// std::cout << itr2->first << ":" << itr2->second << " ";
// } std::cout << std::endl;
// }
// }
template <typename graph_type>
static void performTouch(graph_type& graph, TouchSetData& tsd) {
polygon_sort(tsd.begin(), tsd.end(), lessVertex45Compact());
typedef std::vector<std::pair<Point, typename boolean_op_45<Unit>::template Scan45CountT<CountTouch> > > TSD;
TSD tsd_;
tsd_.reserve(tsd.size());
for(typename TouchSetData::iterator itr = tsd.begin(); itr != tsd.end(); ) {
typename TouchSetData::iterator itr2 = itr;
++itr2;
for(; itr2 != tsd.end() && itr2->first == itr->first; ++itr2) {
(itr->second) += (itr2->second); //accumulate
}
tsd_.push_back(std::make_pair(itr->first, itr->second));
itr = itr2;
}
std::pair<std::pair<Unit, std::map<Unit, std::set<int> > >, graph_type*> output
(std::make_pair(std::make_pair((std::numeric_limits<Unit>::max)(), std::map<Unit, std::set<int> >()), &graph));
typename boolean_op_45<Unit>::template Scan45<CountTouch, touch_45_output_functor> scanline;
for(typename TSD::iterator itr = tsd_.begin(); itr != tsd_.end(); ) {
typename TSD::iterator itr2 = itr;
++itr2;
while(itr2 != tsd_.end() && itr2->first.x() == itr->first.x()) {
++itr2;
}
scanline.scan(output, itr, itr2);
itr = itr2;
}
process_previous_x(output);
}
template <typename iT>
static void populateTouchSetData(TouchSetData& tsd, iT begin, iT end, int nodeCount) {
for( ; begin != end; ++begin) {
Vertex45Compact vertex;
vertex.first = typename Vertex45Compact::first_type(begin->pt.x() * 2, begin->pt.y() * 2);
tsd.push_back(vertex);
for(unsigned int i = 0; i < 4; ++i) {
if(begin->count[i]) {
tsd.back().second[i][nodeCount] += begin->count[i];
}
}
}
}
};
}
}
#endif

View file

@ -0,0 +1,490 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_90_SET_VIEW_HPP
#define BOOST_POLYGON_POLYGON_90_SET_VIEW_HPP
namespace boost { namespace polygon{
struct operator_provides_storage {};
struct operator_requires_copy {};
template <typename value_type, typename arg_type>
inline void insert_into_view_arg(value_type& dest, const arg_type& arg, orientation_2d orient);
template <typename ltype, typename rtype, typename op_type>
class polygon_90_set_view;
template <typename ltype, typename rtype, typename op_type>
struct polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> > {
typedef typename polygon_90_set_view<ltype, rtype, op_type>::coordinate_type coordinate_type;
typedef typename polygon_90_set_view<ltype, rtype, op_type>::iterator_type iterator_type;
typedef typename polygon_90_set_view<ltype, rtype, op_type>::operator_arg_type operator_arg_type;
static inline iterator_type begin(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set);
static inline iterator_type end(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set);
static inline orientation_2d orient(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set);
static inline bool clean(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set);
static inline bool sorted(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set);
};
template <typename value_type, typename ltype, typename rtype, typename op_type>
struct compute_90_set_value {
static
void value(value_type& output_, const ltype& lvalue_, const rtype& rvalue_, orientation_2d orient_) {
value_type linput_(orient_);
value_type rinput_(orient_);
orientation_2d orient_l = polygon_90_set_traits<ltype>::orient(lvalue_);
orientation_2d orient_r = polygon_90_set_traits<rtype>::orient(rvalue_);
//std::cout << "compute_90_set_value-0 orientations (left, right, out):\t" << orient_l.to_int()
// << "," << orient_r.to_int() << "," << orient_.to_int() << std::endl;
insert_into_view_arg(linput_, lvalue_, orient_l);
insert_into_view_arg(rinput_, rvalue_, orient_r);
output_.applyBooleanBinaryOp(linput_.begin(), linput_.end(),
rinput_.begin(), rinput_.end(), boolean_op::BinaryCount<op_type>());
}
};
template <typename value_type, typename lcoord, typename rcoord, typename op_type>
struct compute_90_set_value<value_type, polygon_90_set_data<lcoord>, polygon_90_set_data<rcoord>, op_type> {
static
void value(value_type& output_, const polygon_90_set_data<lcoord>& lvalue_,
const polygon_90_set_data<rcoord>& rvalue_, orientation_2d orient_) {
orientation_2d orient_l = lvalue_.orient();
orientation_2d orient_r = rvalue_.orient();
value_type linput_(orient_);
value_type rinput_(orient_);
//std::cout << "compute_90_set_value-1 orientations (left, right, out):\t" << orient_l.to_int()
// << "," << orient_r.to_int() << "," << orient_.to_int() << std::endl;
if((orient_ == orient_l) && (orient_== orient_r)){ // assume that most of the time this condition is met
lvalue_.sort();
rvalue_.sort();
output_.applyBooleanBinaryOp(lvalue_.begin(), lvalue_.end(),
rvalue_.begin(), rvalue_.end(), boolean_op::BinaryCount<op_type>());
}else if((orient_ != orient_l) && (orient_!= orient_r)){ // both the orientations are not equal to input
// easier way is to ignore the input orientation and use the input data's orientation, but not done so
insert_into_view_arg(linput_, lvalue_, orient_l);
insert_into_view_arg(rinput_, rvalue_, orient_r);
output_.applyBooleanBinaryOp(linput_.begin(), linput_.end(),
rinput_.begin(), rinput_.end(), boolean_op::BinaryCount<op_type>());
}else if(orient_ != orient_l){ // left hand side orientation is different
insert_into_view_arg(linput_, lvalue_, orient_l);
rvalue_.sort();
output_.applyBooleanBinaryOp(linput_.begin(), linput_.end(),
rvalue_.begin(), rvalue_.end(), boolean_op::BinaryCount<op_type>());
} else if(orient_ != orient_r){ // right hand side orientation is different
insert_into_view_arg(rinput_, rvalue_, orient_r);
lvalue_.sort();
output_.applyBooleanBinaryOp(lvalue_.begin(), lvalue_.end(),
rinput_.begin(), rinput_.end(), boolean_op::BinaryCount<op_type>());
}
}
};
template <typename value_type, typename lcoord, typename rtype, typename op_type>
struct compute_90_set_value<value_type, polygon_90_set_data<lcoord>, rtype, op_type> {
static
void value(value_type& output_, const polygon_90_set_data<lcoord>& lvalue_,
const rtype& rvalue_, orientation_2d orient_) {
value_type rinput_(orient_);
lvalue_.sort();
orientation_2d orient_r = polygon_90_set_traits<rtype>::orient(rvalue_);
//std::cout << "compute_90_set_value-2 orientations (right, out):\t" << orient_r.to_int()
// << "," << orient_.to_int() << std::endl;
insert_into_view_arg(rinput_, rvalue_, orient_r);
output_.applyBooleanBinaryOp(lvalue_.begin(), lvalue_.end(),
rinput_.begin(), rinput_.end(), boolean_op::BinaryCount<op_type>());
}
};
template <typename value_type, typename ltype, typename rcoord, typename op_type>
struct compute_90_set_value<value_type, ltype, polygon_90_set_data<rcoord>, op_type> {
static
void value(value_type& output_, const ltype& lvalue_,
const polygon_90_set_data<rcoord>& rvalue_, orientation_2d orient_) {
value_type linput_(orient_);
orientation_2d orient_l = polygon_90_set_traits<ltype>::orient(lvalue_);
insert_into_view_arg(linput_, lvalue_, orient_l);
rvalue_.sort();
//std::cout << "compute_90_set_value-3 orientations (left, out):\t" << orient_l.to_int()
// << "," << orient_.to_int() << std::endl;
output_.applyBooleanBinaryOp(linput_.begin(), linput_.end(),
rvalue_.begin(), rvalue_.end(), boolean_op::BinaryCount<op_type>());
}
};
template <typename ltype, typename rtype, typename op_type>
class polygon_90_set_view {
public:
typedef typename polygon_90_set_traits<ltype>::coordinate_type coordinate_type;
typedef polygon_90_set_data<coordinate_type> value_type;
typedef typename value_type::iterator_type iterator_type;
typedef polygon_90_set_view operator_arg_type;
private:
const ltype& lvalue_;
const rtype& rvalue_;
orientation_2d orient_;
op_type op_;
mutable value_type output_;
mutable bool evaluated_;
polygon_90_set_view& operator=(const polygon_90_set_view&);
public:
polygon_90_set_view(const ltype& lvalue,
const rtype& rvalue,
orientation_2d orient,
op_type op) :
lvalue_(lvalue), rvalue_(rvalue), orient_(orient), op_(op), output_(orient), evaluated_(false) {}
// get iterator to begin vertex data
private:
const value_type& value() const {
if(!evaluated_) {
evaluated_ = true;
compute_90_set_value<value_type, ltype, rtype, op_type>::value(output_, lvalue_, rvalue_, orient_);
}
return output_;
}
public:
iterator_type begin() const { return value().begin(); }
iterator_type end() const { return value().end(); }
orientation_2d orient() const { return orient_; }
bool dirty() const { return false; } //result of a boolean is clean
bool sorted() const { return true; } //result of a boolean is sorted
// template <typename input_iterator_type>
// void set(input_iterator_type input_begin, input_iterator_type input_end,
// orientation_2d orient) const {
// orient_ = orient;
// output_.clear();
// output_.insert(output_.end(), input_begin, input_end);
// polygon_sort(output_.begin(), output_.end());
// }
void sort() const {} //is always sorted
};
template <typename ltype, typename rtype, typename op_type>
struct geometry_concept<polygon_90_set_view<ltype, rtype, op_type> > {
typedef polygon_90_set_concept type;
};
template <typename ltype, typename rtype, typename op_type>
typename polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> >::iterator_type
polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> >::
begin(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set) {
return polygon_set.begin();
}
template <typename ltype, typename rtype, typename op_type>
typename polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> >::iterator_type
polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> >::
end(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set) {
return polygon_set.end();
}
// template <typename ltype, typename rtype, typename op_type>
// template <typename input_iterator_type>
// void polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> >::
// set(polygon_90_set_view<ltype, rtype, op_type>& polygon_set,
// input_iterator_type input_begin, input_iterator_type input_end,
// orientation_2d orient) {
// polygon_set.set(input_begin, input_end, orient);
// }
template <typename ltype, typename rtype, typename op_type>
orientation_2d polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> >::
orient(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set) {
return polygon_set.orient(); }
template <typename ltype, typename rtype, typename op_type>
bool polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> >::
clean(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set) {
return true; }
template <typename ltype, typename rtype, typename op_type>
bool polygon_90_set_traits<polygon_90_set_view<ltype, rtype, op_type> >::
sorted(const polygon_90_set_view<ltype, rtype, op_type>& polygon_set) {
return true; }
template <typename value_type, typename arg_type>
inline void insert_into_view_arg(value_type& dest, const arg_type& arg, orientation_2d orient) {
typedef typename polygon_90_set_traits<arg_type>::iterator_type literator;
literator itr1, itr2;
itr1 = polygon_90_set_traits<arg_type>::begin(arg);
itr2 = polygon_90_set_traits<arg_type>::end(arg);
dest.insert(itr1, itr2, orient);
dest.sort();
}
template <typename T>
template <typename ltype, typename rtype, typename op_type>
inline polygon_90_set_data<T>& polygon_90_set_data<T>::operator=(const polygon_90_set_view<ltype, rtype, op_type>& that) {
set(that.begin(), that.end(), that.orient());
dirty_ = false;
unsorted_ = false;
return *this;
}
template <typename T>
template <typename ltype, typename rtype, typename op_type>
inline polygon_90_set_data<T>::polygon_90_set_data(const polygon_90_set_view<ltype, rtype, op_type>& that) :
orient_(that.orient()), data_(that.begin(), that.end()), dirty_(false), unsorted_(false) {}
template <typename geometry_type_1, typename geometry_type_2>
struct self_assign_operator_lvalue {
typedef geometry_type_1& type;
};
template <typename type_1, typename type_2>
struct by_value_binary_operator {
typedef type_1 type;
};
template <typename geometry_type_1, typename geometry_type_2, typename op_type>
geometry_type_1& self_assignment_boolean_op(geometry_type_1& lvalue_, const geometry_type_2& rvalue_) {
typedef geometry_type_1 ltype;
typedef geometry_type_2 rtype;
typedef typename polygon_90_set_traits<ltype>::coordinate_type coordinate_type;
typedef polygon_90_set_data<coordinate_type> value_type;
orientation_2d orient_ = polygon_90_set_traits<ltype>::orient(lvalue_);
//BM: rvalue_ data set may have its own orientation for scanline
orientation_2d orient_r = polygon_90_set_traits<rtype>::orient(rvalue_);
//std::cout << "self-assignment boolean-op (left, right, out):\t" << orient_.to_int()
// << "," << orient_r.to_int() << "," << orient_.to_int() << std::endl;
value_type linput_(orient_);
// BM: the rinput_ set's (that stores the rvalue_ dataset polygons) scanline orientation is *forced*
// to be same as linput
value_type rinput_(orient_);
//BM: The output dataset's scanline orient is set as equal to first input dataset's (lvalue_) orientation
value_type output_(orient_);
insert_into_view_arg(linput_, lvalue_, orient_);
// BM: The last argument orient_r is the user initialized scanline orientation for rvalue_ data set.
// But since rinput (see above) is initialized to scanline orientation consistent with the lvalue_
// data set, this insertion operation will change the incoming rvalue_ dataset's scanline orientation
insert_into_view_arg(rinput_, rvalue_, orient_r);
// BM: boolean operation and output uses lvalue_ dataset's scanline orientation.
output_.applyBooleanBinaryOp(linput_.begin(), linput_.end(),
rinput_.begin(), rinput_.end(), boolean_op::BinaryCount<op_type>());
polygon_90_set_mutable_traits<geometry_type_1>::set(lvalue_, output_.begin(), output_.end(), orient_);
return lvalue_;
}
namespace operators {
struct y_ps90_b : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3< y_ps90_b,
typename is_polygon_90_set_type<geometry_type_1>::type,
typename is_polygon_90_set_type<geometry_type_2>::type>::type,
polygon_90_set_view<geometry_type_1, geometry_type_2, boolean_op::BinaryOr> >::type
operator|(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_90_set_view<geometry_type_1, geometry_type_2, boolean_op::BinaryOr>
(lvalue, rvalue,
polygon_90_set_traits<geometry_type_1>::orient(lvalue),
boolean_op::BinaryOr());
}
struct y_ps90_p : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if<
typename gtl_and_3< y_ps90_p,
typename gtl_if<typename is_polygon_90_set_type<geometry_type_1>::type>::type,
typename gtl_if<typename is_polygon_90_set_type<geometry_type_2>::type>::type>::type,
polygon_90_set_view<geometry_type_1, geometry_type_2, boolean_op::BinaryOr> >::type
operator+(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_90_set_view<geometry_type_1, geometry_type_2, boolean_op::BinaryOr>
(lvalue, rvalue,
polygon_90_set_traits<geometry_type_1>::orient(lvalue),
boolean_op::BinaryOr());
}
struct y_ps90_s : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3< y_ps90_s,
typename is_polygon_90_set_type<geometry_type_1>::type,
typename is_polygon_90_set_type<geometry_type_2>::type>::type,
polygon_90_set_view<geometry_type_1, geometry_type_2, boolean_op::BinaryAnd> >::type
operator*(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_90_set_view<geometry_type_1, geometry_type_2, boolean_op::BinaryAnd>
(lvalue, rvalue,
polygon_90_set_traits<geometry_type_1>::orient(lvalue),
boolean_op::BinaryAnd());
}
struct y_ps90_a : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3< y_ps90_a,
typename is_polygon_90_set_type<geometry_type_1>::type,
typename is_polygon_90_set_type<geometry_type_2>::type>::type,
polygon_90_set_view<geometry_type_1, geometry_type_2, boolean_op::BinaryAnd> >::type
operator&(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_90_set_view<geometry_type_1, geometry_type_2, boolean_op::BinaryAnd>
(lvalue, rvalue,
polygon_90_set_traits<geometry_type_1>::orient(lvalue),
boolean_op::BinaryAnd());
}
struct y_ps90_x : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3< y_ps90_x,
typename is_polygon_90_set_type<geometry_type_1>::type,
typename is_polygon_90_set_type<geometry_type_2>::type>::type,
polygon_90_set_view<geometry_type_1, geometry_type_2, boolean_op::BinaryXor> >::type
operator^(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_90_set_view<geometry_type_1, geometry_type_2, boolean_op::BinaryXor>
(lvalue, rvalue,
polygon_90_set_traits<geometry_type_1>::orient(lvalue),
boolean_op::BinaryXor());
}
struct y_ps90_m : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3< y_ps90_m,
typename gtl_if<typename is_polygon_90_set_type<geometry_type_1>::type>::type,
typename gtl_if<typename is_polygon_90_set_type<geometry_type_2>::type>::type>::type,
polygon_90_set_view<geometry_type_1, geometry_type_2, boolean_op::BinaryNot> >::type
operator-(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_90_set_view<geometry_type_1, geometry_type_2, boolean_op::BinaryNot>
(lvalue, rvalue,
polygon_90_set_traits<geometry_type_1>::orient(lvalue),
boolean_op::BinaryNot());
}
struct y_ps90_pe : gtl_yes {};
template <typename coordinate_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and< y_ps90_pe, typename is_polygon_90_set_type<geometry_type_2>::type>::type,
polygon_90_set_data<coordinate_type_1> >::type &
operator+=(polygon_90_set_data<coordinate_type_1>& lvalue, const geometry_type_2& rvalue) {
lvalue.insert(polygon_90_set_traits<geometry_type_2>::begin(rvalue), polygon_90_set_traits<geometry_type_2>::end(rvalue),
polygon_90_set_traits<geometry_type_2>::orient(rvalue));
return lvalue;
}
struct y_ps90_be : gtl_yes {};
//
template <typename coordinate_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and< y_ps90_be, typename is_polygon_90_set_type<geometry_type_2>::type>::type,
polygon_90_set_data<coordinate_type_1> >::type &
operator|=(polygon_90_set_data<coordinate_type_1>& lvalue, const geometry_type_2& rvalue) {
return lvalue += rvalue;
}
struct y_ps90_pe2 : gtl_yes {};
//normal self assignment boolean operations
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3< y_ps90_pe2, typename is_mutable_polygon_90_set_type<geometry_type_1>::type,
typename is_polygon_90_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator+=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op<geometry_type_1, geometry_type_2, boolean_op::BinaryOr>(lvalue, rvalue);
}
struct y_ps90_be2 : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3<y_ps90_be2, typename is_mutable_polygon_90_set_type<geometry_type_1>::type,
typename is_polygon_90_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator|=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op<geometry_type_1, geometry_type_2, boolean_op::BinaryOr>(lvalue, rvalue);
}
struct y_ps90_se : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3<y_ps90_se, typename is_mutable_polygon_90_set_type<geometry_type_1>::type,
typename is_polygon_90_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator*=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op<geometry_type_1, geometry_type_2, boolean_op::BinaryAnd>(lvalue, rvalue);
}
struct y_ps90_ae : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3<y_ps90_ae, typename is_mutable_polygon_90_set_type<geometry_type_1>::type,
typename is_polygon_90_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator&=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op<geometry_type_1, geometry_type_2, boolean_op::BinaryAnd>(lvalue, rvalue);
}
struct y_ps90_xe : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3<y_ps90_xe, typename is_mutable_polygon_90_set_type<geometry_type_1>::type,
typename is_polygon_90_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator^=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op<geometry_type_1, geometry_type_2, boolean_op::BinaryXor>(lvalue, rvalue);
}
struct y_ps90_me : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3< y_ps90_me, typename is_mutable_polygon_90_set_type<geometry_type_1>::type,
typename is_polygon_90_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator-=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op<geometry_type_1, geometry_type_2, boolean_op::BinaryNot>(lvalue, rvalue);
}
struct y_ps90_rpe : gtl_yes {};
template <typename geometry_type_1, typename coordinate_type_1>
typename enable_if< typename gtl_and_3<y_ps90_rpe,
typename is_mutable_polygon_90_set_type<geometry_type_1>::type,
typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type, coordinate_concept>::type>::type,
geometry_type_1>::type &
operator+=(geometry_type_1& lvalue, coordinate_type_1 rvalue) {
return resize(lvalue, rvalue);
}
struct y_ps90_rme : gtl_yes {};
template <typename geometry_type_1, typename coordinate_type_1>
typename enable_if< typename gtl_and_3<y_ps90_rme,
typename is_mutable_polygon_90_set_type<geometry_type_1>::type,
typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type, coordinate_concept>::type>::type,
geometry_type_1>::type &
operator-=(geometry_type_1& lvalue, coordinate_type_1 rvalue) {
return resize(lvalue, -rvalue);
}
struct y_ps90_rp : gtl_yes {};
template <typename geometry_type_1, typename coordinate_type_1>
typename enable_if< typename gtl_and_3<y_ps90_rp,
typename gtl_if<typename is_mutable_polygon_90_set_type<geometry_type_1>::type>::type,
typename gtl_if<typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type, coordinate_concept>::type>::type>::type,
geometry_type_1>::type
operator+(const geometry_type_1& lvalue, coordinate_type_1 rvalue) {
geometry_type_1 retval(lvalue);
retval += rvalue;
return retval;
}
struct y_ps90_rm : gtl_yes {};
template <typename geometry_type_1, typename coordinate_type_1>
typename enable_if< typename gtl_and_3<y_ps90_rm,
typename gtl_if<typename is_mutable_polygon_90_set_type<geometry_type_1>::type>::type,
typename gtl_if<typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type, coordinate_concept>::type>::type>::type,
geometry_type_1>::type
operator-(const geometry_type_1& lvalue, coordinate_type_1 rvalue) {
geometry_type_1 retval(lvalue);
retval -= rvalue;
return retval;
}
}
}
}
#endif

View file

@ -0,0 +1,418 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_90_TOUCH_HPP
#define BOOST_POLYGON_POLYGON_90_TOUCH_HPP
namespace boost { namespace polygon{
template <typename Unit>
struct touch_90_operation {
typedef interval_data<Unit> Interval;
class TouchScanEvent {
private:
typedef std::map<Unit, std::set<int> > EventData;
EventData eventData_;
public:
// The TouchScanEvent::iterator is a lazy algorithm that accumulates
// polygon ids in a set as it is incremented through the
// scan event data structure.
// The iterator provides a forward iterator semantic only.
class iterator {
private:
typename EventData::const_iterator itr_;
std::pair<Interval, std::set<int> > ivlIds_;
bool incremented_;
public:
inline iterator() : itr_(), ivlIds_(), incremented_(false) {}
inline iterator(typename EventData::const_iterator itr,
Unit prevPos, Unit curPos, const std::set<int>& ivlIds) : itr_(itr), ivlIds_(), incremented_(false) {
ivlIds_.second = ivlIds;
ivlIds_.first = Interval(prevPos, curPos);
}
inline iterator(const iterator& that) : itr_(), ivlIds_(), incremented_(false) { (*this) = that; }
inline iterator& operator=(const iterator& that) {
itr_ = that.itr_;
ivlIds_.first = that.ivlIds_.first;
ivlIds_.second = that.ivlIds_.second;
incremented_ = that.incremented_;
return *this;
}
inline bool operator==(const iterator& that) { return itr_ == that.itr_; }
inline bool operator!=(const iterator& that) { return itr_ != that.itr_; }
inline iterator& operator++() {
//std::cout << "increment\n";
//std::cout << "state\n";
//for(std::set<int>::iterator itr = ivlIds_.second.begin(); itr != ivlIds_.second.end(); ++itr) {
// std::cout << (*itr) << " ";
//} std::cout << std::endl;
//std::cout << "update\n";
for(std::set<int>::const_iterator itr = (*itr_).second.begin();
itr != (*itr_).second.end(); ++itr) {
//std::cout << (*itr) << " ";
std::set<int>::iterator lb = ivlIds_.second.find(*itr);
if(lb != ivlIds_.second.end()) {
ivlIds_.second.erase(lb);
} else {
ivlIds_.second.insert(*itr);
}
}
//std::cout << std::endl;
//std::cout << "new state\n";
//for(std::set<int>::iterator itr = ivlIds_.second.begin(); itr != ivlIds_.second.end(); ++itr) {
// std::cout << (*itr) << " ";
//} std::cout << std::endl;
++itr_;
//ivlIds_.first = Interval(ivlIds_.first.get(HIGH), itr_->first);
incremented_ = true;
return *this;
}
inline const iterator operator++(int){
iterator tmpItr(*this);
++(*this);
return tmpItr;
}
inline std::pair<Interval, std::set<int> >& operator*() {
if(incremented_) ivlIds_.first = Interval(ivlIds_.first.get(HIGH), itr_->first);
incremented_ = false;
if(ivlIds_.second.empty())(++(*this));
if(incremented_) ivlIds_.first = Interval(ivlIds_.first.get(HIGH), itr_->first);
incremented_ = false;
return ivlIds_; }
};
inline TouchScanEvent() : eventData_() {}
template<class iT>
inline TouchScanEvent(iT begin, iT end) : eventData_() {
for( ; begin != end; ++begin){
insert(*begin);
}
}
inline TouchScanEvent(const TouchScanEvent& that) : eventData_(that.eventData_) {}
inline TouchScanEvent& operator=(const TouchScanEvent& that){
eventData_ = that.eventData_;
return *this;
}
//Insert an interval polygon id into the EventData
inline void insert(const std::pair<Interval, int>& intervalId){
insert(intervalId.first.low(), intervalId.second);
insert(intervalId.first.high(), intervalId.second);
}
//Insert an position and polygon id into EventData
inline void insert(Unit pos, int id) {
typename EventData::iterator lb = eventData_.lower_bound(pos);
if(lb != eventData_.end() && lb->first == pos) {
std::set<int>& mr (lb->second);
std::set<int>::iterator mri = mr.find(id);
if(mri == mr.end()) {
mr.insert(id);
} else {
mr.erase(id);
}
} else {
lb = eventData_.insert(lb, std::pair<Unit, std::set<int> >(pos, std::set<int>()));
(*lb).second.insert(id);
}
}
//merge this scan event with that by inserting its data
inline void insert(const TouchScanEvent& that){
typename EventData::const_iterator itr;
for(itr = that.eventData_.begin(); itr != that.eventData_.end(); ++itr) {
eventData_[(*itr).first].insert(itr->second.begin(), itr->second.end());
}
}
//Get the begin iterator over event data
inline iterator begin() const {
//std::cout << "begin\n";
if(eventData_.empty()) return end();
typename EventData::const_iterator itr = eventData_.begin();
Unit pos = itr->first;
const std::set<int>& idr = itr->second;
++itr;
return iterator(itr, pos, itr->first, idr);
}
//Get the end iterator over event data
inline iterator end() const { return iterator(eventData_.end(), 0, 0, std::set<int>()); }
inline void clear() { eventData_.clear(); }
inline Interval extents() const {
if(eventData_.empty()) return Interval();
return Interval((*(eventData_.begin())).first, (*(eventData_.rbegin())).first);
}
};
//declaration of a map of scan events by coordinate value used to store all the
//polygon data for a single layer input into the scanline algorithm
typedef std::pair<std::map<Unit, TouchScanEvent>, std::map<Unit, TouchScanEvent> > TouchSetData;
class TouchOp {
public:
typedef std::map<Unit, std::set<int> > ScanData;
typedef std::pair<Unit, std::set<int> > ElementType;
protected:
ScanData scanData_;
typename ScanData::iterator nextItr_;
public:
inline TouchOp () : scanData_(), nextItr_() { nextItr_ = scanData_.end(); }
inline TouchOp (const TouchOp& that) : scanData_(that.scanData_), nextItr_() { nextItr_ = scanData_.begin(); }
inline TouchOp& operator=(const TouchOp& that);
//moves scanline forward
inline void advanceScan() { nextItr_ = scanData_.begin(); }
//proceses the given interval and std::set<int> data
//the output data structre is a graph, the indicies in the vector correspond to graph nodes,
//the integers in the set are vector indicies and are the nodes with which that node shares an edge
template <typename graphT>
inline void processInterval(graphT& outputContainer, Interval ivl, const std::set<int>& ids, bool leadingEdge) {
//print();
typename ScanData::iterator lowItr = lookup_(ivl.low());
typename ScanData::iterator highItr = lookup_(ivl.high());
//std::cout << "Interval: " << ivl << std::endl;
//for(std::set<int>::const_iterator itr = ids.begin(); itr != ids.end(); ++itr)
// std::cout << (*itr) << " ";
//std::cout << std::endl;
//add interval to scan data if it is past the end
if(lowItr == scanData_.end()) {
//std::cout << "case0" << std::endl;
lowItr = insert_(ivl.low(), ids);
evaluateBorder_(outputContainer, ids, ids);
highItr = insert_(ivl.high(), std::set<int>());
return;
}
//ensure that highItr points to the end of the ivl
if(highItr == scanData_.end() || (*highItr).first > ivl.high()) {
//std::cout << "case1" << std::endl;
//std::cout << highItr->first << std::endl;
std::set<int> value = std::set<int>();
if(highItr != scanData_.begin()) {
--highItr;
//std::cout << highItr->first << std::endl;
//std::cout << "high set size " << highItr->second.size() << std::endl;
value = highItr->second;
}
nextItr_ = highItr;
highItr = insert_(ivl.high(), value);
} else {
//evaluate border with next higher interval
//std::cout << "case1a" << std::endl;
if(leadingEdge)evaluateBorder_(outputContainer, highItr->second, ids);
}
//split the low interval if needed
if(lowItr->first > ivl.low()) {
//std::cout << "case2" << std::endl;
if(lowItr != scanData_.begin()) {
//std::cout << "case3" << std::endl;
--lowItr;
nextItr_ = lowItr;
//std::cout << lowItr->first << " " << lowItr->second.size() << std::endl;
lowItr = insert_(ivl.low(), lowItr->second);
} else {
//std::cout << "case4" << std::endl;
nextItr_ = lowItr;
lowItr = insert_(ivl.low(), std::set<int>());
}
} else {
//evaluate border with next higher interval
//std::cout << "case2a" << std::endl;
typename ScanData::iterator nextLowerItr = lowItr;
if(leadingEdge && nextLowerItr != scanData_.begin()){
--nextLowerItr;
evaluateBorder_(outputContainer, nextLowerItr->second, ids);
}
}
//std::cout << "low: " << lowItr->first << " high: " << highItr->first << std::endl;
//print();
//process scan data intersecting interval
for(typename ScanData::iterator itr = lowItr; itr != highItr; ){
//std::cout << "case5" << std::endl;
//std::cout << itr->first << std::endl;
std::set<int>& beforeIds = itr->second;
++itr;
evaluateInterval_(outputContainer, beforeIds, ids, leadingEdge);
}
//print();
//merge the bottom interval with the one below if they have the same count
if(lowItr != scanData_.begin()){
//std::cout << "case6" << std::endl;
typename ScanData::iterator belowLowItr = lowItr;
--belowLowItr;
if(belowLowItr->second == lowItr->second) {
//std::cout << "case7" << std::endl;
scanData_.erase(lowItr);
}
}
//merge the top interval with the one above if they have the same count
if(highItr != scanData_.begin()) {
//std::cout << "case8" << std::endl;
typename ScanData::iterator beforeHighItr = highItr;
--beforeHighItr;
if(beforeHighItr->second == highItr->second) {
//std::cout << "case9" << std::endl;
scanData_.erase(highItr);
highItr = beforeHighItr;
++highItr;
}
}
//print();
nextItr_ = highItr;
}
// inline void print() const {
// for(typename ScanData::const_iterator itr = scanData_.begin(); itr != scanData_.end(); ++itr) {
// std::cout << itr->first << ": ";
// for(std::set<int>::const_iterator sitr = itr->second.begin();
// sitr != itr->second.end(); ++sitr){
// std::cout << *sitr << " ";
// }
// std::cout << std::endl;
// }
// }
private:
inline typename ScanData::iterator lookup_(Unit pos){
if(nextItr_ != scanData_.end() && nextItr_->first >= pos) {
return nextItr_;
}
return nextItr_ = scanData_.lower_bound(pos);
}
inline typename ScanData::iterator insert_(Unit pos, const std::set<int>& ids){
//std::cout << "inserting " << ids.size() << " ids at: " << pos << std::endl;
return nextItr_ = scanData_.insert(nextItr_, std::pair<Unit, std::set<int> >(pos, ids));
}
template <typename graphT>
inline void evaluateInterval_(graphT& outputContainer, std::set<int>& ids,
const std::set<int>& changingIds, bool leadingEdge) {
for(std::set<int>::const_iterator ciditr = changingIds.begin(); ciditr != changingIds.end(); ++ciditr){
//std::cout << "evaluateInterval " << (*ciditr) << std::endl;
evaluateId_(outputContainer, ids, *ciditr, leadingEdge);
}
}
template <typename graphT>
inline void evaluateBorder_(graphT& outputContainer, const std::set<int>& ids, const std::set<int>& changingIds) {
for(std::set<int>::const_iterator ciditr = changingIds.begin(); ciditr != changingIds.end(); ++ciditr){
//std::cout << "evaluateBorder " << (*ciditr) << std::endl;
evaluateBorderId_(outputContainer, ids, *ciditr);
}
}
template <typename graphT>
inline void evaluateBorderId_(graphT& outputContainer, const std::set<int>& ids, int changingId) {
for(std::set<int>::const_iterator scanItr = ids.begin(); scanItr != ids.end(); ++scanItr) {
//std::cout << "create edge: " << changingId << " " << *scanItr << std::endl;
if(changingId != *scanItr){
outputContainer[changingId].insert(*scanItr);
outputContainer[*scanItr].insert(changingId);
}
}
}
template <typename graphT>
inline void evaluateId_(graphT& outputContainer, std::set<int>& ids, int changingId, bool leadingEdge) {
//std::cout << "changingId: " << changingId << std::endl;
//for( std::set<int>::iterator itr = ids.begin(); itr != ids.end(); ++itr){
// std::cout << *itr << " ";
//}std::cout << std::endl;
std::set<int>::iterator lb = ids.lower_bound(changingId);
if(lb == ids.end() || (*lb) != changingId) {
if(leadingEdge) {
//std::cout << "insert\n";
//insert and add to output
for(std::set<int>::iterator scanItr = ids.begin(); scanItr != ids.end(); ++scanItr) {
//std::cout << "create edge: " << changingId << " " << *scanItr << std::endl;
if(changingId != *scanItr){
outputContainer[changingId].insert(*scanItr);
outputContainer[*scanItr].insert(changingId);
}
}
ids.insert(changingId);
}
} else {
if(!leadingEdge){
//std::cout << "erase\n";
ids.erase(lb);
}
}
}
};
template <typename graphT>
static inline void processEvent(graphT& outputContainer, TouchOp& op, const TouchScanEvent& data, bool leadingEdge) {
for(typename TouchScanEvent::iterator itr = data.begin(); itr != data.end(); ++itr) {
//std::cout << "processInterval" << std::endl;
op.processInterval(outputContainer, (*itr).first, (*itr).second, leadingEdge);
}
}
template <typename graphT>
static inline void performTouch(graphT& outputContainer, const TouchSetData& data) {
typename std::map<Unit, TouchScanEvent>::const_iterator leftItr = data.first.begin();
typename std::map<Unit, TouchScanEvent>::const_iterator rightItr = data.second.begin();
typename std::map<Unit, TouchScanEvent>::const_iterator leftEnd = data.first.end();
typename std::map<Unit, TouchScanEvent>::const_iterator rightEnd = data.second.end();
TouchOp op;
while(leftItr != leftEnd || rightItr != rightEnd) {
//std::cout << "loop" << std::endl;
op.advanceScan();
//rightItr cannont be at end if leftItr is not at end
if(leftItr != leftEnd && rightItr != rightEnd &&
leftItr->first <= rightItr->first) {
//std::cout << "case1" << std::endl;
//std::cout << leftItr ->first << std::endl;
processEvent(outputContainer, op, leftItr->second, true);
++leftItr;
} else {
//std::cout << "case2" << std::endl;
//std::cout << rightItr ->first << std::endl;
processEvent(outputContainer, op, rightItr->second, false);
++rightItr;
}
}
}
template <class iT>
static inline void populateTouchSetData(TouchSetData& data, iT beginData, iT endData, int id) {
Unit prevPos = ((std::numeric_limits<Unit>::max)());
Unit prevY = prevPos;
int count = 0;
for(iT itr = beginData; itr != endData; ++itr) {
Unit pos = (*itr).first;
if(pos != prevPos) {
prevPos = pos;
prevY = (*itr).second.first;
count = (*itr).second.second;
continue;
}
Unit y = (*itr).second.first;
if(count != 0 && y != prevY) {
std::pair<Interval, int> element(Interval(prevY, y), id);
if(count > 0) {
data.first[pos].insert(element);
} else {
data.second[pos].insert(element);
}
}
prevY = y;
count += (*itr).second.second;
}
}
static inline void populateTouchSetData(TouchSetData& data, const std::vector<std::pair<Unit, std::pair<Unit, int> > >& inputData, int id) {
populateTouchSetData(data, inputData.begin(), inputData.end(), id);
}
};
}
}
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,222 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_SET_VIEW_HPP
#define BOOST_POLYGON_POLYGON_SET_VIEW_HPP
namespace boost { namespace polygon{
template <typename coordinate_type>
inline void polygon_set_data<coordinate_type>::clean() const {
if(dirty_) {
//polygon_45_set_data<coordinate_type> tmp;
//very important:
//the 45 degree algorithm does not satisfy
//the precondition of arbitrary polygon formation
//that vertices be "linearly consistent"
//therefore it doesn't work to fall back on 45-degree
//booleans for arbitrary angle polygons
//if(0) { //downcast(tmp) ) {
// tmp.clean();
// data_.clear();
// is_45_ = true;
// polygon_set_data<coordinate_type> tmp2;
// tmp2.insert(tmp);
// data_.swap(tmp2.data_);
// dirty_ = false;
// sort();
//} else {
sort();
arbitrary_boolean_op<coordinate_type> abo;
polygon_set_data<coordinate_type> tmp2;
abo.execute(tmp2, begin(), end(), end(), end(), 0);
data_.swap(tmp2.data_);
is_45_ = tmp2.is_45_;
dirty_ = false;
//}
}
}
template <>
inline void polygon_set_data<double>::clean() const {
if(dirty_) {
sort();
arbitrary_boolean_op<double> abo;
polygon_set_data<double> tmp2;
abo.execute(tmp2, begin(), end(), end(), end(), 0);
data_.swap(tmp2.data_);
is_45_ = tmp2.is_45_;
dirty_ = false;
}
}
template <typename value_type, typename arg_type>
inline void insert_into_view_arg(value_type& dest, const arg_type& arg);
template <typename ltype, typename rtype, int op_type>
class polygon_set_view;
template <typename ltype, typename rtype, int op_type>
struct polygon_set_traits<polygon_set_view<ltype, rtype, op_type> > {
typedef typename polygon_set_view<ltype, rtype, op_type>::coordinate_type coordinate_type;
typedef typename polygon_set_view<ltype, rtype, op_type>::iterator_type iterator_type;
typedef typename polygon_set_view<ltype, rtype, op_type>::operator_arg_type operator_arg_type;
static inline iterator_type begin(const polygon_set_view<ltype, rtype, op_type>& polygon_set);
static inline iterator_type end(const polygon_set_view<ltype, rtype, op_type>& polygon_set);
static inline bool clean(const polygon_set_view<ltype, rtype, op_type>& polygon_set);
static inline bool sort(const polygon_set_view<ltype, rtype, op_type>& polygon_set);
};
//template <typename value_type, typename geometry_type_1, typename geometry_type_2, int op_type>
//void execute_boolean_op(value_type& output_, const geometry_type_1& lvalue_, const geometry_type_2& rvalue_,
// double coord) {
// typedef geometry_type_1 ltype;
// typedef geometry_type_2 rtype;
// typedef typename polygon_set_traits<ltype>::coordinate_type coordinate_type;
// value_type linput_;
// value_type rinput_;
// insert_into_view_arg(linput_, lvalue_);
// insert_into_view_arg(rinput_, rvalue_);
// arbitrary_boolean_op<coordinate_type> abo;
// abo.execute(output_, linput_.begin(), linput_.end(),
// rinput_.begin(), rinput_.end(), op_type);
//}
template <typename value_type, typename geometry_type_1, typename geometry_type_2, int op_type>
void execute_boolean_op(value_type& output_, const geometry_type_1& lvalue_, const geometry_type_2& rvalue_) {
typedef geometry_type_1 ltype;
typedef geometry_type_2 rtype;
typedef typename polygon_set_traits<ltype>::coordinate_type coordinate_type;
value_type linput_;
value_type rinput_;
insert_into_view_arg(linput_, lvalue_);
insert_into_view_arg(rinput_, rvalue_);
polygon_45_set_data<coordinate_type> l45, r45, o45;
// if(linput_.downcast(l45) && rinput_.downcast(r45)) {
// //the op codes are screwed up between 45 and arbitrary
//#ifdef BOOST_POLYGON_MSVC
//#pragma warning (push)
//#pragma warning (disable: 4127)
//#endif
// if(op_type < 2)
// l45.template applyAdaptiveBoolean_<op_type>(o45, r45);
// else if(op_type == 2)
// l45.template applyAdaptiveBoolean_<3>(o45, r45);
// else
// l45.template applyAdaptiveBoolean_<2>(o45, r45);
//#ifdef BOOST_POLYGON_MSVC
//#pragma warning (pop)
//#endif
// output_.insert(o45);
// } else {
arbitrary_boolean_op<coordinate_type> abo;
abo.execute(output_, linput_.begin(), linput_.end(),
rinput_.begin(), rinput_.end(), op_type);
// }
}
template <typename ltype, typename rtype, int op_type>
class polygon_set_view {
public:
typedef typename polygon_set_traits<ltype>::coordinate_type coordinate_type;
typedef polygon_set_data<coordinate_type> value_type;
typedef typename value_type::iterator_type iterator_type;
typedef polygon_set_view operator_arg_type;
private:
const ltype& lvalue_;
const rtype& rvalue_;
mutable value_type output_;
mutable bool evaluated_;
polygon_set_view& operator=(const polygon_set_view&);
public:
polygon_set_view(const ltype& lvalue,
const rtype& rvalue ) :
lvalue_(lvalue), rvalue_(rvalue), output_(), evaluated_(false) {}
// get iterator to begin vertex data
public:
const value_type& value() const {
if(!evaluated_) {
evaluated_ = true;
execute_boolean_op<value_type, ltype, rtype, op_type>(output_, lvalue_, rvalue_);
}
return output_;
}
public:
iterator_type begin() const { return value().begin(); }
iterator_type end() const { return value().end(); }
bool dirty() const { return false; } //result of a boolean is clean
bool sorted() const { return true; } //result of a boolean is sorted
void sort() const {} //is always sorted
};
template <typename ltype, typename rtype, int op_type>
typename polygon_set_traits<polygon_set_view<ltype, rtype, op_type> >::iterator_type
polygon_set_traits<polygon_set_view<ltype, rtype, op_type> >::
begin(const polygon_set_view<ltype, rtype, op_type>& polygon_set) {
return polygon_set.begin();
}
template <typename ltype, typename rtype, int op_type>
typename polygon_set_traits<polygon_set_view<ltype, rtype, op_type> >::iterator_type
polygon_set_traits<polygon_set_view<ltype, rtype, op_type> >::
end(const polygon_set_view<ltype, rtype, op_type>& polygon_set) {
return polygon_set.end();
}
template <typename ltype, typename rtype, int op_type>
bool polygon_set_traits<polygon_set_view<ltype, rtype, op_type> >::
clean(const polygon_set_view<ltype, rtype, op_type>& ) {
return true; }
template <typename ltype, typename rtype, int op_type>
bool polygon_set_traits<polygon_set_view<ltype, rtype, op_type> >::
sort(const polygon_set_view<ltype, rtype, op_type>& ) {
return true; }
template <typename value_type, typename arg_type>
inline void insert_into_view_arg(value_type& dest, const arg_type& arg) {
typedef typename polygon_set_traits<arg_type>::iterator_type literator;
literator itr1, itr2;
itr1 = polygon_set_traits<arg_type>::begin(arg);
itr2 = polygon_set_traits<arg_type>::end(arg);
dest.insert(itr1, itr2);
}
template <typename geometry_type_1, typename geometry_type_2, int op_type>
geometry_type_1& self_assignment_boolean_op(geometry_type_1& lvalue_, const geometry_type_2& rvalue_) {
typedef geometry_type_1 ltype;
typedef typename polygon_set_traits<ltype>::coordinate_type coordinate_type;
typedef polygon_set_data<coordinate_type> value_type;
value_type output_;
execute_boolean_op<value_type, geometry_type_1, geometry_type_2, op_type>(output_, lvalue_, rvalue_);
polygon_set_mutable_traits<geometry_type_1>::set(lvalue_, output_.begin(), output_.end());
return lvalue_;
}
// copy constructor
template <typename coordinate_type>
template <typename ltype, typename rtype, int op_type>
polygon_set_data<coordinate_type>::polygon_set_data(const polygon_set_view<ltype, rtype, op_type>& that) :
data_(that.value().data_), dirty_(that.value().dirty_), unsorted_(that.value().unsorted_), is_45_(that.value().is_45_) {}
// equivalence operator
template <typename coordinate_type>
inline bool polygon_set_data<coordinate_type>::operator==(const polygon_set_data<coordinate_type>& p) const {
typedef polygon_set_data<coordinate_type> value_type;
value_type output_;
execute_boolean_op<value_type, value_type, value_type, 2>(output_, (*this), p);
return output_.data_.empty();
}
template <typename ltype, typename rtype, int op_type>
struct geometry_concept<polygon_set_view<ltype, rtype, op_type> > { typedef polygon_set_concept type; };
}
}
#endif

View file

@ -0,0 +1,116 @@
// Copyright 2011, Andrew Ross
//
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
#ifndef BOOST_POLYGON_DETAIL_SIMPLIFY_HPP
#define BOOST_POLYGON_DETAIL_SIMPLIFY_HPP
#include <vector>
namespace boost { namespace polygon { namespace detail { namespace simplify_detail {
// Does a simplification/optimization pass on the polygon. If a given
// vertex lies within "len" of the line segment joining its neighbor
// vertices, it is removed.
template <typename T> //T is a model of point concept
std::size_t simplify(std::vector<T>& dst, const std::vector<T>& src,
typename coordinate_traits<
typename point_traits<T>::coordinate_type
>::coordinate_distance len)
{
using namespace boost::polygon;
typedef typename point_traits<T>::coordinate_type coordinate_type;
typedef typename coordinate_traits<coordinate_type>::area_type ftype;
typedef typename std::vector<T>::const_iterator iter;
std::vector<T> out;
out.reserve(src.size());
dst = src;
std::size_t final_result = 0;
std::size_t orig_size = src.size();
//I can't use == if T doesn't provide it, so use generic point concept compare
bool closed = equivalence(src.front(), src.back());
//we need to keep smoothing until we don't find points to remove
//because removing points in the first iteration through the
//polygon may leave it in a state where more removal is possible
bool not_done = true;
while(not_done) {
if(dst.size() < 3) {
dst.clear();
return orig_size;
}
// Start with the second, test for the last point
// explicitly, and exit after looping back around to the first.
ftype len2 = ftype(len) * ftype(len);
for(iter prev=dst.begin(), i=prev+1, next; /**/; i = next) {
next = i+1;
if(next == dst.end())
next = dst.begin();
// points A, B, C
ftype ax = x(*prev), ay = y(*prev);
ftype bx = x(*i), by = y(*i);
ftype cx = x(*next), cy = y(*next);
// vectors AB, BC and AC:
ftype abx = bx-ax, aby = by-ay;
ftype bcx = cx-bx, bcy = cy-by;
ftype acx = cx-ax, acy = cy-ay;
// dot products
ftype ab_ab = abx*abx + aby*aby;
ftype bc_bc = bcx*bcx + bcy*bcy;
ftype ac_ac = acx*acx + acy*acy;
ftype ab_ac = abx*acx + aby*acy;
// projection of AB along AC
ftype projf = ab_ac / ac_ac;
ftype projx = acx * projf, projy = acy * projf;
// perpendicular vector from the line AC to point B (i.e. AB - proj)
ftype perpx = abx - projx, perpy = aby - projy;
// Squared fractional distance of projection. FIXME: can
// remove this division, the decisions below can be made with
// just the sign of the quotient and a check to see if
// abs(numerator) is greater than abs(divisor).
ftype f2 = (projx*acx + projy*acx) / ac_ac;
// Square of the relevant distance from point B:
ftype dist2;
if (f2 < 0) dist2 = ab_ab;
else if(f2 > 1) dist2 = bc_bc;
else dist2 = perpx*perpx + perpy*perpy;
if(dist2 > len2) {
prev = i; // bump prev, we didn't remove the segment
out.push_back(*i);
}
if(i == dst.begin())
break;
}
std::size_t result = dst.size() - out.size();
if(result == 0) {
not_done = false;
} else {
final_result += result;
dst = out;
out.clear();
}
} //end of while loop
if(closed) {
//if the input was closed we want the output to be closed
--final_result;
dst.push_back(dst.front());
}
return final_result;
}
}}}}
#endif

View file

@ -0,0 +1,67 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_SORT_ADAPTOR_HPP
#define BOOST_POLYGON_SORT_ADAPTOR_HPP
#ifdef __ICC
#pragma warning(disable:2022)
#pragma warning(disable:2023)
#endif
#include <algorithm>
//! @brief polygon_sort_adaptor default implementation that calls std::sort
namespace boost {
namespace polygon {
template<typename iterator_type>
struct dummy_to_delay_instantiation{
typedef int unit_type; // default GTL unit
};
//! @brief polygon_sort_adaptor default implementation that calls std::sort
template<typename T>
struct polygon_sort_adaptor {
//! @brief wrapper that mimics std::sort() function and takes
// the same arguments
template<typename RandomAccessIterator_Type>
static void sort(RandomAccessIterator_Type _First,
RandomAccessIterator_Type _Last)
{
std::sort(_First, _Last);
}
//! @brief wrapper that mimics std::sort() function overload and takes
// the same arguments
template<typename RandomAccessIterator_Type, typename Pred_Type>
static void sort(RandomAccessIterator_Type _First,
RandomAccessIterator_Type _Last,
const Pred_Type& _Comp)
{
std::sort(_First, _Last, _Comp);
}
};
//! @brief user level wrapper for sorting quantities
template <typename iter_type>
void polygon_sort(iter_type _b_, iter_type _e_)
{
polygon_sort_adaptor<typename dummy_to_delay_instantiation<iter_type>::unit_type>::sort(_b_, _e_);
}
//! @brief user level wrapper for sorting quantities that takes predicate
// as additional argument
template <typename iter_type, typename pred_type>
void polygon_sort(iter_type _b_, iter_type _e_, const pred_type& _pred_)
{
polygon_sort_adaptor<typename dummy_to_delay_instantiation<iter_type>::unit_type>::sort(_b_, _e_, _pred_);
}
} // namespace polygon
} // namespace boost
#endif

View file

@ -0,0 +1,588 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_PROPERTY_MERGE_HPP
#define BOOST_POLYGON_PROPERTY_MERGE_HPP
namespace boost { namespace polygon{
template <typename coordinate_type>
class property_merge_point {
private:
coordinate_type x_, y_;
public:
inline property_merge_point() : x_(), y_() {}
inline property_merge_point(coordinate_type x, coordinate_type y) : x_(x), y_(y) {}
//use builtin assign and copy
inline bool operator==(const property_merge_point& that) const { return x_ == that.x_ && y_ == that.y_; }
inline bool operator!=(const property_merge_point& that) const { return !((*this) == that); }
inline bool operator<(const property_merge_point& that) const {
if(x_ < that.x_) return true;
if(x_ > that.x_) return false;
return y_ < that.y_;
}
inline coordinate_type x() const { return x_; }
inline coordinate_type y() const { return y_; }
inline void x(coordinate_type value) { x_ = value; }
inline void y(coordinate_type value) { y_ = value; }
};
template <typename coordinate_type>
class property_merge_interval {
private:
coordinate_type low_, high_;
public:
inline property_merge_interval() : low_(), high_() {}
inline property_merge_interval(coordinate_type low, coordinate_type high) : low_(low), high_(high) {}
//use builtin assign and copy
inline bool operator==(const property_merge_interval& that) const { return low_ == that.low_ && high_ == that.high_; }
inline bool operator!=(const property_merge_interval& that) const { return !((*this) == that); }
inline bool operator<(const property_merge_interval& that) const {
if(low_ < that.low_) return true;
if(low_ > that.low_) return false;
return high_ < that.high_;
}
inline coordinate_type low() const { return low_; }
inline coordinate_type high() const { return high_; }
inline void low(coordinate_type value) { low_ = value; }
inline void high(coordinate_type value) { high_ = value; }
};
template <typename coordinate_type, typename property_type, typename polygon_set_type, typename keytype = std::set<property_type> >
class merge_scanline {
public:
//definitions
typedef keytype property_set;
typedef std::vector<std::pair<property_type, int> > property_map;
typedef std::pair<property_merge_point<coordinate_type>, std::pair<property_type, int> > vertex_property;
typedef std::pair<property_merge_point<coordinate_type>, property_map> vertex_data;
typedef std::vector<vertex_property> property_merge_data;
//typedef std::map<property_set, polygon_set_type> Result;
typedef std::map<coordinate_type, property_map> scanline_type;
typedef typename scanline_type::iterator scanline_iterator;
typedef std::pair<property_merge_interval<coordinate_type>, std::pair<property_set, property_set> > edge_property;
typedef std::vector<edge_property> edge_property_vector;
//static public member functions
template <typename iT, typename orientation_2d_type>
static inline void
populate_property_merge_data(property_merge_data& pmd, iT input_begin, iT input_end,
const property_type& property, orientation_2d_type orient) {
for( ; input_begin != input_end; ++input_begin) {
std::pair<property_merge_point<coordinate_type>, std::pair<property_type, int> > element;
if(orient == HORIZONTAL)
element.first = property_merge_point<coordinate_type>((*input_begin).second.first, (*input_begin).first);
else
element.first = property_merge_point<coordinate_type>((*input_begin).first, (*input_begin).second.first);
element.second.first = property;
element.second.second = (*input_begin).second.second;
pmd.push_back(element);
}
}
//public member functions
merge_scanline() : output(), scanline(), currentVertex(), tmpVector(), previousY(), countFromBelow(), scanlinePosition() {}
merge_scanline(const merge_scanline& that) :
output(that.output),
scanline(that.scanline),
currentVertex(that.currentVertex),
tmpVector(that.tmpVector),
previousY(that.previousY),
countFromBelow(that.countFromBelow),
scanlinePosition(that.scanlinePosition)
{}
merge_scanline& operator=(const merge_scanline& that) {
output = that.output;
scanline = that.scanline;
currentVertex = that.currentVertex;
tmpVector = that.tmpVector;
previousY = that.previousY;
countFromBelow = that.countFromBelow;
scanlinePosition = that.scanlinePosition;
return *this;
}
template <typename result_type>
inline void perform_merge(result_type& result, property_merge_data& data) {
if(data.empty()) return;
//sort
polygon_sort(data.begin(), data.end(), less_vertex_data<vertex_property>());
//scanline
bool firstIteration = true;
scanlinePosition = scanline.end();
for(std::size_t i = 0; i < data.size(); ++i) {
if(firstIteration) {
mergeProperty(currentVertex.second, data[i].second);
currentVertex.first = data[i].first;
firstIteration = false;
} else {
if(data[i].first != currentVertex.first) {
if(data[i].first.x() != currentVertex.first.x()) {
processVertex(output);
//std::cout << scanline.size() << " ";
countFromBelow.clear(); //should already be clear
writeOutput(currentVertex.first.x(), result, output);
currentVertex.second.clear();
mergeProperty(currentVertex.second, data[i].second);
currentVertex.first = data[i].first;
//std::cout << assertRedundant(scanline) << "/" << scanline.size() << " ";
} else {
processVertex(output);
currentVertex.second.clear();
mergeProperty(currentVertex.second, data[i].second);
currentVertex.first = data[i].first;
}
} else {
mergeProperty(currentVertex.second, data[i].second);
}
}
}
processVertex(output);
writeOutput(currentVertex.first.x(), result, output);
//std::cout << assertRedundant(scanline) << "/" << scanline.size() << "\n";
//std::cout << scanline.size() << "\n";
}
private:
//private supporting types
template <class T>
class less_vertex_data {
public:
less_vertex_data() {}
bool operator()(const T& lvalue, const T& rvalue) const {
if(lvalue.first.x() < rvalue.first.x()) return true;
if(lvalue.first.x() > rvalue.first.x()) return false;
if(lvalue.first.y() < rvalue.first.y()) return true;
return false;
}
};
template <typename T>
struct lessPropertyCount {
lessPropertyCount() {}
bool operator()(const T& a, const T& b) {
return a.first < b.first;
}
};
//private static member functions
static inline void mergeProperty(property_map& lvalue, std::pair<property_type, int>& rvalue) {
typename property_map::iterator itr = std::lower_bound(lvalue.begin(), lvalue.end(), rvalue,
lessPropertyCount<std::pair<property_type, int> >());
if(itr == lvalue.end() ||
(*itr).first != rvalue.first) {
lvalue.insert(itr, rvalue);
} else {
(*itr).second += rvalue.second;
if((*itr).second == 0)
lvalue.erase(itr);
}
// if(assertSorted(lvalue)) {
// std::cout << "in mergeProperty\n";
// exit(0);
// }
}
// static inline bool assertSorted(property_map& pset) {
// bool result = false;
// for(std::size_t i = 1; i < pset.size(); ++i) {
// if(pset[i] < pset[i-1]) {
// std::cout << "Out of Order Error ";
// result = true;
// }
// if(pset[i].first == pset[i-1].first) {
// std::cout << "Duplicate Property Error ";
// result = true;
// }
// if(pset[0].second == 0 || pset[1].second == 0) {
// std::cout << "Empty Property Error ";
// result = true;
// }
// }
// return result;
// }
static inline void setProperty(property_set& pset, property_map& pmap) {
for(typename property_map::iterator itr = pmap.begin(); itr != pmap.end(); ++itr) {
if((*itr).second > 0) {
pset.insert(pset.end(), (*itr).first);
}
}
}
//private data members
edge_property_vector output;
scanline_type scanline;
vertex_data currentVertex;
property_map tmpVector;
coordinate_type previousY;
property_map countFromBelow;
scanline_iterator scanlinePosition;
//private member functions
inline void mergeCount(property_map& lvalue, property_map& rvalue) {
typename property_map::iterator litr = lvalue.begin();
typename property_map::iterator ritr = rvalue.begin();
tmpVector.clear();
while(litr != lvalue.end() && ritr != rvalue.end()) {
if((*litr).first <= (*ritr).first) {
if(!tmpVector.empty() &&
(*litr).first == tmpVector.back().first) {
tmpVector.back().second += (*litr).second;
} else {
tmpVector.push_back(*litr);
}
++litr;
} else if((*ritr).first <= (*litr).first) {
if(!tmpVector.empty() &&
(*ritr).first == tmpVector.back().first) {
tmpVector.back().second += (*ritr).second;
} else {
tmpVector.push_back(*ritr);
}
++ritr;
}
}
while(litr != lvalue.end()) {
if(!tmpVector.empty() &&
(*litr).first == tmpVector.back().first) {
tmpVector.back().second += (*litr).second;
} else {
tmpVector.push_back(*litr);
}
++litr;
}
while(ritr != rvalue.end()) {
if(!tmpVector.empty() &&
(*ritr).first == tmpVector.back().first) {
tmpVector.back().second += (*ritr).second;
} else {
tmpVector.push_back(*ritr);
}
++ritr;
}
lvalue.clear();
for(std::size_t i = 0; i < tmpVector.size(); ++i) {
if(tmpVector[i].second != 0) {
lvalue.push_back(tmpVector[i]);
}
}
// if(assertSorted(lvalue)) {
// std::cout << "in mergeCount\n";
// exit(0);
// }
}
inline void processVertex(edge_property_vector& output) {
if(!countFromBelow.empty()) {
//we are processing an interval of change in scanline state between
//previous vertex position and current vertex position where
//count from below represents the change on the interval
//foreach scanline element from previous to current we
//write the interval on the scanline that is changing
//the old value and the new value to output
property_merge_interval<coordinate_type> currentInterval(previousY, currentVertex.first.y());
coordinate_type currentY = currentInterval.low();
if(scanlinePosition == scanline.end() ||
(*scanlinePosition).first != previousY) {
scanlinePosition = scanline.lower_bound(previousY);
}
scanline_iterator previousScanlinePosition = scanlinePosition;
++scanlinePosition;
while(scanlinePosition != scanline.end()) {
coordinate_type elementY = (*scanlinePosition).first;
if(elementY <= currentInterval.high()) {
property_map& countOnLeft = (*previousScanlinePosition).second;
edge_property element;
output.push_back(element);
output.back().first = property_merge_interval<coordinate_type>((*previousScanlinePosition).first, elementY);
setProperty(output.back().second.first, countOnLeft);
mergeCount(countOnLeft, countFromBelow);
setProperty(output.back().second.second, countOnLeft);
if(output.back().second.first == output.back().second.second) {
output.pop_back(); //it was an internal vertical edge, not to be output
}
else if(output.size() > 1) {
edge_property& secondToLast = output[output.size()-2];
if(secondToLast.first.high() == output.back().first.low() &&
secondToLast.second.first == output.back().second.first &&
secondToLast.second.second == output.back().second.second) {
//merge output onto previous output because properties are
//identical on both sides implying an internal horizontal edge
secondToLast.first.high(output.back().first.high());
output.pop_back();
}
}
if(previousScanlinePosition == scanline.begin()) {
if(countOnLeft.empty()) {
scanline.erase(previousScanlinePosition);
}
} else {
scanline_iterator tmpitr = previousScanlinePosition;
--tmpitr;
if((*tmpitr).second == (*previousScanlinePosition).second)
scanline.erase(previousScanlinePosition);
}
} else if(currentY < currentInterval.high()){
//elementY > currentInterval.high()
//split the interval between previous and current scanline elements
std::pair<coordinate_type, property_map> elementScan;
elementScan.first = currentInterval.high();
elementScan.second = (*previousScanlinePosition).second;
scanlinePosition = scanline.insert(scanlinePosition, elementScan);
continue;
} else {
break;
}
previousScanlinePosition = scanlinePosition;
currentY = previousY = elementY;
++scanlinePosition;
if(scanlinePosition == scanline.end() &&
currentY < currentInterval.high()) {
//insert a new element for top of range
std::pair<coordinate_type, property_map> elementScan;
elementScan.first = currentInterval.high();
scanlinePosition = scanline.insert(scanline.end(), elementScan);
}
}
if(scanlinePosition == scanline.end() &&
currentY < currentInterval.high()) {
//handle case where we iterated to end of the scanline
//we need to insert an element into the scanline at currentY
//with property value coming from below
//and another one at currentInterval.high() with empty property value
mergeCount(scanline[currentY], countFromBelow);
std::pair<coordinate_type, property_map> elementScan;
elementScan.first = currentInterval.high();
scanline.insert(scanline.end(), elementScan);
edge_property element;
output.push_back(element);
output.back().first = property_merge_interval<coordinate_type>(currentY, currentInterval.high());
setProperty(output.back().second.second, countFromBelow);
mergeCount(countFromBelow, currentVertex.second);
} else {
mergeCount(countFromBelow, currentVertex.second);
if(countFromBelow.empty()) {
if(previousScanlinePosition == scanline.begin()) {
if((*previousScanlinePosition).second.empty()) {
scanline.erase(previousScanlinePosition);
//previousScanlinePosition = scanline.end();
//std::cout << "ERASE_A ";
}
} else {
scanline_iterator tmpitr = previousScanlinePosition;
--tmpitr;
if((*tmpitr).second == (*previousScanlinePosition).second) {
scanline.erase(previousScanlinePosition);
//previousScanlinePosition = scanline.end();
//std::cout << "ERASE_B ";
}
}
}
}
} else {
//count from below is empty, we are starting a new interval of change
countFromBelow = currentVertex.second;
scanlinePosition = scanline.lower_bound(currentVertex.first.y());
if(scanlinePosition != scanline.end()) {
if((*scanlinePosition).first != currentVertex.first.y()) {
if(scanlinePosition != scanline.begin()) {
//decrement to get the lower position of the first interval this vertex intersects
--scanlinePosition;
//insert a new element into the scanline for the incoming vertex
property_map& countOnLeft = (*scanlinePosition).second;
std::pair<coordinate_type, property_map> element(currentVertex.first.y(), countOnLeft);
scanlinePosition = scanline.insert(scanlinePosition, element);
} else {
property_map countOnLeft;
std::pair<coordinate_type, property_map> element(currentVertex.first.y(), countOnLeft);
scanlinePosition = scanline.insert(scanlinePosition, element);
}
}
} else {
property_map countOnLeft;
std::pair<coordinate_type, property_map> element(currentVertex.first.y(), countOnLeft);
scanlinePosition = scanline.insert(scanlinePosition, element);
}
}
previousY = currentVertex.first.y();
}
template <typename T>
inline int assertRedundant(T& t) {
if(t.empty()) return 0;
int count = 0;
typename T::iterator itr = t.begin();
if((*itr).second.empty())
++count;
typename T::iterator itr2 = itr;
++itr2;
while(itr2 != t.end()) {
if((*itr).second == (*itr2).second)
++count;
itr = itr2;
++itr2;
}
return count;
}
template <typename T>
inline void performExtract(T& result, property_merge_data& data) {
if(data.empty()) return;
//sort
polygon_sort(data.begin(), data.end(), less_vertex_data<vertex_property>());
//scanline
bool firstIteration = true;
scanlinePosition = scanline.end();
for(std::size_t i = 0; i < data.size(); ++i) {
if(firstIteration) {
mergeProperty(currentVertex.second, data[i].second);
currentVertex.first = data[i].first;
firstIteration = false;
} else {
if(data[i].first != currentVertex.first) {
if(data[i].first.x() != currentVertex.first.x()) {
processVertex(output);
//std::cout << scanline.size() << " ";
countFromBelow.clear(); //should already be clear
writeGraph(currentVertex.first.x(), result, output, scanline);
currentVertex.second.clear();
mergeProperty(currentVertex.second, data[i].second);
currentVertex.first = data[i].first;
} else {
processVertex(output);
currentVertex.second.clear();
mergeProperty(currentVertex.second, data[i].second);
currentVertex.first = data[i].first;
}
} else {
mergeProperty(currentVertex.second, data[i].second);
}
}
}
processVertex(output);
writeGraph(currentVertex.first.x(), result, output, scanline);
//std::cout << scanline.size() << "\n";
}
template <typename T>
inline void insertEdges(T& graph, property_set& p1, property_set& p2) {
for(typename property_set::iterator itr = p1.begin(); itr != p1.end(); ++itr) {
for(typename property_set::iterator itr2 = p2.begin(); itr2 != p2.end(); ++itr2) {
if(*itr != *itr2) {
graph[*itr].insert(*itr2);
graph[*itr2].insert(*itr);
}
}
}
}
template <typename T>
inline void propertySetAbove(coordinate_type y, property_set& ps, T& scanline) {
ps.clear();
typename T::iterator itr = scanline.find(y);
if(itr != scanline.end())
setProperty(ps, (*itr).second);
}
template <typename T>
inline void propertySetBelow(coordinate_type y, property_set& ps, T& scanline) {
ps.clear();
typename T::iterator itr = scanline.find(y);
if(itr != scanline.begin()) {
--itr;
setProperty(ps, (*itr).second);
}
}
template <typename T, typename T2>
inline void writeGraph(coordinate_type x, T& graph, edge_property_vector& output, T2& scanline) {
if(output.empty()) return;
edge_property* previousEdgeP = &(output[0]);
bool firstIteration = true;
property_set ps;
for(std::size_t i = 0; i < output.size(); ++i) {
edge_property& previousEdge = *previousEdgeP;
edge_property& edge = output[i];
if(previousEdge.first.high() == edge.first.low()) {
//horizontal edge
insertEdges(graph, edge.second.first, previousEdge.second.first);
//corner 1
insertEdges(graph, edge.second.first, previousEdge.second.second);
//other horizontal edge
insertEdges(graph, edge.second.second, previousEdge.second.second);
//corner 2
insertEdges(graph, edge.second.second, previousEdge.second.first);
} else {
if(!firstIteration){
//look up regions above previous edge
propertySetAbove(previousEdge.first.high(), ps, scanline);
insertEdges(graph, ps, previousEdge.second.first);
insertEdges(graph, ps, previousEdge.second.second);
}
//look up regions below current edge in the scanline
propertySetBelow(edge.first.high(), ps, scanline);
insertEdges(graph, ps, edge.second.first);
insertEdges(graph, ps, edge.second.second);
}
firstIteration = false;
//vertical edge
insertEdges(graph, edge.second.second, edge.second.first);
//shared region to left
insertEdges(graph, edge.second.second, edge.second.second);
//shared region to right
insertEdges(graph, edge.second.first, edge.second.first);
previousEdgeP = &(output[i]);
}
edge_property& previousEdge = *previousEdgeP;
propertySetAbove(previousEdge.first.high(), ps, scanline);
insertEdges(graph, ps, previousEdge.second.first);
insertEdges(graph, ps, previousEdge.second.second);
output.clear();
}
template <typename Result>
inline void writeOutput(coordinate_type x, Result& result, edge_property_vector& output) {
for(std::size_t i = 0; i < output.size(); ++i) {
edge_property& edge = output[i];
//edge.second.first is the property set on the left of the edge
if(!edge.second.first.empty()) {
typename Result::iterator itr = result.find(edge.second.first);
if(itr == result.end()) {
std::pair<property_set, polygon_set_type> element(edge.second.first, polygon_set_type(VERTICAL));
itr = result.insert(result.end(), element);
}
std::pair<interval_data<coordinate_type>, int> element2(interval_data<coordinate_type>(edge.first.low(), edge.first.high()), -1); //right edge of figure
(*itr).second.insert(x, element2);
}
if(!edge.second.second.empty()) {
//edge.second.second is the property set on the right of the edge
typename Result::iterator itr = result.find(edge.second.second);
if(itr == result.end()) {
std::pair<property_set, polygon_set_type> element(edge.second.second, polygon_set_type(VERTICAL));
itr = result.insert(result.end(), element);
}
std::pair<interval_data<coordinate_type>, int> element3(interval_data<coordinate_type>(edge.first.low(), edge.first.high()), 1); //left edge of figure
(*itr).second.insert(x, element3);
}
}
output.clear();
}
};
}
}
#endif

View file

@ -0,0 +1,160 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_PROPERTY_MERGE_45_HPP
#define BOOST_POLYGON_PROPERTY_MERGE_45_HPP
namespace boost { namespace polygon{
template <typename Unit, typename property_type>
struct polygon_45_property_merge {
typedef point_data<Unit> Point;
typedef typename coordinate_traits<Unit>::manhattan_area_type LongUnit;
template <typename property_map>
static inline void merge_property_maps(property_map& mp, const property_map& mp2, bool subtract = false) {
polygon_45_touch<Unit>::merge_property_maps(mp, mp2, subtract);
}
class CountMerge {
public:
inline CountMerge() : counts() {}
//inline CountMerge(int count) { counts[0] = counts[1] = count; }
//inline CountMerge(int count1, int count2) { counts[0] = count1; counts[1] = count2; }
inline CountMerge(const CountMerge& count) : counts(count.counts) {}
inline bool operator==(const CountMerge& count) const { return counts == count.counts; }
inline bool operator!=(const CountMerge& count) const { return !((*this) == count); }
//inline CountMerge& operator=(int count) { counts[0] = counts[1] = count; return *this; }
inline CountMerge& operator=(const CountMerge& count) { counts = count.counts; return *this; }
inline int& operator[](property_type index) {
std::vector<std::pair<int, int> >::iterator itr = lower_bound(counts.begin(), counts.end(), std::make_pair(index, int(0)));
if(itr != counts.end() && itr->first == index) {
return itr->second;
}
itr = counts.insert(itr, std::make_pair(index, int(0)));
return itr->second;
}
// inline int operator[](int index) const {
// std::vector<std::pair<int, int> >::const_iterator itr = counts.begin();
// for( ; itr != counts.end() && itr->first <= index; ++itr) {
// if(itr->first == index) {
// return itr->second;
// }
// }
// return 0;
// }
inline CountMerge& operator+=(const CountMerge& count){
merge_property_maps(counts, count.counts, false);
return *this;
}
inline CountMerge& operator-=(const CountMerge& count){
merge_property_maps(counts, count.counts, true);
return *this;
}
inline CountMerge operator+(const CountMerge& count) const {
return CountMerge(*this)+=count;
}
inline CountMerge operator-(const CountMerge& count) const {
return CountMerge(*this)-=count;
}
inline CountMerge invert() const {
CountMerge retval;
retval -= *this;
return retval;
}
std::vector<std::pair<property_type, int> > counts;
};
//output is a std::map<std::set<property_type>, polygon_45_set_data<Unit> >
struct merge_45_output_functor {
template <typename cT>
void operator()(cT& output, const CountMerge& count1, const CountMerge& count2,
const Point& pt, int rise, direction_1d end) {
typedef typename cT::key_type keytype;
keytype left;
keytype right;
int edgeType = end == LOW ? -1 : 1;
for(typename std::vector<std::pair<property_type, int> >::const_iterator itr = count1.counts.begin();
itr != count1.counts.end(); ++itr) {
left.insert(left.end(), (*itr).first);
}
for(typename std::vector<std::pair<property_type, int> >::const_iterator itr = count2.counts.begin();
itr != count2.counts.end(); ++itr) {
right.insert(right.end(), (*itr).first);
}
if(left == right) return;
if(!left.empty()) {
//std::cout << pt.x() << " " << pt.y() << " " << rise << " " << edgeType << std::endl;
output[left].insert_clean(typename boolean_op_45<Unit>::Vertex45(pt, rise, -edgeType));
}
if(!right.empty()) {
//std::cout << pt.x() << " " << pt.y() << " " << rise << " " << -edgeType << std::endl;
output[right].insert_clean(typename boolean_op_45<Unit>::Vertex45(pt, rise, edgeType));
}
}
};
typedef typename std::pair<Point,
typename boolean_op_45<Unit>::template Scan45CountT<CountMerge> > Vertex45Compact;
typedef std::vector<Vertex45Compact> MergeSetData;
struct lessVertex45Compact {
bool operator()(const Vertex45Compact& l, const Vertex45Compact& r) {
return l.first < r.first;
}
};
template <typename output_type>
static void performMerge(output_type& result, MergeSetData& tsd) {
polygon_sort(tsd.begin(), tsd.end(), lessVertex45Compact());
typedef std::vector<std::pair<Point, typename boolean_op_45<Unit>::template Scan45CountT<CountMerge> > > TSD;
TSD tsd_;
tsd_.reserve(tsd.size());
for(typename MergeSetData::iterator itr = tsd.begin(); itr != tsd.end(); ) {
typename MergeSetData::iterator itr2 = itr;
++itr2;
for(; itr2 != tsd.end() && itr2->first == itr->first; ++itr2) {
(itr->second) += (itr2->second); //accumulate
}
tsd_.push_back(std::make_pair(itr->first, itr->second));
itr = itr2;
}
typename boolean_op_45<Unit>::template Scan45<CountMerge, merge_45_output_functor> scanline;
for(typename TSD::iterator itr = tsd_.begin(); itr != tsd_.end(); ) {
typename TSD::iterator itr2 = itr;
++itr2;
while(itr2 != tsd_.end() && itr2->first.x() == itr->first.x()) {
++itr2;
}
scanline.scan(result, itr, itr2);
itr = itr2;
}
}
template <typename iT>
static void populateMergeSetData(MergeSetData& tsd, iT begin, iT end, property_type property) {
for( ; begin != end; ++begin) {
Vertex45Compact vertex;
vertex.first = typename Vertex45Compact::first_type(begin->pt.x() * 2, begin->pt.y() * 2);
tsd.push_back(vertex);
for(unsigned int i = 0; i < 4; ++i) {
if(begin->count[i]) {
tsd.back().second[i][property] += begin->count[i];
}
}
}
}
};
}
}
#endif

View file

@ -0,0 +1,266 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_RECTANGLE_FORMATION_HPP
#define BOOST_POLYGON_RECTANGLE_FORMATION_HPP
namespace boost { namespace polygon{
namespace rectangle_formation {
template <class T>
class ScanLineToRects {
public:
typedef T rectangle_type;
typedef typename rectangle_traits<T>::coordinate_type coordinate_type;
typedef rectangle_data<coordinate_type> scan_rect_type;
private:
typedef std::set<scan_rect_type, less_rectangle_concept<scan_rect_type, scan_rect_type> > ScanData;
ScanData scanData_;
bool haveCurrentRect_;
scan_rect_type currentRect_;
orientation_2d orient_;
typename rectangle_traits<T>::coordinate_type currentCoordinate_;
public:
inline ScanLineToRects() : scanData_(), haveCurrentRect_(), currentRect_(), orient_(), currentCoordinate_() {}
inline ScanLineToRects(orientation_2d orient, rectangle_type model) :
scanData_(orientation_2d(orient.to_int() ? VERTICAL : HORIZONTAL)),
haveCurrentRect_(false), currentRect_(), orient_(orient), currentCoordinate_() {
assign(currentRect_, model);
currentCoordinate_ = (std::numeric_limits<coordinate_type>::max)();
}
template <typename CT>
inline ScanLineToRects& processEdge(CT& rectangles, const interval_data<coordinate_type>& edge);
inline ScanLineToRects& nextMajorCoordinate(coordinate_type currentCoordinate) {
if(haveCurrentRect_) {
scanData_.insert(scanData_.end(), currentRect_);
haveCurrentRect_ = false;
}
currentCoordinate_ = currentCoordinate;
return *this;
}
};
template <class CT, class ST, class rectangle_type, typename interval_type, typename coordinate_type> inline CT&
processEdge_(CT& rectangles, ST& scanData, const interval_type& edge,
bool& haveCurrentRect, rectangle_type& currentRect, coordinate_type currentCoordinate, orientation_2d orient)
{
typedef typename CT::value_type result_type;
bool edgeProcessed = false;
if(!scanData.empty()) {
//process all rectangles in the scanData that touch the edge
typename ST::iterator dataIter = scanData.lower_bound(rectangle_type(edge, edge));
//decrement beginIter until its low is less than edge's low
while((dataIter == scanData.end() || (*dataIter).get(orient).get(LOW) > edge.get(LOW)) &&
dataIter != scanData.begin())
{
--dataIter;
}
//process each rectangle until the low end of the rectangle
//is greater than the high end of the edge
while(dataIter != scanData.end() &&
(*dataIter).get(orient).get(LOW) <= edge.get(HIGH))
{
const rectangle_type& rect = *dataIter;
//if the rectangle data intersects the edge at all
if(rect.get(orient).get(HIGH) >= edge.get(LOW)) {
if(contains(rect.get(orient), edge, true)) {
//this is a closing edge
//we need to write out the intersecting rectangle and
//insert between 0 and 2 rectangles into the scanData
//write out rectangle
rectangle_type tmpRect = rect;
if(rect.get(orient.get_perpendicular()).get(LOW) < currentCoordinate) {
//set the high coordinate perpedicular to slicing orientation
//to the current coordinate of the scan event
tmpRect.set(orient.get_perpendicular().get_direction(HIGH),
currentCoordinate);
result_type result;
assign(result, tmpRect);
rectangles.insert(rectangles.end(), result);
}
//erase the rectangle from the scan data
typename ST::iterator nextIter = dataIter;
++nextIter;
scanData.erase(dataIter);
if(tmpRect.get(orient).get(LOW) < edge.get(LOW)) {
//insert a rectangle for the overhang of the bottom
//of the rectangle back into scan data
rectangle_type lowRect(tmpRect);
lowRect.set(orient.get_perpendicular(), interval_data<coordinate_type>(currentCoordinate,
currentCoordinate));
lowRect.set(orient.get_direction(HIGH), edge.get(LOW));
scanData.insert(nextIter, lowRect);
}
if(tmpRect.get(orient).get(HIGH) > edge.get(HIGH)) {
//insert a rectangle for the overhang of the top
//of the rectangle back into scan data
rectangle_type highRect(tmpRect);
highRect.set(orient.get_perpendicular(), interval_data<coordinate_type>(currentCoordinate,
currentCoordinate));
highRect.set(orient.get_direction(LOW), edge.get(HIGH));
scanData.insert(nextIter, highRect);
}
//we are done with this edge
edgeProcessed = true;
break;
} else {
//it must be an opening edge
//assert that rect does not overlap the edge but only touches
//write out rectangle
rectangle_type tmpRect = rect;
//set the high coordinate perpedicular to slicing orientation
//to the current coordinate of the scan event
if(tmpRect.get(orient.get_perpendicular().get_direction(LOW)) < currentCoordinate) {
tmpRect.set(orient.get_perpendicular().get_direction(HIGH),
currentCoordinate);
result_type result;
assign(result, tmpRect);
rectangles.insert(rectangles.end(), result);
}
//erase the rectangle from the scan data
typename ST::iterator nextIter = dataIter;
++nextIter;
scanData.erase(dataIter);
dataIter = nextIter;
if(haveCurrentRect) {
if(currentRect.get(orient).get(HIGH) >= edge.get(LOW)){
if(!edgeProcessed && currentRect.get(orient.get_direction(HIGH)) > edge.get(LOW)){
rectangle_type tmpRect2(currentRect);
tmpRect2.set(orient.get_direction(HIGH), edge.get(LOW));
scanData.insert(nextIter, tmpRect2);
if(currentRect.get(orient.get_direction(HIGH)) > edge.get(HIGH)) {
currentRect.set(orient, interval_data<coordinate_type>(edge.get(HIGH), currentRect.get(orient.get_direction(HIGH))));
} else {
haveCurrentRect = false;
}
} else {
//extend the top of current rect
currentRect.set(orient.get_direction(HIGH),
(std::max)(edge.get(HIGH),
tmpRect.get(orient.get_direction(HIGH))));
}
} else {
//insert current rect into the scanData
scanData.insert(nextIter, currentRect);
//create a new current rect
currentRect.set(orient.get_perpendicular(), interval_data<coordinate_type>(currentCoordinate,
currentCoordinate));
currentRect.set(orient, interval_data<coordinate_type>((std::min)(tmpRect.get(orient).get(LOW),
edge.get(LOW)),
(std::max)(tmpRect.get(orient).get(HIGH),
edge.get(HIGH))));
}
} else {
haveCurrentRect = true;
currentRect.set(orient.get_perpendicular(), interval_data<coordinate_type>(currentCoordinate,
currentCoordinate));
currentRect.set(orient, interval_data<coordinate_type>((std::min)(tmpRect.get(orient).get(LOW),
edge.get(LOW)),
(std::max)(tmpRect.get(orient).get(HIGH),
edge.get(HIGH))));
}
//skip to nextIter position
edgeProcessed = true;
continue;
}
//edgeProcessed = true;
}
++dataIter;
} //end while edge intersects rectangle data
}
if(!edgeProcessed) {
if(haveCurrentRect) {
if(currentRect.get(orient.get_perpendicular().get_direction(HIGH))
== currentCoordinate &&
currentRect.get(orient.get_direction(HIGH)) >= edge.get(LOW))
{
if(currentRect.get(orient.get_direction(HIGH)) > edge.get(LOW)){
rectangle_type tmpRect(currentRect);
tmpRect.set(orient.get_direction(HIGH), edge.get(LOW));
scanData.insert(scanData.end(), tmpRect);
if(currentRect.get(orient.get_direction(HIGH)) > edge.get(HIGH)) {
currentRect.set(orient,
interval_data<coordinate_type>(edge.get(HIGH),
currentRect.get(orient.get_direction(HIGH))));
return rectangles;
} else {
haveCurrentRect = false;
return rectangles;
}
}
//extend current rect
currentRect.set(orient.get_direction(HIGH), edge.get(HIGH));
return rectangles;
}
scanData.insert(scanData.end(), currentRect);
haveCurrentRect = false;
}
rectangle_type tmpRect(currentRect);
tmpRect.set(orient.get_perpendicular(), interval_data<coordinate_type>(currentCoordinate,
currentCoordinate));
tmpRect.set(orient, edge);
scanData.insert(tmpRect);
return rectangles;
}
return rectangles;
}
template <class T>
template <class CT>
inline
ScanLineToRects<T>& ScanLineToRects<T>::processEdge(CT& rectangles, const interval_data<coordinate_type>& edge)
{
processEdge_(rectangles, scanData_, edge, haveCurrentRect_, currentRect_, currentCoordinate_, orient_);
return *this;
}
} //namespace rectangle_formation
template <typename T, typename T2>
struct get_coordinate_type_for_rectangles {
typedef typename polygon_traits<T>::coordinate_type type;
};
template <typename T>
struct get_coordinate_type_for_rectangles<T, rectangle_concept> {
typedef typename rectangle_traits<T>::coordinate_type type;
};
template <typename output_container, typename iterator_type, typename rectangle_concept>
void form_rectangles(output_container& output, iterator_type begin, iterator_type end,
orientation_2d orient, rectangle_concept ) {
typedef typename output_container::value_type rectangle_type;
typedef typename get_coordinate_type_for_rectangles<rectangle_type, typename geometry_concept<rectangle_type>::type>::type Unit;
rectangle_data<Unit> model;
Unit prevPos = (std::numeric_limits<Unit>::max)();
rectangle_formation::ScanLineToRects<rectangle_data<Unit> > scanlineToRects(orient, model);
for(iterator_type itr = begin;
itr != end; ++ itr) {
Unit pos = (*itr).first;
if(pos != prevPos) {
scanlineToRects.nextMajorCoordinate(pos);
prevPos = pos;
}
Unit lowy = (*itr).second.first;
iterator_type tmp_itr = itr;
++itr;
Unit highy = (*itr).second.first;
scanlineToRects.processEdge(output, interval_data<Unit>(lowy, highy));
if(abs((*itr).second.second) > 1) itr = tmp_itr; //next edge begins from this vertex
}
}
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,642 @@
// Boost.Polygon library detail/voronoi_ctypes.hpp header file
// Copyright Andrii Sydorchuk 2010-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POLYGON_DETAIL_VORONOI_CTYPES
#define BOOST_POLYGON_DETAIL_VORONOI_CTYPES
#include <boost/cstdint.hpp>
#include <cmath>
#include <cstring>
#include <utility>
#include <vector>
namespace boost {
namespace polygon {
namespace detail {
typedef boost::int32_t int32;
typedef boost::int64_t int64;
typedef boost::uint32_t uint32;
typedef boost::uint64_t uint64;
typedef double fpt64;
// If two floating-point numbers in the same format are ordered (x < y),
// then they are ordered the same way when their bits are reinterpreted as
// sign-magnitude integers. Values are considered to be almost equal if
// their integer bits reinterpretations differ in not more than maxUlps units.
template <typename _fpt>
struct ulp_comparison;
template <>
struct ulp_comparison<fpt64> {
enum Result {
LESS = -1,
EQUAL = 0,
MORE = 1
};
Result operator()(fpt64 a, fpt64 b, unsigned int maxUlps) const {
uint64 ll_a, ll_b;
// Reinterpret double bits as 64-bit signed integer.
std::memcpy(&ll_a, &a, sizeof(fpt64));
std::memcpy(&ll_b, &b, sizeof(fpt64));
// Positive 0.0 is integer zero. Negative 0.0 is 0x8000000000000000.
// Map negative zero to an integer zero representation - making it
// identical to positive zero - the smallest negative number is
// represented by negative one, and downwards from there.
if (ll_a < 0x8000000000000000ULL)
ll_a = 0x8000000000000000ULL - ll_a;
if (ll_b < 0x8000000000000000ULL)
ll_b = 0x8000000000000000ULL - ll_b;
// Compare 64-bit signed integer representations of input values.
// Difference in 1 Ulp is equivalent to a relative error of between
// 1/4,000,000,000,000,000 and 1/8,000,000,000,000,000.
if (ll_a > ll_b)
return (ll_a - ll_b <= maxUlps) ? EQUAL : LESS;
return (ll_b - ll_a <= maxUlps) ? EQUAL : MORE;
}
};
template <typename _fpt>
struct extened_exponent_fpt_traits;
template <>
class extened_exponent_fpt_traits<fpt64> {
public:
typedef int exp_type;
enum {
MAX_SIGNIFICANT_EXP_DIF = 54
};
};
// Floating point type wrapper. Allows to extend exponent boundaries to the
// integer type range. This class does not handle division by zero, subnormal
// numbers or NaNs.
template <typename _fpt, typename _traits = extened_exponent_fpt_traits<_fpt> >
class extended_exponent_fpt {
public:
typedef _fpt fpt_type;
typedef typename _traits::exp_type exp_type;
explicit extended_exponent_fpt(fpt_type val) {
val_ = std::frexp(val, &exp_);
}
extended_exponent_fpt(fpt_type val, exp_type exp) {
val_ = std::frexp(val, &exp_);
exp_ += exp;
}
bool is_pos() const {
return val_ > 0;
}
bool is_neg() const {
return val_ < 0;
}
bool is_zero() const {
return val_ == 0;
}
extended_exponent_fpt operator-() const {
return extended_exponent_fpt(-val_, exp_);
}
extended_exponent_fpt operator+(const extended_exponent_fpt& that) const {
if (this->val_ == 0.0 ||
that.exp_ > this->exp_ + _traits::MAX_SIGNIFICANT_EXP_DIF) {
return that;
}
if (that.val_ == 0.0 ||
this->exp_ > that.exp_ + _traits::MAX_SIGNIFICANT_EXP_DIF) {
return *this;
}
if (this->exp_ >= that.exp_) {
exp_type exp_dif = this->exp_ - that.exp_;
fpt_type val = std::ldexp(this->val_, exp_dif) + that.val_;
return extended_exponent_fpt(val, that.exp_);
} else {
exp_type exp_dif = that.exp_ - this->exp_;
fpt_type val = std::ldexp(that.val_, exp_dif) + this->val_;
return extended_exponent_fpt(val, this->exp_);
}
}
extended_exponent_fpt operator-(const extended_exponent_fpt& that) const {
if (this->val_ == 0.0 ||
that.exp_ > this->exp_ + _traits::MAX_SIGNIFICANT_EXP_DIF) {
return extended_exponent_fpt(-that.val_, that.exp_);
}
if (that.val_ == 0.0 ||
this->exp_ > that.exp_ + _traits::MAX_SIGNIFICANT_EXP_DIF) {
return *this;
}
if (this->exp_ >= that.exp_) {
exp_type exp_dif = this->exp_ - that.exp_;
fpt_type val = std::ldexp(this->val_, exp_dif) - that.val_;
return extended_exponent_fpt(val, that.exp_);
} else {
exp_type exp_dif = that.exp_ - this->exp_;
fpt_type val = std::ldexp(-that.val_, exp_dif) + this->val_;
return extended_exponent_fpt(val, this->exp_);
}
}
extended_exponent_fpt operator*(const extended_exponent_fpt& that) const {
fpt_type val = this->val_ * that.val_;
exp_type exp = this->exp_ + that.exp_;
return extended_exponent_fpt(val, exp);
}
extended_exponent_fpt operator/(const extended_exponent_fpt& that) const {
fpt_type val = this->val_ / that.val_;
exp_type exp = this->exp_ - that.exp_;
return extended_exponent_fpt(val, exp);
}
extended_exponent_fpt& operator+=(const extended_exponent_fpt& that) {
return *this = *this + that;
}
extended_exponent_fpt& operator-=(const extended_exponent_fpt& that) {
return *this = *this - that;
}
extended_exponent_fpt& operator*=(const extended_exponent_fpt& that) {
return *this = *this * that;
}
extended_exponent_fpt& operator/=(const extended_exponent_fpt& that) {
return *this = *this / that;
}
extended_exponent_fpt sqrt() const {
fpt_type val = val_;
exp_type exp = exp_;
if (exp & 1) {
val *= 2.0;
--exp;
}
return extended_exponent_fpt(std::sqrt(val), exp >> 1);
}
fpt_type d() const {
return std::ldexp(val_, exp_);
}
private:
fpt_type val_;
exp_type exp_;
};
typedef extended_exponent_fpt<double> efpt64;
template <typename _fpt>
extended_exponent_fpt<_fpt> get_sqrt(const extended_exponent_fpt<_fpt>& that) {
return that.sqrt();
}
template <typename _fpt>
bool is_pos(const extended_exponent_fpt<_fpt>& that) {
return that.is_pos();
}
template <typename _fpt>
bool is_neg(const extended_exponent_fpt<_fpt>& that) {
return that.is_neg();
}
template <typename _fpt>
bool is_zero(const extended_exponent_fpt<_fpt>& that) {
return that.is_zero();
}
// Very efficient stack allocated big integer class.
// Supports next set of arithmetic operations: +, -, *.
template<std::size_t N>
class extended_int {
public:
extended_int() {}
extended_int(int32 that) {
if (that > 0) {
this->chunks_[0] = that;
this->count_ = 1;
} else if (that < 0) {
this->chunks_[0] = -that;
this->count_ = -1;
} else {
this->count_ = 0;
}
}
extended_int(int64 that) {
if (that > 0) {
this->chunks_[0] = static_cast<uint32>(that);
this->chunks_[1] = that >> 32;
this->count_ = this->chunks_[1] ? 2 : 1;
} else if (that < 0) {
that = -that;
this->chunks_[0] = static_cast<uint32>(that);
this->chunks_[1] = that >> 32;
this->count_ = this->chunks_[1] ? -2 : -1;
} else {
this->count_ = 0;
}
}
extended_int(const std::vector<uint32>& chunks, bool plus = true) {
this->count_ = static_cast<int32>((std::min)(N, chunks.size()));
for (int i = 0; i < this->count_; ++i)
this->chunks_[i] = chunks[chunks.size() - i - 1];
if (!plus)
this->count_ = -this->count_;
}
template<std::size_t M>
extended_int(const extended_int<M>& that) {
this->count_ = that.count();
std::memcpy(this->chunks_, that.chunks(), that.size() * sizeof(uint32));
}
extended_int& operator=(int32 that) {
if (that > 0) {
this->chunks_[0] = that;
this->count_ = 1;
} else if (that < 0) {
this->chunks_[0] = -that;
this->count_ = -1;
} else {
this->count_ = 0;
}
return *this;
}
extended_int& operator=(int64 that) {
if (that > 0) {
this->chunks_[0] = static_cast<uint32>(that);
this->chunks_[1] = that >> 32;
this->count_ = this->chunks_[1] ? 2 : 1;
} else if (that < 0) {
that = -that;
this->chunks_[0] = static_cast<uint32>(that);
this->chunks_[1] = that >> 32;
this->count_ = this->chunks_[1] ? -2 : -1;
} else {
this->count_ = 0;
}
return *this;
}
template<std::size_t M>
extended_int& operator=(const extended_int<M>& that) {
this->count_ = that.count();
std::memcpy(this->chunks_, that.chunks(), that.size() * sizeof(uint32));
return *this;
}
bool is_pos() const {
return this->count_ > 0;
}
bool is_neg() const {
return this->count_ < 0;
}
bool is_zero() const {
return this->count_ == 0;
}
bool operator==(const extended_int& that) const {
if (this->count_ != that.count())
return false;
for (std::size_t i = 0; i < this->size(); ++i)
if (this->chunks_[i] != that.chunks()[i])
return false;
return true;
}
bool operator!=(const extended_int& that) const {
return !(*this == that);
}
bool operator<(const extended_int& that) const {
if (this->count_ != that.count())
return this->count_ < that.count();
std::size_t i = this->size();
if (!i)
return false;
do {
--i;
if (this->chunks_[i] != that.chunks()[i])
return (this->chunks_[i] < that.chunks()[i]) ^ (this->count_ < 0);
} while (i);
return false;
}
bool operator>(const extended_int& that) const {
return that < *this;
}
bool operator<=(const extended_int& that) const {
return !(that < *this);
}
bool operator>=(const extended_int& that) const {
return !(*this < that);
}
extended_int operator-() const {
extended_int ret_val = *this;
ret_val.neg();
return ret_val;
}
void neg() {
this->count_ = -this->count_;
}
extended_int operator+(const extended_int& that) const {
extended_int ret_val;
ret_val.add(*this, that);
return ret_val;
}
void add(const extended_int& e1, const extended_int& e2) {
if (!e1.count()) {
*this = e2;
return;
}
if (!e2.count()) {
*this = e1;
return;
}
if ((e1.count() > 0) ^ (e2.count() > 0)) {
dif(e1.chunks(), e1.size(), e2.chunks(), e2.size());
} else {
add(e1.chunks(), e1.size(), e2.chunks(), e2.size());
}
if (e1.count() < 0)
this->count_ = -this->count_;
}
extended_int operator-(const extended_int& that) const {
extended_int ret_val;
ret_val.dif(*this, that);
return ret_val;
}
void dif(const extended_int& e1, const extended_int& e2) {
if (!e1.count()) {
*this = e2;
this->count_ = -this->count_;
return;
}
if (!e2.count()) {
*this = e1;
return;
}
if ((e1.count() > 0) ^ (e2.count() > 0)) {
add(e1.chunks(), e1.size(), e2.chunks(), e2.size());
} else {
dif(e1.chunks(), e1.size(), e2.chunks(), e2.size());
}
if (e1.count() < 0)
this->count_ = -this->count_;
}
extended_int operator*(int32 that) const {
extended_int temp(that);
return (*this) * temp;
}
extended_int operator*(int64 that) const {
extended_int temp(that);
return (*this) * temp;
}
extended_int operator*(const extended_int& that) const {
extended_int ret_val;
ret_val.mul(*this, that);
return ret_val;
}
void mul(const extended_int& e1, const extended_int& e2) {
if (!e1.count() || !e2.count()) {
this->count_ = 0;
return;
}
mul(e1.chunks(), e1.size(), e2.chunks(), e2.size());
if ((e1.count() > 0) ^ (e2.count() > 0))
this->count_ = -this->count_;
}
const uint32* chunks() const {
return chunks_;
}
int32 count() const {
return count_;
}
std::size_t size() const {
return (std::abs)(count_);
}
std::pair<fpt64, int> p() const {
std::pair<fpt64, int> ret_val(0, 0);
std::size_t sz = this->size();
if (!sz) {
return ret_val;
} else {
if (sz == 1) {
ret_val.first = static_cast<fpt64>(this->chunks_[0]);
} else if (sz == 2) {
ret_val.first = static_cast<fpt64>(this->chunks_[1]) *
static_cast<fpt64>(0x100000000LL) +
static_cast<fpt64>(this->chunks_[0]);
} else {
for (std::size_t i = 1; i <= 3; ++i) {
ret_val.first *= static_cast<fpt64>(0x100000000LL);
ret_val.first += static_cast<fpt64>(this->chunks_[sz - i]);
}
ret_val.second = (sz - 3) << 5;
}
}
if (this->count_ < 0)
ret_val.first = -ret_val.first;
return ret_val;
}
fpt64 d() const {
std::pair<fpt64, int> p = this->p();
return std::ldexp(p.first, p.second);
}
private:
void add(const uint32* c1, std::size_t sz1,
const uint32* c2, std::size_t sz2) {
if (sz1 < sz2) {
add(c2, sz2, c1, sz1);
return;
}
this->count_ = sz1;
uint64 temp = 0;
for (std::size_t i = 0; i < sz2; ++i) {
temp += static_cast<uint64>(c1[i]) + static_cast<uint64>(c2[i]);
this->chunks_[i] = static_cast<uint32>(temp);
temp >>= 32;
}
for (std::size_t i = sz2; i < sz1; ++i) {
temp += static_cast<uint64>(c1[i]);
this->chunks_[i] = static_cast<uint32>(temp);
temp >>= 32;
}
if (temp && (this->count_ != N)) {
this->chunks_[this->count_] = static_cast<uint32>(temp);
++this->count_;
}
}
void dif(const uint32* c1, std::size_t sz1,
const uint32* c2, std::size_t sz2,
bool rec = false) {
if (sz1 < sz2) {
dif(c2, sz2, c1, sz1, true);
this->count_ = -this->count_;
return;
} else if ((sz1 == sz2) && !rec) {
do {
--sz1;
if (c1[sz1] < c2[sz1]) {
++sz1;
dif(c2, sz1, c1, sz1, true);
this->count_ = -this->count_;
return;
} else if (c1[sz1] > c2[sz1]) {
++sz1;
break;
}
} while (sz1);
if (!sz1) {
this->count_ = 0;
return;
}
sz2 = sz1;
}
this->count_ = sz1-1;
bool flag = false;
for (std::size_t i = 0; i < sz2; ++i) {
this->chunks_[i] = c1[i] - c2[i] - (flag?1:0);
flag = (c1[i] < c2[i]) || ((c1[i] == c2[i]) && flag);
}
for (std::size_t i = sz2; i < sz1; ++i) {
this->chunks_[i] = c1[i] - (flag?1:0);
flag = !c1[i] && flag;
}
if (this->chunks_[this->count_])
++this->count_;
}
void mul(const uint32* c1, std::size_t sz1,
const uint32* c2, std::size_t sz2) {
uint64 cur = 0, nxt, tmp;
this->count_ = static_cast<int32>((std::min)(N, sz1 + sz2 - 1));
for (std::size_t shift = 0; shift < static_cast<std::size_t>(this->count_);
++shift) {
nxt = 0;
for (std::size_t first = 0; first <= shift; ++first) {
if (first >= sz1)
break;
std::size_t second = shift - first;
if (second >= sz2)
continue;
tmp = static_cast<uint64>(c1[first]) * static_cast<uint64>(c2[second]);
cur += static_cast<uint32>(tmp);
nxt += tmp >> 32;
}
this->chunks_[shift] = static_cast<uint32>(cur);
cur = nxt + (cur >> 32);
}
if (cur && (this->count_ != N)) {
this->chunks_[this->count_] = static_cast<uint32>(cur);
++this->count_;
}
}
uint32 chunks_[N];
int32 count_;
};
template <std::size_t N>
bool is_pos(const extended_int<N>& that) {
return that.count() > 0;
}
template <std::size_t N>
bool is_neg(const extended_int<N>& that) {
return that.count() < 0;
}
template <std::size_t N>
bool is_zero(const extended_int<N>& that) {
return !that.count();
}
struct type_converter_fpt {
template <typename T>
fpt64 operator()(const T& that) const {
return static_cast<fpt64>(that);
}
template <std::size_t N>
fpt64 operator()(const extended_int<N>& that) const {
return that.d();
}
fpt64 operator()(const extended_exponent_fpt<fpt64>& that) const {
return that.d();
}
};
struct type_converter_efpt {
template <std::size_t N>
extended_exponent_fpt<fpt64> operator()(const extended_int<N>& that) const {
std::pair<fpt64, int> p = that.p();
return extended_exponent_fpt<fpt64>(p.first, p.second);
}
};
// Voronoi coordinate type traits make it possible to extend algorithm
// input coordinate range to any user provided integer type and algorithm
// output coordinate range to any ieee-754 like floating point type.
template <typename T>
struct voronoi_ctype_traits;
template <>
struct voronoi_ctype_traits<int32> {
typedef int32 int_type;
typedef int64 int_x2_type;
typedef uint64 uint_x2_type;
typedef extended_int<64> big_int_type;
typedef fpt64 fpt_type;
typedef extended_exponent_fpt<fpt_type> efpt_type;
typedef ulp_comparison<fpt_type> ulp_cmp_type;
typedef type_converter_fpt to_fpt_converter_type;
typedef type_converter_efpt to_efpt_converter_type;
};
} // detail
} // polygon
} // boost
#endif // BOOST_POLYGON_DETAIL_VORONOI_CTYPES

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,506 @@
// Boost.Polygon library detail/voronoi_robust_fpt.hpp header file
// Copyright Andrii Sydorchuk 2010-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT
#define BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT
#include <cmath>
// Geometry predicates with floating-point variables usually require
// high-precision predicates to retrieve the correct result.
// Epsilon robust predicates give the result within some epsilon relative
// error, but are a lot faster than high-precision predicates.
// To make algorithm robust and efficient epsilon robust predicates are
// used at the first step. In case of the undefined result high-precision
// arithmetic is used to produce required robustness. This approach
// requires exact computation of epsilon intervals within which epsilon
// robust predicates have undefined value.
// There are two ways to measure an error of floating-point calculations:
// relative error and ULPs (units in the last place).
// Let EPS be machine epsilon, then next inequalities have place:
// 1 EPS <= 1 ULP <= 2 EPS (1), 0.5 ULP <= 1 EPS <= 1 ULP (2).
// ULPs are good for measuring rounding errors and comparing values.
// Relative errors are good for computation of general relative
// error of formulas or expressions. So to calculate epsilon
// interval within which epsilon robust predicates have undefined result
// next schema is used:
// 1) Compute rounding errors of initial variables using ULPs;
// 2) Transform ULPs to epsilons using upper bound of the (1);
// 3) Compute relative error of the formula using epsilon arithmetic;
// 4) Transform epsilon to ULPs using upper bound of the (2);
// In case two values are inside undefined ULP range use high-precision
// arithmetic to produce the correct result, else output the result.
// Look at almost_equal function to see how two floating-point variables
// are checked to fit in the ULP range.
// If A has relative error of r(A) and B has relative error of r(B) then:
// 1) r(A + B) <= max(r(A), r(B)), for A * B >= 0;
// 2) r(A - B) <= B*r(A)+A*r(B)/(A-B), for A * B >= 0;
// 2) r(A * B) <= r(A) + r(B);
// 3) r(A / B) <= r(A) + r(B);
// In addition rounding error should be added, that is always equal to
// 0.5 ULP or at most 1 epsilon. As you might see from the above formulas
// subtraction relative error may be extremely large, that's why
// epsilon robust comparator class is used to store floating point values
// and compute subtraction as the final step of the evaluation.
// For further information about relative errors and ULPs try this link:
// http://docs.sun.com/source/806-3568/ncg_goldberg.html
namespace boost {
namespace polygon {
namespace detail {
template <typename T>
T get_sqrt(const T& that) {
return (std::sqrt)(that);
}
template <typename T>
bool is_pos(const T& that) {
return that > 0;
}
template <typename T>
bool is_neg(const T& that) {
return that < 0;
}
template <typename T>
bool is_zero(const T& that) {
return that == 0;
}
template <typename _fpt>
class robust_fpt {
public:
typedef _fpt floating_point_type;
typedef _fpt relative_error_type;
// Rounding error is at most 1 EPS.
enum {
ROUNDING_ERROR = 1
};
robust_fpt() : fpv_(0.0), re_(0.0) {}
explicit robust_fpt(floating_point_type fpv) :
fpv_(fpv), re_(0.0) {}
robust_fpt(floating_point_type fpv, relative_error_type error) :
fpv_(fpv), re_(error) {}
floating_point_type fpv() const { return fpv_; }
relative_error_type re() const { return re_; }
relative_error_type ulp() const { return re_; }
robust_fpt& operator=(const robust_fpt& that) {
this->fpv_ = that.fpv_;
this->re_ = that.re_;
return *this;
}
bool has_pos_value() const {
return is_pos(fpv_);
}
bool has_neg_value() const {
return is_neg(fpv_);
}
bool has_zero_value() const {
return is_zero(fpv_);
}
robust_fpt operator-() const {
return robust_fpt(-fpv_, re_);
}
robust_fpt& operator+=(const robust_fpt& that) {
floating_point_type fpv = this->fpv_ + that.fpv_;
if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) ||
(!is_pos(this->fpv_) && !is_pos(that.fpv_))) {
this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
} else {
floating_point_type temp =
(this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv;
if (is_neg(temp))
temp = -temp;
this->re_ = temp + ROUNDING_ERROR;
}
this->fpv_ = fpv;
return *this;
}
robust_fpt& operator-=(const robust_fpt& that) {
floating_point_type fpv = this->fpv_ - that.fpv_;
if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) ||
(!is_pos(this->fpv_) && !is_neg(that.fpv_))) {
this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
} else {
floating_point_type temp =
(this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv;
if (is_neg(temp))
temp = -temp;
this->re_ = temp + ROUNDING_ERROR;
}
this->fpv_ = fpv;
return *this;
}
robust_fpt& operator*=(const robust_fpt& that) {
this->re_ += that.re_ + ROUNDING_ERROR;
this->fpv_ *= that.fpv_;
return *this;
}
robust_fpt& operator/=(const robust_fpt& that) {
this->re_ += that.re_ + ROUNDING_ERROR;
this->fpv_ /= that.fpv_;
return *this;
}
robust_fpt operator+(const robust_fpt& that) const {
floating_point_type fpv = this->fpv_ + that.fpv_;
relative_error_type re;
if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) ||
(!is_pos(this->fpv_) && !is_pos(that.fpv_))) {
re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
} else {
floating_point_type temp =
(this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv;
if (is_neg(temp))
temp = -temp;
re = temp + ROUNDING_ERROR;
}
return robust_fpt(fpv, re);
}
robust_fpt operator-(const robust_fpt& that) const {
floating_point_type fpv = this->fpv_ - that.fpv_;
relative_error_type re;
if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) ||
(!is_pos(this->fpv_) && !is_neg(that.fpv_))) {
re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
} else {
floating_point_type temp =
(this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv;
if (is_neg(temp))
temp = -temp;
re = temp + ROUNDING_ERROR;
}
return robust_fpt(fpv, re);
}
robust_fpt operator*(const robust_fpt& that) const {
floating_point_type fpv = this->fpv_ * that.fpv_;
relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR;
return robust_fpt(fpv, re);
}
robust_fpt operator/(const robust_fpt& that) const {
floating_point_type fpv = this->fpv_ / that.fpv_;
relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR;
return robust_fpt(fpv, re);
}
robust_fpt sqrt() const {
return robust_fpt(get_sqrt(fpv_),
re_ * static_cast<relative_error_type>(0.5) +
ROUNDING_ERROR);
}
private:
floating_point_type fpv_;
relative_error_type re_;
};
template <typename T>
robust_fpt<T> get_sqrt(const robust_fpt<T>& that) {
return that.sqrt();
}
template <typename T>
bool is_pos(const robust_fpt<T>& that) {
return that.has_pos_value();
}
template <typename T>
bool is_neg(const robust_fpt<T>& that) {
return that.has_neg_value();
}
template <typename T>
bool is_zero(const robust_fpt<T>& that) {
return that.has_zero_value();
}
// robust_dif consists of two not negative values: value1 and value2.
// The resulting expression is equal to the value1 - value2.
// Subtraction of a positive value is equivalent to the addition to value2
// and subtraction of a negative value is equivalent to the addition to
// value1. The structure implicitly avoids difference computation.
template <typename T>
class robust_dif {
public:
robust_dif() :
positive_sum_(0),
negative_sum_(0) {}
explicit robust_dif(const T& value) :
positive_sum_((value > 0)?value:0),
negative_sum_((value < 0)?-value:0) {}
robust_dif(const T& pos, const T& neg) :
positive_sum_(pos),
negative_sum_(neg) {}
T dif() const {
return positive_sum_ - negative_sum_;
}
T pos() const {
return positive_sum_;
}
T neg() const {
return negative_sum_;
}
robust_dif<T> operator-() const {
return robust_dif(negative_sum_, positive_sum_);
}
robust_dif<T>& operator+=(const T& val) {
if (!is_neg(val))
positive_sum_ += val;
else
negative_sum_ -= val;
return *this;
}
robust_dif<T>& operator+=(const robust_dif<T>& that) {
positive_sum_ += that.positive_sum_;
negative_sum_ += that.negative_sum_;
return *this;
}
robust_dif<T>& operator-=(const T& val) {
if (!is_neg(val))
negative_sum_ += val;
else
positive_sum_ -= val;
return *this;
}
robust_dif<T>& operator-=(const robust_dif<T>& that) {
positive_sum_ += that.negative_sum_;
negative_sum_ += that.positive_sum_;
return *this;
}
robust_dif<T>& operator*=(const T& val) {
if (!is_neg(val)) {
positive_sum_ *= val;
negative_sum_ *= val;
} else {
positive_sum_ *= -val;
negative_sum_ *= -val;
swap();
}
return *this;
}
robust_dif<T>& operator*=(const robust_dif<T>& that) {
T positive_sum = this->positive_sum_ * that.positive_sum_ +
this->negative_sum_ * that.negative_sum_;
T negative_sum = this->positive_sum_ * that.negative_sum_ +
this->negative_sum_ * that.positive_sum_;
positive_sum_ = positive_sum;
negative_sum_ = negative_sum;
return *this;
}
robust_dif<T>& operator/=(const T& val) {
if (!is_neg(val)) {
positive_sum_ /= val;
negative_sum_ /= val;
} else {
positive_sum_ /= -val;
negative_sum_ /= -val;
swap();
}
return *this;
}
private:
void swap() {
(std::swap)(positive_sum_, negative_sum_);
}
T positive_sum_;
T negative_sum_;
};
template<typename T>
robust_dif<T> operator+(const robust_dif<T>& lhs,
const robust_dif<T>& rhs) {
return robust_dif<T>(lhs.pos() + rhs.pos(), lhs.neg() + rhs.neg());
}
template<typename T>
robust_dif<T> operator+(const robust_dif<T>& lhs, const T& rhs) {
if (!is_neg(rhs)) {
return robust_dif<T>(lhs.pos() + rhs, lhs.neg());
} else {
return robust_dif<T>(lhs.pos(), lhs.neg() - rhs);
}
}
template<typename T>
robust_dif<T> operator+(const T& lhs, const robust_dif<T>& rhs) {
if (!is_neg(lhs)) {
return robust_dif<T>(lhs + rhs.pos(), rhs.neg());
} else {
return robust_dif<T>(rhs.pos(), rhs.neg() - lhs);
}
}
template<typename T>
robust_dif<T> operator-(const robust_dif<T>& lhs,
const robust_dif<T>& rhs) {
return robust_dif<T>(lhs.pos() + rhs.neg(), lhs.neg() + rhs.pos());
}
template<typename T>
robust_dif<T> operator-(const robust_dif<T>& lhs, const T& rhs) {
if (!is_neg(rhs)) {
return robust_dif<T>(lhs.pos(), lhs.neg() + rhs);
} else {
return robust_dif<T>(lhs.pos() - rhs, lhs.neg());
}
}
template<typename T>
robust_dif<T> operator-(const T& lhs, const robust_dif<T>& rhs) {
if (!is_neg(lhs)) {
return robust_dif<T>(lhs + rhs.neg(), rhs.pos());
} else {
return robust_dif<T>(rhs.neg(), rhs.pos() - lhs);
}
}
template<typename T>
robust_dif<T> operator*(const robust_dif<T>& lhs,
const robust_dif<T>& rhs) {
T res_pos = lhs.pos() * rhs.pos() + lhs.neg() * rhs.neg();
T res_neg = lhs.pos() * rhs.neg() + lhs.neg() * rhs.pos();
return robust_dif<T>(res_pos, res_neg);
}
template<typename T>
robust_dif<T> operator*(const robust_dif<T>& lhs, const T& val) {
if (!is_neg(val)) {
return robust_dif<T>(lhs.pos() * val, lhs.neg() * val);
} else {
return robust_dif<T>(-lhs.neg() * val, -lhs.pos() * val);
}
}
template<typename T>
robust_dif<T> operator*(const T& val, const robust_dif<T>& rhs) {
if (!is_neg(val)) {
return robust_dif<T>(val * rhs.pos(), val * rhs.neg());
} else {
return robust_dif<T>(-val * rhs.neg(), -val * rhs.pos());
}
}
template<typename T>
robust_dif<T> operator/(const robust_dif<T>& lhs, const T& val) {
if (!is_neg(val)) {
return robust_dif<T>(lhs.pos() / val, lhs.neg() / val);
} else {
return robust_dif<T>(-lhs.neg() / val, -lhs.pos() / val);
}
}
// Used to compute expressions that operate with sqrts with predefined
// relative error. Evaluates expressions of the next type:
// sum(i = 1 .. n)(A[i] * sqrt(B[i])), 1 <= n <= 4.
template <typename _int, typename _fpt, typename _converter>
class robust_sqrt_expr {
public:
enum MAX_RELATIVE_ERROR {
MAX_RELATIVE_ERROR_EVAL1 = 4,
MAX_RELATIVE_ERROR_EVAL2 = 7,
MAX_RELATIVE_ERROR_EVAL3 = 16,
MAX_RELATIVE_ERROR_EVAL4 = 25
};
// Evaluates expression (re = 4 EPS):
// A[0] * sqrt(B[0]).
_fpt eval1(_int* A, _int* B) {
_fpt a = convert(A[0]);
_fpt b = convert(B[0]);
return a * get_sqrt(b);
}
// Evaluates expression (re = 7 EPS):
// A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]).
_fpt eval2(_int* A, _int* B) {
_fpt a = eval1(A, B);
_fpt b = eval1(A + 1, B + 1);
if ((!is_neg(a) && !is_neg(b)) ||
(!is_pos(a) && !is_pos(b)))
return a + b;
return convert(A[0] * A[0] * B[0] - A[1] * A[1] * B[1]) / (a - b);
}
// Evaluates expression (re = 16 EPS):
// A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) + A[2] * sqrt(B[2]).
_fpt eval3(_int* A, _int* B) {
_fpt a = eval2(A, B);
_fpt b = eval1(A + 2, B + 2);
if ((!is_neg(a) && !is_neg(b)) ||
(!is_pos(a) && !is_pos(b)))
return a + b;
tA[3] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] - A[2] * A[2] * B[2];
tB[3] = 1;
tA[4] = A[0] * A[1] * 2;
tB[4] = B[0] * B[1];
return eval2(tA + 3, tB + 3) / (a - b);
}
// Evaluates expression (re = 25 EPS):
// A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) +
// A[2] * sqrt(B[2]) + A[3] * sqrt(B[3]).
_fpt eval4(_int* A, _int* B) {
_fpt a = eval2(A, B);
_fpt b = eval2(A + 2, B + 2);
if ((!is_neg(a) && !is_neg(b)) ||
(!is_pos(a) && !is_pos(b)))
return a + b;
tA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] -
A[2] * A[2] * B[2] - A[3] * A[3] * B[3];
tB[0] = 1;
tA[1] = A[0] * A[1] * 2;
tB[1] = B[0] * B[1];
tA[2] = A[2] * A[3] * -2;
tB[2] = B[2] * B[3];
return eval3(tA, tB) / (a - b);
}
private:
_int tA[5];
_int tB[5];
_converter convert;
};
} // detail
} // polygon
} // boost
#endif // BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT

View file

@ -0,0 +1,450 @@
// Boost.Polygon library detail/voronoi_structures.hpp header file
// Copyright Andrii Sydorchuk 2010-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES
#define BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES
#include <list>
#include <queue>
#include <vector>
#include "boost/polygon/voronoi_geometry_type.hpp"
namespace boost {
namespace polygon {
namespace detail {
// Cartesian 2D point data structure.
template <typename T>
class point_2d {
public:
typedef T coordinate_type;
point_2d() {}
point_2d(coordinate_type x, coordinate_type y) :
x_(x),
y_(y) {}
bool operator==(const point_2d& that) const {
return (this->x_ == that.x()) && (this->y_ == that.y());
}
bool operator!=(const point_2d& that) const {
return (this->x_ != that.x()) || (this->y_ != that.y());
}
coordinate_type x() const {
return x_;
}
coordinate_type y() const {
return y_;
}
point_2d& x(coordinate_type x) {
x_ = x;
return *this;
}
point_2d& y(coordinate_type y) {
y_ = y;
return *this;
}
private:
coordinate_type x_;
coordinate_type y_;
};
// Site event type.
// Occurs when the sweepline sweeps over one of the initial sites:
// 1) point site
// 2) start-point of the segment site
// 3) endpoint of the segment site
// Implicit segment direction is defined: the start-point of
// the segment compares less than its endpoint.
// Each input segment is divided onto two site events:
// 1) One going from the start-point to the endpoint
// (is_inverse() = false)
// 2) Another going from the endpoint to the start-point
// (is_inverse() = true)
// In beach line data structure segment sites of the first
// type precede sites of the second type for the same segment.
// Members:
// point0_ - point site or segment's start-point
// point1_ - segment's endpoint if site is a segment
// sorted_index_ - the last bit encodes information if the site is inverse;
// the other bits encode site event index among the sorted site events
// initial_index_ - site index among the initial input set
// Note: for all sites is_inverse_ flag is equal to false by default.
template <typename T>
class site_event {
public:
typedef T coordinate_type;
typedef point_2d<T> point_type;
site_event() :
point0_(0, 0),
point1_(0, 0),
sorted_index_(0),
flags_(0) {}
site_event(coordinate_type x, coordinate_type y) :
point0_(x, y),
point1_(x, y),
sorted_index_(0),
flags_(0) {}
explicit site_event(const point_type& point) :
point0_(point),
point1_(point),
sorted_index_(0),
flags_(0) {}
site_event(coordinate_type x1, coordinate_type y1,
coordinate_type x2, coordinate_type y2):
point0_(x1, y1),
point1_(x2, y2),
sorted_index_(0),
flags_(0) {}
site_event(const point_type& point1, const point_type& point2) :
point0_(point1),
point1_(point2),
sorted_index_(0),
flags_(0) {}
bool operator==(const site_event& that) const {
return (this->point0_ == that.point0_) &&
(this->point1_ == that.point1_);
}
bool operator!=(const site_event& that) const {
return (this->point0_ != that.point0_) ||
(this->point1_ != that.point1_);
}
coordinate_type x() const {
return point0_.x();
}
coordinate_type y() const {
return point0_.y();
}
coordinate_type x0() const {
return point0_.x();
}
coordinate_type y0() const {
return point0_.y();
}
coordinate_type x1() const {
return point1_.x();
}
coordinate_type y1() const {
return point1_.y();
}
const point_type& point0() const {
return point0_;
}
const point_type& point1() const {
return point1_;
}
std::size_t sorted_index() const {
return sorted_index_;
}
site_event& sorted_index(std::size_t index) {
sorted_index_ = index;
return *this;
}
std::size_t initial_index() const {
return initial_index_;
}
site_event& initial_index(std::size_t index) {
initial_index_ = index;
return *this;
}
bool is_inverse() const {
return (flags_ & IS_INVERSE) ? true : false;
}
site_event& inverse() {
std::swap(point0_, point1_);
flags_ ^= IS_INVERSE;
return *this;
}
SourceCategory source_category() const {
return static_cast<SourceCategory>(flags_ & SOURCE_CATEGORY_BITMASK);
}
site_event& source_category(SourceCategory source_category) {
flags_ |= source_category;
return *this;
}
bool is_point() const {
return (point0_.x() == point1_.x()) && (point0_.y() == point1_.y());
}
bool is_segment() const {
return (point0_.x() != point1_.x()) || (point0_.y() != point1_.y());
}
private:
enum Bits {
IS_INVERSE = 0x20 // 32
};
point_type point0_;
point_type point1_;
std::size_t sorted_index_;
std::size_t initial_index_;
std::size_t flags_;
};
// Circle event type.
// Occurs when the sweepline sweeps over the rightmost point of the Voronoi
// circle (with the center at the intersection point of the bisectors).
// Circle event is made of the two consecutive nodes in the beach line data
// structure. In case another node was inserted during algorithm execution
// between the given two nodes circle event becomes inactive.
// Variables:
// center_x_ - center x-coordinate;
// center_y_ - center y-coordinate;
// lower_x_ - leftmost x-coordinate;
// is_active_ - states whether circle event is still active.
// NOTE: lower_y coordinate is always equal to center_y.
template <typename T>
class circle_event {
public:
typedef T coordinate_type;
circle_event() : is_active_(true) {}
circle_event(coordinate_type c_x,
coordinate_type c_y,
coordinate_type lower_x) :
center_x_(c_x),
center_y_(c_y),
lower_x_(lower_x),
is_active_(true) {}
coordinate_type x() const {
return center_x_;
}
circle_event& x(coordinate_type center_x) {
center_x_ = center_x;
return *this;
}
coordinate_type y() const {
return center_y_;
}
circle_event& y(coordinate_type center_y) {
center_y_ = center_y;
return *this;
}
coordinate_type lower_x() const {
return lower_x_;
}
circle_event& lower_x(coordinate_type lower_x) {
lower_x_ = lower_x;
return *this;
}
coordinate_type lower_y() const {
return center_y_;
}
bool is_active() const {
return is_active_;
}
circle_event& deactivate() {
is_active_ = false;
return *this;
}
private:
coordinate_type center_x_;
coordinate_type center_y_;
coordinate_type lower_x_;
bool is_active_;
};
// Event queue data structure, holds circle events.
// During algorithm run, some of the circle events disappear (become
// inactive). Priority queue data structure doesn't support
// iterators (there is no direct ability to modify its elements).
// Instead list is used to store all the circle events and priority queue
// of the iterators to the list elements is used to keep the correct circle
// events ordering.
template <typename T, typename Predicate>
class ordered_queue {
public:
ordered_queue() {}
bool empty() const {
return c_.empty();
}
const T &top() const {
return *c_.top();
}
void pop() {
list_iterator_type it = c_.top();
c_.pop();
c_list_.erase(it);
}
T &push(const T &e) {
c_list_.push_front(e);
c_.push(c_list_.begin());
return c_list_.front();
}
void clear() {
while (!c_.empty())
c_.pop();
c_list_.clear();
}
private:
typedef typename std::list<T>::iterator list_iterator_type;
struct comparison {
bool operator() (const list_iterator_type &it1,
const list_iterator_type &it2) const {
return cmp_(*it1, *it2);
}
Predicate cmp_;
};
std::priority_queue< list_iterator_type,
std::vector<list_iterator_type>,
comparison > c_;
std::list<T> c_list_;
// Disallow copy constructor and operator=
ordered_queue(const ordered_queue&);
void operator=(const ordered_queue&);
};
// Represents a bisector node made by two arcs that correspond to the left
// and right sites. Arc is defined as a curve with points equidistant from
// the site and from the sweepline. If the site is a point then arc is
// a parabola, otherwise it's a line segment. A segment site event will
// produce different bisectors based on its direction.
// In general case two sites will create two opposite bisectors. That's
// why the order of the sites is important to define the unique bisector.
// The one site is considered to be newer than the other one if it was
// processed by the algorithm later (has greater index).
template <typename Site>
class beach_line_node_key {
public:
typedef Site site_type;
// Constructs degenerate bisector, used to search an arc that is above
// the given site. The input to the constructor is the new site point.
explicit beach_line_node_key(const site_type &new_site) :
left_site_(new_site),
right_site_(new_site) {}
// Constructs a new bisector. The input to the constructor is the two
// sites that create the bisector. The order of sites is important.
beach_line_node_key(const site_type &left_site,
const site_type &right_site) :
left_site_(left_site),
right_site_(right_site) {}
const site_type &left_site() const {
return left_site_;
}
site_type &left_site() {
return left_site_;
}
beach_line_node_key& left_site(const site_type &site) {
left_site_ = site;
return *this;
}
const site_type &right_site() const {
return right_site_;
}
site_type &right_site() {
return right_site_;
}
beach_line_node_key& right_site(const site_type &site) {
right_site_ = site;
return *this;
}
private:
site_type left_site_;
site_type right_site_;
};
// Represents edge data structure from the Voronoi output, that is
// associated as a value with beach line bisector in the beach
// line. Contains pointer to the circle event in the circle event
// queue if the edge corresponds to the right bisector of the circle event.
template <typename Edge, typename Circle>
class beach_line_node_data {
public:
explicit beach_line_node_data(Edge* new_edge) :
circle_event_(NULL),
edge_(new_edge) {}
Circle* circle_event() const {
return circle_event_;
}
beach_line_node_data& circle_event(Circle* circle_event) {
circle_event_ = circle_event;
return *this;
}
Edge* edge() const {
return edge_;
}
beach_line_node_data& edge(Edge* new_edge) {
edge_ = new_edge;
return *this;
}
private:
Circle* circle_event_;
Edge* edge_;
};
} // detail
} // polygon
} // boost
#endif // BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES

View file

@ -0,0 +1,128 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_GMP_OVERRIDE_HPP
#define BOOST_POLYGON_GMP_OVERRIDE_HPP
#include <gmpxx.h>
namespace boost { namespace polygon {
class gmp_int {
private:
inline gmp_int(const mpq_class& input) : v_(input) {}
public:
inline gmp_int() {}
explicit inline gmp_int(long input) : v_(input) {}
inline gmp_int(const gmp_int& input) : v_(input.v_) {}
inline gmp_int& operator=(const gmp_int& that) {
v_ = that.v_;
return (*this);
}
inline gmp_int& operator=(long that) {
v_ = that;
return (*this);
}
inline operator int() const {
std::cout << "cast\n";
mpz_class num = v_.get_num();
mpz_class den = v_.get_den();
num /= den;
return num.get_si();
}
inline double get_d() const {
return v_.get_d();
}
inline int get_num() const {
return v_.get_num().get_si();
}
inline int get_den() const {
return v_.get_den().get_si();
}
inline bool operator==(const gmp_int& that) const {
return v_ == that.v_;
}
inline bool operator!=(const gmp_int& that) const {
return v_ != that.v_;
}
inline bool operator<(const gmp_int& that) const {
bool retval = v_ < that.v_;
return retval;
}
inline bool operator<=(const gmp_int& that) const {
return v_ <= that.v_;
}
inline bool operator>(const gmp_int& that) const {
return v_ > that.v_;
}
inline bool operator>=(const gmp_int& that) const {
return v_ >= that.v_;
}
inline gmp_int operator+(const gmp_int& b) {
return gmp_int((*this).v_ + b.v_);
}
inline gmp_int operator-(const gmp_int& b) {
return gmp_int((*this).v_ - b.v_);
}
inline gmp_int operator*(const gmp_int& b) {
return gmp_int((*this).v_ * b.v_);
}
inline gmp_int operator/(const gmp_int& b) {
return gmp_int((*this).v_ / b.v_);
}
inline gmp_int& operator+=(const gmp_int& b) {
(*this).v_ += b.v_;
return (*this);
}
inline gmp_int& operator-=(const gmp_int& b) {
(*this).v_ -= b.v_;
return (*this);
}
inline gmp_int& operator*=(const gmp_int& b) {
(*this).v_ *= b.v_;
return (*this);
}
inline gmp_int& operator/=(const gmp_int& b) {
(*this).v_ /= b.v_;
return (*this);
}
inline gmp_int& operator++() {
++v_;
return (*this);
}
inline gmp_int& operator--() {
--v_;
return (*this);
}
inline gmp_int operator++(int) {
gmp_int retval(*this);
++(*this);
return retval;
}
inline gmp_int operator--(int) {
gmp_int retval(*this);
--(*this);
return retval;
}
private:
mpq_class v_;
};
template <>
struct high_precision_type<int> {
typedef mpq_class type;
};
template <>
int convert_high_precision_type<int>(const mpq_class& v) {
mpz_class num = v.get_num();
mpz_class den = v.get_den();
num /= den;
return num.get_si();
};
}
}
#endif

View file

@ -0,0 +1,35 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef GTL_GTL_HPP
#define GTL_GTL_HPP
#ifdef __ICC
#pragma warning (push)
#pragma warning (disable:1125)
#endif
#ifdef WIN32
#pragma warning (push)
#pragma warning( disable: 4996 )
#pragma warning( disable: 4800 )
#endif
#define BOOST_POLYGON_NO_DEPS
#include "polygon.hpp"
namespace gtl = boost::polygon;
using namespace boost::polygon::operators;
#ifdef WIN32
#pragma warning (pop)
#endif
#ifdef __ICC
#pragma warning (pop)
#endif
#endif

View file

@ -0,0 +1,935 @@
// Boost.Polygon library interval_concept.hpp header file
// Copyright (c) Intel Corporation 2008.
// Copyright (c) 2008-2012 Simonson Lucanus.
// Copyright (c) 2012-2012 Andrii Sydorchuk.
// See http://www.boost.org for updates, documentation, and revision history.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_POLYGON_INTERVAL_CONCEPT_HPP
#define BOOST_POLYGON_INTERVAL_CONCEPT_HPP
#include "isotropy.hpp"
#include "interval_traits.hpp"
namespace boost {
namespace polygon {
struct interval_concept {};
template <typename ConceptType>
struct is_interval_concept {
typedef gtl_no type;
};
template <>
struct is_interval_concept<interval_concept> {
typedef gtl_yes type;
};
template <typename ConceptType>
struct is_mutable_interval_concept {
typedef gtl_no type;
};
template <>
struct is_mutable_interval_concept<interval_concept> {
typedef gtl_yes type;
};
template <typename GeometryType, typename BoolType>
struct interval_coordinate_type_by_concept {
typedef void type;
};
template <typename GeometryType>
struct interval_coordinate_type_by_concept<GeometryType, gtl_yes> {
typedef typename interval_traits<GeometryType>::coordinate_type type;
};
template <typename GeometryType>
struct interval_coordinate_type {
typedef typename interval_coordinate_type_by_concept<
GeometryType,
typename is_interval_concept<
typename geometry_concept<GeometryType>::type
>::type
>::type type;
};
template <typename GeometryType, typename BoolType>
struct interval_difference_type_by_concept {
typedef void type;
};
template <typename GeometryType>
struct interval_difference_type_by_concept<GeometryType, gtl_yes> {
typedef typename coordinate_traits<
typename interval_traits<GeometryType>::coordinate_type
>::coordinate_difference type;
};
template <typename GeometryType>
struct interval_difference_type {
typedef typename interval_difference_type_by_concept<
GeometryType,
typename is_interval_concept<
typename geometry_concept<GeometryType>::type
>::type
>::type type;
};
struct y_i_get : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_get,
typename is_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
typename interval_coordinate_type<IntervalType>::type
>::type get(const IntervalType& interval, direction_1d dir) {
return interval_traits<IntervalType>::get(interval, dir);
}
struct y_i_set : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_set,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
void
>::type set(IntervalType& interval, direction_1d dir,
typename interval_mutable_traits<IntervalType>::coordinate_type value) {
interval_mutable_traits<IntervalType>::set(interval, dir, value);
}
struct y_i_construct : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_construct,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
IntervalType
>::type construct(
typename interval_mutable_traits<IntervalType>::coordinate_type low,
typename interval_mutable_traits<IntervalType>::coordinate_type high) {
if (low > high) {
(std::swap)(low, high);
}
return interval_mutable_traits<IntervalType>::construct(low, high);
}
struct y_i_copy_construct : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_copy_construct,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
IntervalType1
>::type copy_construct(const IntervalType2& interval) {
return construct<IntervalType1>(get(interval, LOW), get(interval, HIGH));
}
struct y_i_assign : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_assign,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
IntervalType1
>::type& assign(IntervalType1& lvalue, const IntervalType2& rvalue) {
set(lvalue, LOW, get(rvalue, LOW));
set(lvalue, HIGH, get(rvalue, HIGH));
return lvalue;
}
struct y_i_low : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_low,
typename is_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
typename interval_coordinate_type<IntervalType>::type
>::type low(const IntervalType& interval) {
return get(interval, LOW);
}
struct y_i_high : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_high,
typename is_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
typename interval_coordinate_type<IntervalType>::type
>::type high(const IntervalType& interval) {
return get(interval, HIGH);
}
struct y_i_low2 : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_low2,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
void
>::type low(IntervalType& interval,
typename interval_mutable_traits<IntervalType>::coordinate_type value) {
set(interval, LOW, value);
}
struct y_i_high2 : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_high2,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
void
>::type high(IntervalType& interval,
typename interval_mutable_traits<IntervalType>::coordinate_type value) {
set(interval, HIGH, value);
}
struct y_i_equivalence : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_equivalence,
typename is_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
bool
>::type equivalence(
const IntervalType1& interval1,
const IntervalType2& interval2) {
return (get(interval1, LOW) == get(interval2, LOW)) &&
(get(interval1, HIGH) == get(interval2, HIGH));
}
struct y_i_contains : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_contains,
typename is_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
bool
>::type contains(
const IntervalType& interval,
typename interval_coordinate_type<IntervalType>::type value,
bool consider_touch = true ) {
if (consider_touch) {
return value <= high(interval) && value >= low(interval);
} else {
return value < high(interval) && value > low(interval);
}
}
struct y_i_contains2 : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_contains2,
typename is_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
bool
>::type contains(
const IntervalType1& interval1,
const IntervalType2& interval2,
bool consider_touch = true) {
return contains(interval1, get(interval2, LOW), consider_touch) &&
contains(interval1, get(interval2, HIGH), consider_touch);
}
struct y_i_center : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_center,
typename is_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
typename interval_coordinate_type<IntervalType>::type
>::type center(const IntervalType& interval) {
return (high(interval) + low(interval)) / 2;
}
struct y_i_delta : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_delta,
typename is_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
typename interval_difference_type<IntervalType>::type
>::type delta(const IntervalType& interval) {
typedef typename interval_difference_type<IntervalType>::type diff_type;
return static_cast<diff_type>(high(interval)) -
static_cast<diff_type>(low(interval));
}
struct y_i_flip : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_flip,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
IntervalType>::type& flip(
IntervalType& interval,
typename interval_coordinate_type<IntervalType>::type axis = 0) {
typename interval_coordinate_type<IntervalType>::type newLow, newHigh;
newLow = 2 * axis - high(interval);
newHigh = 2 * axis - low(interval);
low(interval, newLow);
high(interval, newHigh);
return interval;
}
struct y_i_scale_up : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_scale_up,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
IntervalType
>::type& scale_up(
IntervalType& interval,
typename interval_coordinate_type<IntervalType>::type factor) {
typename interval_coordinate_type<IntervalType>::type newHigh =
high(interval) * factor;
low(interval, low(interval) * factor);
high(interval, (newHigh));
return interval;
}
struct y_i_scale_down : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_scale_down,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
IntervalType
>::type& scale_down(
IntervalType& interval,
typename interval_coordinate_type<IntervalType>::type factor) {
typedef typename interval_coordinate_type<IntervalType>::type Unit;
typename interval_coordinate_type<IntervalType>::type newHigh =
high(interval) / factor;
low(interval, low(interval) / factor);
high(interval, (newHigh));
return interval;
}
// TODO(asydorchuk): Deprecated.
struct y_i_scale : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_scale,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
IntervalType
>::type& scale(IntervalType& interval, double factor) {
typedef typename interval_coordinate_type<IntervalType>::type Unit;
Unit newHigh = scaling_policy<Unit>::round(
static_cast<double>(high(interval)) * factor);
low(interval, scaling_policy<Unit>::round(
static_cast<double>(low(interval)) * factor));
high(interval, (newHigh));
return interval;
}
struct y_i_move : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_move,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
IntervalType
>::type& move(
IntervalType& interval,
typename interval_difference_type<IntervalType>::type displacement) {
typedef typename interval_coordinate_type<IntervalType>::type ctype;
typedef typename coordinate_traits<ctype>::coordinate_difference Unit;
low(interval, static_cast<ctype>(
static_cast<Unit>(low(interval)) + displacement));
high(interval, static_cast<ctype>(
static_cast<Unit>(high(interval)) + displacement));
return interval;
}
struct y_i_convolve : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_convolve,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
IntervalType
>::type& convolve(
IntervalType& interval,
typename interval_coordinate_type<IntervalType>::type value) {
typedef typename interval_coordinate_type<IntervalType>::type Unit;
Unit newLow = low(interval) + value;
Unit newHigh = high(interval) + value;
low(interval, newLow);
high(interval, newHigh);
return interval;
}
struct y_i_deconvolve : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_deconvolve,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
IntervalType
>::type& deconvolve(
IntervalType& interval,
typename interval_coordinate_type<IntervalType>::type value) {
typedef typename interval_coordinate_type<IntervalType>::type Unit;
Unit newLow = low(interval) - value;
Unit newHigh = high(interval) - value;
low(interval, newLow);
high(interval, newHigh);
return interval;
}
struct y_i_convolve2 : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_convolve2,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
IntervalType1
>::type& convolve(IntervalType1& lvalue, const IntervalType2& rvalue) {
typedef typename interval_coordinate_type<IntervalType1>::type Unit;
Unit newLow = low(lvalue) + low(rvalue);
Unit newHigh = high(lvalue) + high(rvalue);
low(lvalue, newLow);
high(lvalue, newHigh);
return lvalue;
}
struct y_i_deconvolve2 : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_deconvolve2,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
IntervalType1
>::type& deconvolve(IntervalType1& lvalue, const IntervalType2& rvalue) {
typedef typename interval_coordinate_type<IntervalType1>::type Unit;
Unit newLow = low(lvalue) - low(rvalue);
Unit newHigh = high(lvalue) - high(rvalue);
low(lvalue, newLow);
high(lvalue, newHigh);
return lvalue;
}
struct y_i_reconvolve : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_reconvolve,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
IntervalType1
>::type& reflected_convolve(
IntervalType1& lvalue,
const IntervalType2& rvalue) {
typedef typename interval_coordinate_type<IntervalType1>::type Unit;
Unit newLow = low(lvalue) - high(rvalue);
Unit newHigh = high(lvalue) - low(rvalue);
low(lvalue, newLow);
high(lvalue, newHigh);
return lvalue;
}
struct y_i_redeconvolve : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_redeconvolve,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
IntervalType1
>::type& reflected_deconvolve(
IntervalType1& lvalue,
const IntervalType2& rvalue) {
typedef typename interval_coordinate_type<IntervalType1>::type Unit;
Unit newLow = low(lvalue) + high(rvalue);
Unit newHigh = high(lvalue) + low(rvalue);
low(lvalue, newLow);
high(lvalue, newHigh);
return lvalue;
}
struct y_i_e_dist1 : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<y_i_e_dist1,
typename is_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
typename interval_difference_type<IntervalType>::type
>::type euclidean_distance(
const IntervalType& interval,
typename interval_coordinate_type<IntervalType>::type position) {
typedef typename interval_difference_type<IntervalType>::type Unit;
Unit dist[3] = {
0,
(Unit)low(interval) - (Unit)position,
(Unit)position - (Unit)high(interval)
};
return dist[(dist[1] > 0) + ((dist[2] > 0) << 1)];
}
struct y_i_e_dist2 : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_e_dist2,
typename is_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
typename interval_difference_type<IntervalType1>::type
>::type euclidean_distance(
const IntervalType1& interval1,
const IntervalType2& interval2) {
typedef typename interval_difference_type<IntervalType1>::type Unit;
Unit dist[3] = {
0,
(Unit)low(interval1) - (Unit)high(interval2),
(Unit)low(interval2) - (Unit)high(interval1)
};
return dist[(dist[1] > 0) + ((dist[2] > 0) << 1)];
}
struct y_i_e_intersects : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_e_intersects,
typename is_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
bool
>::type intersects(
const IntervalType1& interval1,
const IntervalType2& interval2,
bool consider_touch = true) {
return consider_touch ?
(low(interval1) <= high(interval2)) &&
(high(interval1) >= low(interval2)) :
(low(interval1) < high(interval2)) &&
(high(interval1) > low(interval2));
}
struct y_i_e_bintersect : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_e_bintersect,
typename is_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
bool
>::type boundaries_intersect(
const IntervalType1& interval1,
const IntervalType2& interval2,
bool consider_touch = true) {
return (contains(interval1, low(interval2), consider_touch) ||
contains(interval1, high(interval2), consider_touch)) &&
(contains(interval2, low(interval1), consider_touch) ||
contains(interval2, high(interval1), consider_touch));
}
struct y_i_intersect : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_intersect,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
bool
>::type intersect(
IntervalType1& lvalue,
const IntervalType2& rvalue,
bool consider_touch = true) {
typedef typename interval_coordinate_type<IntervalType1>::type Unit;
Unit lowVal = (std::max)(low(lvalue), low(rvalue));
Unit highVal = (std::min)(high(lvalue), high(rvalue));
bool valid = consider_touch ? lowVal <= highVal : lowVal < highVal;
if (valid) {
low(lvalue, lowVal);
high(lvalue, highVal);
}
return valid;
}
struct y_i_g_intersect : gtl_yes {};
// TODO(asydorchuk): Deprecated.
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_g_intersect,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
IntervalType1
>::type& generalized_intersect(
IntervalType1& lvalue,
const IntervalType2& rvalue) {
typedef typename interval_coordinate_type<IntervalType1>::type Unit;
Unit coords[4] = {low(lvalue), high(lvalue), low(rvalue), high(rvalue)};
// TODO(asydorchuk): consider implementing faster sorting of small
// fixed length range.
polygon_sort(coords, coords+4);
low(lvalue, coords[1]);
high(lvalue, coords[2]);
return lvalue;
}
struct y_i_abuts1 : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_abuts1,
typename is_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
bool
>::type abuts(
const IntervalType1& interval1,
const IntervalType2& interval2,
direction_1d dir) {
return dir.to_int() ? low(interval2) == high(interval1) :
low(interval1) == high(interval2);
}
struct y_i_abuts2 : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_abuts2,
typename is_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
bool
>::type abuts(
const IntervalType1& interval1,
const IntervalType2& interval2) {
return abuts(interval1, interval2, HIGH) ||
abuts(interval1, interval2, LOW);
}
struct y_i_bloat : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_bloat,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
IntervalType
>::type& bloat(
IntervalType& interval,
typename interval_coordinate_type<IntervalType>::type bloating) {
low(interval, low(interval) - bloating);
high(interval, high(interval) + bloating);
return interval;
}
struct y_i_bloat2 : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_bloat2,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
IntervalType
>::type& bloat(
IntervalType& interval,
direction_1d dir,
typename interval_coordinate_type<IntervalType>::type bloating) {
set(interval, dir, get(interval, dir) + dir.get_sign() * bloating);
return interval;
}
struct y_i_shrink : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_shrink,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
IntervalType
>::type& shrink(
IntervalType& interval,
typename interval_coordinate_type<IntervalType>::type shrinking) {
return bloat(interval, -shrinking);
}
struct y_i_shrink2 : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_shrink2,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
IntervalType
>::type& shrink(
IntervalType& interval,
direction_1d dir,
typename interval_coordinate_type<IntervalType>::type shrinking) {
return bloat(interval, dir, -shrinking);
}
struct y_i_encompass : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_encompass,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type
>::type,
bool
>::type encompass(IntervalType1& interval1, const IntervalType2& interval2) {
bool retval = !contains(interval1, interval2, true);
low(interval1, (std::min)(low(interval1), low(interval2)));
high(interval1, (std::max)(high(interval1), high(interval2)));
return retval;
}
struct y_i_encompass2 : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_encompass2,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
bool
>::type encompass(
IntervalType& interval,
typename interval_coordinate_type<IntervalType>::type value) {
bool retval = !contains(interval, value, true);
low(interval, (std::min)(low(interval), value));
high(interval, (std::max)(high(interval), value));
return retval;
}
struct y_i_get_half : gtl_yes {};
template <typename IntervalType>
typename enable_if<
typename gtl_and<
y_i_get_half,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType>::type
>::type
>::type,
IntervalType
>::type get_half(const IntervalType& interval, direction_1d dir) {
typedef typename interval_coordinate_type<IntervalType>::type Unit;
Unit c = (get(interval, LOW) + get(interval, HIGH)) / 2;
return construct<IntervalType>(
(dir == LOW) ? get(interval, LOW) : c,
(dir == LOW) ? c : get(interval, HIGH));
}
struct y_i_join_with : gtl_yes {};
template <typename IntervalType1, typename IntervalType2>
typename enable_if<
typename gtl_and_3<
y_i_join_with,
typename is_mutable_interval_concept<
typename geometry_concept<IntervalType1>::type
>::type,
typename is_interval_concept<
typename geometry_concept<IntervalType2>::type
>::type>::type,
bool
>::type join_with(IntervalType1& interval1, const IntervalType2& interval2) {
if (abuts(interval1, interval2)) {
encompass(interval1, interval2);
return true;
}
return false;
}
} // polygon
} // boost
#endif // BOOST_POLYGON_INTERVAL_CONCEPT_HPP

View file

@ -0,0 +1,118 @@
// Boost.Polygon library interval_data.hpp header file
// Copyright (c) Intel Corporation 2008.
// Copyright (c) 2008-2012 Simonson Lucanus.
// Copyright (c) 2012-2012 Andrii Sydorchuk.
// See http://www.boost.org for updates, documentation, and revision history.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_POLYGON_INTERVAL_DATA_HPP
#define BOOST_POLYGON_INTERVAL_DATA_HPP
#include "isotropy.hpp"
#include "interval_concept.hpp"
namespace boost {
namespace polygon {
template <typename T>
class interval_data {
public:
typedef T coordinate_type;
interval_data()
#ifndef BOOST_POLYGON_MSVC
: coords_()
#endif
{}
interval_data(coordinate_type low, coordinate_type high) {
coords_[LOW] = low;
coords_[HIGH] = high;
}
interval_data(const interval_data& that) {
coords_[0] = that.coords_[0];
coords_[1] = that.coords_[1];
}
interval_data& operator=(const interval_data& that) {
coords_[0] = that.coords_[0];
coords_[1] = that.coords_[1];
return *this;
}
template <typename IntervalType>
interval_data& operator=(const IntervalType& that) {
assign(*this, that);
return *this;
}
coordinate_type get(direction_1d dir) const {
return coords_[dir.to_int()];
}
void set(direction_1d dir, coordinate_type value) {
coords_[dir.to_int()] = value;
}
coordinate_type low() const {
return coords_[0];
}
interval_data& low(coordinate_type value) {
coords_[LOW] = value;
return *this;
}
coordinate_type high() const {
return coords_[1];
}
interval_data& high(coordinate_type value) {
coords_[HIGH] = value;
return *this;
}
bool operator==(const interval_data& that) const {
return low() == that.low() && high() == that.high();
}
bool operator!=(const interval_data& that) const {
return low() != that.low() || high() != that.high();
}
bool operator<(const interval_data& that) const {
if (coords_[0] != that.coords_[0]) {
return coords_[0] < that.coords_[0];
}
return coords_[1] < that.coords_[1];
}
bool operator<=(const interval_data& that) const {
return !(that < *this);
}
bool operator>(const interval_data& that) const {
return that < *this;
}
bool operator>=(const interval_data& that) const {
return !((*this) < that);
}
private:
coordinate_type coords_[2];
};
template <typename CType>
struct geometry_concept< interval_data<CType> > {
typedef interval_concept type;
};
} // polygon
} // boost
#endif // BOOST_POLYGON_INTERVAL_DATA_HPP

View file

@ -0,0 +1,47 @@
// Boost.Polygon library interval_traits.hpp header file
// Copyright (c) Intel Corporation 2008.
// Copyright (c) 2008-2012 Simonson Lucanus.
// Copyright (c) 2012-2012 Andrii Sydorchuk.
// See http://www.boost.org for updates, documentation, and revision history.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_POLYGON_INTERVAL_TRAITS_HPP
#define BOOST_POLYGON_INTERVAL_TRAITS_HPP
#include "isotropy.hpp"
namespace boost {
namespace polygon {
template <typename Interval>
struct interval_traits {
typedef Interval interval_type;
typedef typename interval_type::coordinate_type coordinate_type;
static coordinate_type get(const interval_type& interval, direction_1d dir) {
return interval.get(dir);
}
};
template <typename Interval>
struct interval_mutable_traits {
typedef Interval interval_type;
typedef typename interval_type::coordinate_type coordinate_type;
static void set(
interval_type& interval, direction_1d dir, coordinate_type value) {
interval.set(dir, value);
}
static interval_type construct(coordinate_type low, coordinate_type high) {
return interval_type(low, high);
}
};
} // polygon
} // boost
#endif // BOOST_POLICY_INTERVAL_TRAITS_HPP

View file

@ -0,0 +1,562 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_ISOTROPY_HPP
#define BOOST_POLYGON_ISOTROPY_HPP
//external
#include <cmath>
#include <cstddef>
#include <cstdlib>
#include <vector>
#include <deque>
#include <map>
#include <set>
#include <list>
//#include <iostream>
#include <algorithm>
#include <limits>
#include <iterator>
#include <string>
#ifndef BOOST_POLYGON_NO_DEPS
#include <boost/config.hpp>
#ifdef BOOST_MSVC
#define BOOST_POLYGON_MSVC
#endif
#ifdef BOOST_INTEL
#define BOOST_POLYGON_ICC
#endif
#ifdef BOOST_HAS_LONG_LONG
#define BOOST_POLYGON_USE_LONG_LONG
typedef boost::long_long_type polygon_long_long_type;
typedef boost::ulong_long_type polygon_ulong_long_type;
//typedef long long polygon_long_long_type;
//typedef unsigned long long polygon_ulong_long_type;
#endif
#include <boost/mpl/size_t.hpp>
#include <boost/mpl/protect.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/or.hpp>
#else
#ifdef _WIN32
#define BOOST_POLYGON_MSVC
#endif
#ifdef __ICC
#define BOOST_POLYGON_ICC
#endif
#define BOOST_POLYGON_USE_LONG_LONG
typedef long long polygon_long_long_type;
typedef unsigned long long polygon_ulong_long_type;
namespace boost {
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_enable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_enable_if_c<false, T> {};
template <class Cond, class T>
struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
template <bool B, class T = void>
struct disable_if_c {
typedef T type;
};
template <class T>
struct disable_if_c<true, T> {};
template <class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_disable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_disable_if_c<true, T> {};
template <class Cond, class T>
struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
}
#endif
namespace boost { namespace polygon{
enum GEOMETRY_CONCEPT_ID {
COORDINATE_CONCEPT,
INTERVAL_CONCEPT,
POINT_CONCEPT,
POINT_3D_CONCEPT,
RECTANGLE_CONCEPT,
POLYGON_90_CONCEPT,
POLYGON_90_WITH_HOLES_CONCEPT,
POLYGON_45_CONCEPT,
POLYGON_45_WITH_HOLES_CONCEPT,
POLYGON_CONCEPT,
POLYGON_WITH_HOLES_CONCEPT,
POLYGON_90_SET_CONCEPT,
POLYGON_45_SET_CONCEPT,
POLYGON_SET_CONCEPT
};
struct undefined_concept {};
template <typename T>
struct geometry_concept { typedef undefined_concept type; };
template <typename GCT, typename T>
struct view_of {};
template <typename T1, typename T2>
view_of<T1, T2> view_as(const T2& obj) { return view_of<T1, T2>(obj); }
template <typename T>
struct coordinate_traits {};
//used to override long double with an infinite precision datatype
template <typename T>
struct high_precision_type {
typedef long double type;
};
template <typename T>
T convert_high_precision_type(const typename high_precision_type<T>::type& v) {
return T(v);
}
//used to override std::sort with an alternative (parallel) algorithm
template <typename iter_type>
void polygon_sort(iter_type _b_, iter_type _e_);
template <typename iter_type, typename pred_type>
void polygon_sort(iter_type _b_, iter_type _e_, const pred_type& _pred_);
template <>
struct coordinate_traits<int> {
typedef int coordinate_type;
typedef long double area_type;
#ifdef BOOST_POLYGON_USE_LONG_LONG
typedef polygon_long_long_type manhattan_area_type;
typedef polygon_ulong_long_type unsigned_area_type;
typedef polygon_long_long_type coordinate_difference;
#else
typedef long manhattan_area_type;
typedef unsigned long unsigned_area_type;
typedef long coordinate_difference;
#endif
typedef long double coordinate_distance;
};
#ifdef BOOST_POLYGON_USE_LONG_LONG
template <>
struct coordinate_traits<polygon_long_long_type> {
typedef polygon_long_long_type coordinate_type;
typedef long double area_type;
typedef polygon_long_long_type manhattan_area_type;
typedef polygon_ulong_long_type unsigned_area_type;
typedef polygon_long_long_type coordinate_difference;
typedef long double coordinate_distance;
};
#endif
template <>
struct coordinate_traits<float> {
typedef float coordinate_type;
typedef float area_type;
typedef float manhattan_area_type;
typedef float unsigned_area_type;
typedef float coordinate_difference;
typedef float coordinate_distance;
};
template <>
struct coordinate_traits<double> {
typedef double coordinate_type;
typedef double area_type;
typedef double manhattan_area_type;
typedef double unsigned_area_type;
typedef double coordinate_difference;
typedef double coordinate_distance;
};
template <>
struct coordinate_traits<long double> {
typedef long double coordinate_type;
typedef long double area_type;
typedef long double manhattan_area_type;
typedef long double unsigned_area_type;
typedef long double coordinate_difference;
typedef long double coordinate_distance;
};
template <typename T>
struct scaling_policy {
template <typename T2>
static inline T round(T2 t2) {
return (T)std::floor(t2+0.5);
}
static inline T round(T t2) {
return t2;
}
};
struct coordinate_concept {};
template <>
struct geometry_concept<int> { typedef coordinate_concept type; };
#ifdef BOOST_POLYGON_USE_LONG_LONG
template <>
struct geometry_concept<polygon_long_long_type> { typedef coordinate_concept type; };
#endif
template <>
struct geometry_concept<float> { typedef coordinate_concept type; };
template <>
struct geometry_concept<double> { typedef coordinate_concept type; };
template <>
struct geometry_concept<long double> { typedef coordinate_concept type; };
#ifndef BOOST_POLYGON_NO_DEPS
struct gtl_no : mpl::bool_<false> {};
struct gtl_yes : mpl::bool_<true> {};
template <typename T, typename T2>
struct gtl_and : mpl::and_<T, T2> {};
template <typename T, typename T2, typename T3>
struct gtl_and_3 : mpl::and_<T, T2, T3> {};
template <typename T, typename T2, typename T3, typename T4>
struct gtl_and_4 : mpl::and_<T, T2, T3, T4> {};
// template <typename T, typename T2>
// struct gtl_or : mpl::or_<T, T2> {};
// template <typename T, typename T2, typename T3>
// struct gtl_or_3 : mpl::or_<T, T2, T3> {};
// template <typename T, typename T2, typename T3, typename T4>
// struct gtl_or_4 : mpl::or_<T, T2, T3, T4> {};
#else
struct gtl_no { static const bool value = false; };
struct gtl_yes { typedef gtl_yes type;
static const bool value = true; };
template <bool T, bool T2>
struct gtl_and_c { typedef gtl_no type; };
template <>
struct gtl_and_c<true, true> { typedef gtl_yes type; };
template <typename T, typename T2>
struct gtl_and : gtl_and_c<T::value, T2::value> {};
template <typename T, typename T2, typename T3>
struct gtl_and_3 { typedef typename gtl_and<
T, typename gtl_and<T2, T3>::type>::type type; };
template <typename T, typename T2, typename T3, typename T4>
struct gtl_and_4 { typedef typename gtl_and_3<
T, T2, typename gtl_and<T3, T4>::type>::type type; };
#endif
template <typename T, typename T2>
struct gtl_or { typedef gtl_yes type; };
template <typename T>
struct gtl_or<T, T> { typedef T type; };
template <typename T, typename T2, typename T3>
struct gtl_or_3 { typedef typename gtl_or<
T, typename gtl_or<T2, T3>::type>::type type; };
template <typename T, typename T2, typename T3, typename T4>
struct gtl_or_4 { typedef typename gtl_or<
T, typename gtl_or_3<T2, T3, T4>::type>::type type; };
template <typename T>
struct gtl_not { typedef gtl_no type; };
template <>
struct gtl_not<gtl_no> { typedef gtl_yes type; };
template <typename T>
struct gtl_if {
#ifdef BOOST_POLYGON_MSVC
typedef gtl_no type;
#endif
};
template <>
struct gtl_if<gtl_yes> { typedef gtl_yes type; };
template <typename T, typename T2>
struct gtl_same_type { typedef gtl_no type; };
template <typename T>
struct gtl_same_type<T, T> { typedef gtl_yes type; };
template <typename T, typename T2>
struct gtl_different_type { typedef typename gtl_not<typename gtl_same_type<T, T2>::type>::type type; };
struct manhattan_domain {};
struct forty_five_domain {};
struct general_domain {};
template <typename T>
struct geometry_domain { typedef general_domain type; };
template <typename domain_type, typename coordinate_type>
struct area_type_by_domain { typedef typename coordinate_traits<coordinate_type>::area_type type; };
template <typename coordinate_type>
struct area_type_by_domain<manhattan_domain, coordinate_type> {
typedef typename coordinate_traits<coordinate_type>::manhattan_area_type type; };
struct y_c_edist : gtl_yes {};
template <typename coordinate_type_1, typename coordinate_type_2>
typename enable_if<
typename gtl_and_3<y_c_edist, typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type, coordinate_concept>::type,
typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type, coordinate_concept>::type>::type,
typename coordinate_traits<coordinate_type_1>::coordinate_difference>::type
euclidean_distance(const coordinate_type_1& lvalue, const coordinate_type_2& rvalue) {
typedef typename coordinate_traits<coordinate_type_1>::coordinate_difference Unit;
return (lvalue < rvalue) ? (Unit)rvalue - (Unit)lvalue : (Unit)lvalue - (Unit)rvalue;
}
// predicated_swap swaps a and b if pred is true
// predicated_swap is guarenteed to behave the same as
// if(pred){
// T tmp = a;
// a = b;
// b = tmp;
// }
// but will not generate a branch instruction.
// predicated_swap always creates a temp copy of a, but does not
// create more than one temp copy of an input.
// predicated_swap can be used to optimize away branch instructions in C++
template <class T>
inline bool predicated_swap(const bool& pred,
T& a,
T& b) {
const T tmp = a;
const T* input[2] = {&b, &tmp};
a = *input[!pred];
b = *input[pred];
return pred;
}
enum direction_1d_enum { LOW = 0, HIGH = 1,
LEFT = 0, RIGHT = 1,
CLOCKWISE = 0, COUNTERCLOCKWISE = 1,
REVERSE = 0, FORWARD = 1,
NEGATIVE = 0, POSITIVE = 1 };
enum orientation_2d_enum { HORIZONTAL = 0, VERTICAL = 1 };
enum direction_2d_enum { WEST = 0, EAST = 1, SOUTH = 2, NORTH = 3 };
enum orientation_3d_enum { PROXIMAL = 2 };
enum direction_3d_enum { DOWN = 4, UP = 5 };
enum winding_direction {
clockwise_winding = 0,
counterclockwise_winding = 1,
unknown_winding = 2
};
class direction_2d;
class direction_3d;
class orientation_2d;
class direction_1d {
private:
unsigned int val_;
explicit direction_1d(int d);
public:
inline direction_1d() : val_(LOW) {}
inline direction_1d(const direction_1d& that) : val_(that.val_) {}
inline direction_1d(const direction_1d_enum val) : val_(val) {}
explicit inline direction_1d(const direction_2d& that);
explicit inline direction_1d(const direction_3d& that);
inline direction_1d& operator = (const direction_1d& d) {
val_ = d.val_; return * this; }
inline bool operator==(direction_1d d) const { return (val_ == d.val_); }
inline bool operator!=(direction_1d d) const { return !((*this) == d); }
inline unsigned int to_int(void) const { return val_; }
inline direction_1d& backward() { val_ ^= 1; return *this; }
inline int get_sign() const { return val_ * 2 - 1; }
};
class direction_2d;
class orientation_2d {
private:
unsigned int val_;
explicit inline orientation_2d(int o);
public:
inline orientation_2d() : val_(HORIZONTAL) {}
inline orientation_2d(const orientation_2d& ori) : val_(ori.val_) {}
inline orientation_2d(const orientation_2d_enum val) : val_(val) {}
explicit inline orientation_2d(const direction_2d& that);
inline orientation_2d& operator=(const orientation_2d& ori) {
val_ = ori.val_; return * this; }
inline bool operator==(orientation_2d that) const { return (val_ == that.val_); }
inline bool operator!=(orientation_2d that) const { return (val_ != that.val_); }
inline unsigned int to_int() const { return (val_); }
inline void turn_90() { val_ = val_^ 1; }
inline orientation_2d get_perpendicular() const {
orientation_2d retval = *this;
retval.turn_90();
return retval;
}
inline direction_2d get_direction(direction_1d dir) const;
};
class direction_2d {
private:
int val_;
public:
inline direction_2d() : val_(WEST) {}
inline direction_2d(const direction_2d& that) : val_(that.val_) {}
inline direction_2d(const direction_2d_enum val) : val_(val) {}
inline direction_2d& operator=(const direction_2d& d) {
val_ = d.val_;
return * this;
}
inline ~direction_2d() { }
inline bool operator==(direction_2d d) const { return (val_ == d.val_); }
inline bool operator!=(direction_2d d) const { return !((*this) == d); }
inline bool operator< (direction_2d d) const { return (val_ < d.val_); }
inline bool operator<=(direction_2d d) const { return (val_ <= d.val_); }
inline bool operator> (direction_2d d) const { return (val_ > d.val_); }
inline bool operator>=(direction_2d d) const { return (val_ >= d.val_); }
// Casting to int
inline unsigned int to_int(void) const { return val_; }
inline direction_2d backward() const {
// flip the LSB, toggles 0 - 1 and 2 - 3
return direction_2d(direction_2d_enum(val_ ^ 1));
}
// Returns a direction 90 degree left (LOW) or right(HIGH) to this one
inline direction_2d turn(direction_1d t) const {
return direction_2d(direction_2d_enum(val_ ^ 3 ^ (val_ >> 1) ^ t.to_int()));
}
// Returns a direction 90 degree left to this one
inline direction_2d left() const {return turn(HIGH);}
// Returns a direction 90 degree right to this one
inline direction_2d right() const {return turn(LOW);}
// N, E are positive, S, W are negative
inline bool is_positive() const {return (val_ & 1);}
inline bool is_negative() const {return !is_positive();}
inline int get_sign() const {return ((is_positive()) << 1) -1;}
};
direction_1d::direction_1d(const direction_2d& that) : val_(that.to_int() & 1) {}
orientation_2d::orientation_2d(const direction_2d& that) : val_(that.to_int() >> 1) {}
direction_2d orientation_2d::get_direction(direction_1d dir) const {
return direction_2d(direction_2d_enum((val_ << 1) + dir.to_int()));
}
class orientation_3d {
private:
unsigned int val_;
explicit inline orientation_3d(int o);
public:
inline orientation_3d() : val_((int)HORIZONTAL) {}
inline orientation_3d(const orientation_3d& ori) : val_(ori.val_) {}
inline orientation_3d(orientation_2d ori) : val_(ori.to_int()) {}
inline orientation_3d(const orientation_3d_enum val) : val_(val) {}
explicit inline orientation_3d(const direction_2d& that);
explicit inline orientation_3d(const direction_3d& that);
inline ~orientation_3d() { }
inline orientation_3d& operator=(const orientation_3d& ori) {
val_ = ori.val_; return * this; }
inline bool operator==(orientation_3d that) const { return (val_ == that.val_); }
inline bool operator!=(orientation_3d that) const { return (val_ != that.val_); }
inline unsigned int to_int() const { return (val_); }
inline direction_3d get_direction(direction_1d dir) const;
};
class direction_3d {
private:
int val_;
public:
inline direction_3d() : val_(WEST) {}
inline direction_3d(direction_2d that) : val_(that.to_int()) {}
inline direction_3d(const direction_3d& that) : val_(that.val_) {}
inline direction_3d(const direction_2d_enum val) : val_(val) {}
inline direction_3d(const direction_3d_enum val) : val_(val) {}
inline direction_3d& operator=(direction_3d d) {
val_ = d.val_;
return * this;
}
inline ~direction_3d() { }
inline bool operator==(direction_3d d) const { return (val_ == d.val_); }
inline bool operator!=(direction_3d d) const { return !((*this) == d); }
inline bool operator< (direction_3d d) const { return (val_ < d.val_); }
inline bool operator<=(direction_3d d) const { return (val_ <= d.val_); }
inline bool operator> (direction_3d d) const { return (val_ > d.val_); }
inline bool operator>=(direction_3d d) const { return (val_ >= d.val_); }
// Casting to int
inline unsigned int to_int(void) const { return val_; }
inline direction_3d backward() const {
// flip the LSB, toggles 0 - 1 and 2 - 3 and 4 - 5
return direction_2d(direction_2d_enum(val_ ^ 1));
}
// N, E, U are positive, S, W, D are negative
inline bool is_positive() const {return (val_ & 1);}
inline bool is_negative() const {return !is_positive();}
inline int get_sign() const {return ((is_positive()) << 1) -1;}
};
direction_1d::direction_1d(const direction_3d& that) : val_(that.to_int() & 1) {}
orientation_3d::orientation_3d(const direction_3d& that) : val_(that.to_int() >> 1) {}
orientation_3d::orientation_3d(const direction_2d& that) : val_(that.to_int() >> 1) {}
direction_3d orientation_3d::get_direction(direction_1d dir) const {
return direction_3d(direction_3d_enum((val_ << 1) + dir.to_int()));
}
}
}
#endif

View file

@ -0,0 +1,469 @@
// Boost.Polygon library point_concept.hpp header file
// Copyright (c) Intel Corporation 2008.
// Copyright (c) 2008-2012 Simonson Lucanus.
// Copyright (c) 2012-2012 Andrii Sydorchuk.
// See http://www.boost.org for updates, documentation, and revision history.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_POLYGON_POINT_CONCEPT_HPP
#define BOOST_POLYGON_POINT_CONCEPT_HPP
#include "isotropy.hpp"
#include "point_traits.hpp"
namespace boost {
namespace polygon {
struct point_concept {};
template <typename ConceptType>
struct is_point_concept {
typedef gtl_no type;
};
template <>
struct is_point_concept<point_concept> {
typedef gtl_yes type;
};
template <typename ConceptType>
struct is_mutable_point_concept {
typedef gtl_no type;
};
template <>
struct is_mutable_point_concept<point_concept> {
typedef gtl_yes type;
};
template <typename GeometryType, typename BoolType>
struct point_coordinate_type_by_concept {
typedef void type;
};
template <typename GeometryType>
struct point_coordinate_type_by_concept<GeometryType, gtl_yes> {
typedef typename point_traits<GeometryType>::coordinate_type type;
};
template <typename GeometryType>
struct point_coordinate_type {
typedef typename point_coordinate_type_by_concept<
GeometryType,
typename is_point_concept<
typename geometry_concept<GeometryType>::type
>::type
>::type type;
};
template <typename GeometryType, typename BoolType>
struct point_difference_type_by_concept {
typedef void type;
};
template <typename GeometryType>
struct point_difference_type_by_concept<GeometryType, gtl_yes> {
typedef typename coordinate_traits<
typename point_traits<GeometryType>::coordinate_type
>::coordinate_difference type;
};
template <typename GeometryType>
struct point_difference_type {
typedef typename point_difference_type_by_concept<
GeometryType,
typename is_point_concept<
typename geometry_concept<GeometryType>::type
>::type
>::type type;
};
template <typename GeometryType, typename BoolType>
struct point_distance_type_by_concept {
typedef void type;
};
template <typename GeometryType>
struct point_distance_type_by_concept<GeometryType, gtl_yes> {
typedef typename coordinate_traits<
typename point_coordinate_type<GeometryType>::type
>::coordinate_distance type;
};
template <typename GeometryType>
struct point_distance_type {
typedef typename point_distance_type_by_concept<
GeometryType,
typename is_point_concept<
typename geometry_concept<GeometryType>::type
>::type
>::type type;
};
struct y_pt_get : gtl_yes {};
template <typename PointType>
typename enable_if<
typename gtl_and<
y_pt_get,
typename is_point_concept<
typename geometry_concept<PointType>::type
>::type
>::type,
typename point_coordinate_type<PointType>::type
>::type get(const PointType& point, orientation_2d orient) {
return point_traits<PointType>::get(point, orient);
}
struct y_pt_set : gtl_yes {};
template <typename PointType>
typename enable_if<
typename gtl_and<
y_pt_set,
typename is_mutable_point_concept<
typename geometry_concept<PointType>::type
>::type
>::type,
void
>::type set(PointType& point, orientation_2d orient,
typename point_mutable_traits<PointType>::coordinate_type value) {
point_mutable_traits<PointType>::set(point, orient, value);
}
struct y_pt_construct : gtl_yes {};
template <typename PointType>
typename enable_if<
typename gtl_and<
y_pt_construct,
typename is_mutable_point_concept<
typename geometry_concept<PointType>::type
>::type
>::type,
PointType>::type construct(
typename point_mutable_traits<PointType>::coordinate_type x,
typename point_mutable_traits<PointType>::coordinate_type y) {
return point_mutable_traits<PointType>::construct(x, y);
}
struct y_pt_assign : gtl_yes {};
template <typename PointType1, typename PointType2>
typename enable_if<
typename gtl_and_3<
y_pt_assign,
typename is_mutable_point_concept<
typename geometry_concept<PointType1>::type
>::type,
typename is_point_concept<
typename geometry_concept<PointType2>::type
>::type
>::type,
PointType1>::type& assign(PointType1& lvalue, const PointType2& rvalue) {
set(lvalue, HORIZONTAL, get(rvalue, HORIZONTAL));
set(lvalue, VERTICAL, get(rvalue, VERTICAL));
return lvalue;
}
struct y_p_x : gtl_yes {};
template <typename PointType>
typename enable_if<
typename gtl_and<
y_p_x,
typename is_point_concept<
typename geometry_concept<PointType>::type
>::type
>::type,
typename point_coordinate_type<PointType>::type
>::type x(const PointType& point) {
return get(point, HORIZONTAL);
}
struct y_p_y : gtl_yes {};
template <typename PointType>
typename enable_if<
typename gtl_and<
y_p_y,
typename is_point_concept<
typename geometry_concept<PointType>::type
>::type
>::type,
typename point_coordinate_type<PointType>::type
>::type y(const PointType& point) {
return get(point, VERTICAL);
}
struct y_p_sx : gtl_yes {};
template <typename PointType>
typename enable_if<
typename gtl_and<
y_p_sx,
typename is_mutable_point_concept<
typename geometry_concept<PointType>::type
>::type
>::type,
void>::type x(PointType& point,
typename point_mutable_traits<PointType>::coordinate_type value) {
set(point, HORIZONTAL, value);
}
struct y_p_sy : gtl_yes {};
template <typename PointType>
typename enable_if<
typename gtl_and<
y_p_sy,
typename is_mutable_point_concept<
typename geometry_concept<PointType>::type
>::type
>::type,
void>::type y(PointType& point,
typename point_mutable_traits<PointType>::coordinate_type value) {
set(point, VERTICAL, value);
}
struct y_pt_equiv : gtl_yes {};
template <typename PointType1, typename PointType2>
typename enable_if<
typename gtl_and_3<
y_pt_equiv,
typename is_point_concept<
typename geometry_concept<PointType1>::type
>::type,
typename is_point_concept<
typename geometry_concept<PointType2>::type
>::type
>::type,
bool>::type equivalence(
const PointType1& point1, const PointType2& point2) {
return (x(point1) == x(point2)) && (y(point1) == y(point2));
}
struct y_pt_man_dist : gtl_yes {};
template <typename PointType1, typename PointType2>
typename enable_if<
typename gtl_and_3<
y_pt_man_dist,
typename is_point_concept<
typename geometry_concept<PointType1>::type
>::type,
typename is_point_concept<
typename geometry_concept<PointType2>::type
>::type
>::type,
typename point_difference_type<PointType1>::type>::type
manhattan_distance(const PointType1& point1, const PointType2& point2) {
return euclidean_distance(point1, point2, HORIZONTAL) +
euclidean_distance(point1, point2, VERTICAL);
}
struct y_pt_ed1 : gtl_yes {};
template <typename PointType1, typename PointType2>
typename enable_if<
typename gtl_and_3<
y_pt_ed1,
typename is_point_concept<
typename geometry_concept<PointType1>::type
>::type,
typename is_point_concept<
typename geometry_concept<PointType2>::type
>::type
>::type,
typename point_difference_type<PointType1>::type>::type
euclidean_distance(
const PointType1& point1,
const PointType2& point2,
orientation_2d orient) {
typename point_difference_type<PointType1>::type dif =
get(point1, orient) - get(point2, orient);
return (dif < 0) ? -dif : dif;
}
struct y_pt_eds : gtl_yes {};
template <typename PointType1, typename PointType2>
typename enable_if<
typename gtl_and_3<
y_pt_eds,
typename is_point_concept<
typename geometry_concept<PointType1>::type
>::type,
typename is_point_concept<
typename geometry_concept<PointType2>::type
>::type
>::type,
typename point_difference_type<PointType1>::type>::type
distance_squared(const PointType1& point1, const PointType2& point2) {
typename point_difference_type<PointType1>::type dx =
euclidean_distance(point1, point2, HORIZONTAL);
typename point_difference_type<PointType1>::type dy =
euclidean_distance(point1, point2, VERTICAL);
dx *= dx;
dy *= dy;
return dx + dy;
}
struct y_pt_ed2 : gtl_yes {};
template <typename PointType1, typename PointType2>
typename enable_if<
typename gtl_and_3<
y_pt_ed2,
typename is_point_concept<
typename geometry_concept<PointType1>::type
>::type,
typename is_point_concept<
typename geometry_concept<PointType2>::type
>::type
>::type,
typename point_distance_type<PointType1>::type>::type
euclidean_distance(const PointType1& point1, const PointType2& point2) {
return (std::sqrt)(
static_cast<double>(distance_squared(point1, point2)));
}
struct y_pt_convolve : gtl_yes {};
template <typename PointType1, typename PointType2>
typename enable_if<
typename gtl_and_3<
y_pt_convolve,
typename is_mutable_point_concept<
typename geometry_concept<PointType1>::type
>::type,
typename is_point_concept<
typename geometry_concept<PointType2>::type
>::type
>::type,
PointType1>::type& convolve(PointType1& lvalue, const PointType2& rvalue) {
x(lvalue, x(lvalue) + x(rvalue));
y(lvalue, y(lvalue) + y(rvalue));
return lvalue;
}
struct y_pt_deconvolve : gtl_yes {};
template <typename PointType1, typename PointType2>
typename enable_if<
typename gtl_and_3<
y_pt_deconvolve,
typename is_mutable_point_concept<
typename geometry_concept<PointType1>::type
>::type,
typename is_point_concept<
typename geometry_concept<PointType2>::type
>::type
>::type,
PointType1>::type& deconvolve(PointType1& lvalue, const PointType2& rvalue) {
x(lvalue, x(lvalue) - x(rvalue));
y(lvalue, y(lvalue) - y(rvalue));
return lvalue;
}
struct y_pt_scale_up : gtl_yes {};
template <typename PointType, typename CType>
typename enable_if<
typename gtl_and<
y_pt_scale_up,
typename is_mutable_point_concept<
typename geometry_concept<PointType>::type
>::type
>::type,
PointType>::type& scale_up(PointType& point, CType factor) {
typedef typename point_coordinate_type<PointType>::type Unit;
x(point, x(point) * (Unit)factor);
y(point, y(point) * (Unit)factor);
return point;
}
struct y_pt_scale_down : gtl_yes {};
template <typename PointType, typename CType>
typename enable_if<
typename gtl_and<
y_pt_scale_down,
typename is_mutable_point_concept<
typename geometry_concept<PointType>::type
>::type
>::type,
PointType>::type& scale_down(PointType& point, CType factor) {
typedef typename point_coordinate_type<PointType>::type Unit;
typedef typename coordinate_traits<Unit>::coordinate_distance dt;
x(point, scaling_policy<Unit>::round((dt)(x(point)) / (dt)factor));
y(point, scaling_policy<Unit>::round((dt)(y(point)) / (dt)factor));
return point;
}
struct y_pt_scale : gtl_yes {};
template <typename PointType, typename ScaleType>
typename enable_if<
typename gtl_and<
y_pt_scale,
typename is_mutable_point_concept<
typename geometry_concept<PointType>::type
>::type
>::type,
PointType>::type& scale(PointType& point, const ScaleType& scaling) {
typedef typename point_coordinate_type<PointType>::type Unit;
Unit x_coord(x(point));
Unit y_coord(y(point));
scaling.scale(x_coord, y_coord);
x(point, x_coord);
y(point, y_coord);
return point;
}
struct y_pt_transform : gtl_yes {};
template <typename PointType, typename TransformType>
typename enable_if<
typename gtl_and<
y_pt_transform,
typename is_mutable_point_concept<
typename geometry_concept<PointType>::type
>::type
>::type,
PointType>::type& transform(PointType& point, const TransformType& transform) {
typedef typename point_coordinate_type<PointType>::type Unit;
Unit x_coord(x(point));
Unit y_coord(y(point));
transform.transform(x_coord, y_coord);
x(point, x_coord);
y(point, y_coord);
return point;
}
struct y_pt_move : gtl_yes {};
template <typename PointType>
typename enable_if<
typename gtl_and<
y_pt_move,
typename is_mutable_point_concept<
typename geometry_concept<PointType>::type
>::type
>::type,
PointType>::type& move(PointType& point, orientation_2d orient,
typename point_coordinate_type<PointType>::type displacement) {
typedef typename point_coordinate_type<PointType>::type Unit;
Unit coord = get(point, orient);
set(point, orient, coord + displacement);
return point;
}
} // polygon
} // boost
#endif // BOOST_POLYGON_POINT_CONCEPT_HPP

View file

@ -0,0 +1,130 @@
// Boost.Polygon library point_data.hpp header file
// Copyright (c) Intel Corporation 2008.
// Copyright (c) 2008-2012 Simonson Lucanus.
// Copyright (c) 2012-2012 Andrii Sydorchuk.
// See http://www.boost.org for updates, documentation, and revision history.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_POLYGON_POINT_DATA_HPP
#define BOOST_POLYGON_POINT_DATA_HPP
#include "isotropy.hpp"
#include "point_concept.hpp"
namespace boost {
namespace polygon {
template <typename T>
class point_data {
public:
typedef T coordinate_type;
point_data()
#ifndef BOOST_POLYGON_MSVC
: coords_()
#endif
{}
point_data(coordinate_type x, coordinate_type y) {
coords_[HORIZONTAL] = x;
coords_[VERTICAL] = y;
}
explicit point_data(const point_data& that) {
coords_[0] = that.coords_[0];
coords_[1] = that.coords_[1];
}
point_data& operator=(const point_data& that) {
coords_[0] = that.coords_[0];
coords_[1] = that.coords_[1];
return *this;
}
template <typename PointType>
explicit point_data(const PointType& that) {
*this = that;
}
template <typename PointType>
point_data& operator=(const PointType& that) {
assign(*this, that);
return *this;
}
// TODO(asydorchuk): Deprecated.
template <typename CT>
point_data(const point_data<CT>& that) {
coords_[HORIZONTAL] = (coordinate_type)that.x();
coords_[VERTICAL] = (coordinate_type)that.y();
}
coordinate_type get(orientation_2d orient) const {
return coords_[orient.to_int()];
}
void set(orientation_2d orient, coordinate_type value) {
coords_[orient.to_int()] = value;
}
coordinate_type x() const {
return coords_[HORIZONTAL];
}
point_data& x(coordinate_type value) {
coords_[HORIZONTAL] = value;
return *this;
}
coordinate_type y() const {
return coords_[VERTICAL];
}
point_data& y(coordinate_type value) {
coords_[VERTICAL] = value;
return *this;
}
bool operator==(const point_data& that) const {
return (coords_[0] == that.coords_[0]) &&
(coords_[1] == that.coords_[1]);
}
bool operator!=(const point_data& that) const {
return !(*this == that);
}
bool operator<(const point_data& that) const {
return (coords_[0] < that.coords_[0]) ||
((coords_[0] == that.coords_[0]) &&
(coords_[1] < that.coords_[1]));
}
bool operator<=(const point_data& that) const {
return !(that < *this);
}
bool operator>(const point_data& that) const {
return that < *this;
}
bool operator>=(const point_data& that) const {
return !(*this < that);
}
private:
coordinate_type coords_[2];
};
template <typename CType>
struct geometry_concept< point_data<CType> > {
typedef point_concept type;
};
} // polygon
} // boost
#endif // BOOST_POLYGON_POINT_DATA_HPP

View file

@ -0,0 +1,48 @@
// Boost.Polygon library point_traits.hpp header file
// Copyright (c) Intel Corporation 2008.
// Copyright (c) 2008-2012 Simonson Lucanus.
// Copyright (c) 2012-2012 Andrii Sydorchuk.
// See http://www.boost.org for updates, documentation, and revision history.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_POLYGON_POINT_TRAITS_HPP
#define BOOST_POLYGON_POINT_TRAITS_HPP
#include "isotropy.hpp"
namespace boost {
namespace polygon {
template <typename PointType>
struct point_traits {
typedef PointType point_type;
typedef typename point_type::coordinate_type coordinate_type;
static coordinate_type get(
const point_type& point, orientation_2d orient) {
return point.get(orient);
}
};
template <typename PointType>
struct point_mutable_traits {
typedef PointType point_type;
typedef typename point_type::coordinate_type coordinate_type;
static void set(
point_type& point, orientation_2d orient, coordinate_type value) {
point.set(orient, value);
}
static point_type construct(coordinate_type x, coordinate_type y) {
return point_type(x, y);
}
};
} // polygon
} // boost
#endif // BOOST_POLYGON_POINT_TRAITS_HPP

View file

@ -0,0 +1,92 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_HPP
#define BOOST_POLYGON_POLYGON_HPP
#define BOOST_POLYGON_VERSION 014401
#include "isotropy.hpp"
//point
#include "point_data.hpp"
#include "point_traits.hpp"
#include "point_concept.hpp"
#include "transform.hpp"
//interval
#include "interval_data.hpp"
#include "interval_traits.hpp"
#include "interval_concept.hpp"
//rectangle
#include "rectangle_data.hpp"
#include "rectangle_traits.hpp"
#include "rectangle_concept.hpp"
//segment
#include "segment_data.hpp"
#include "segment_traits.hpp"
#include "segment_concept.hpp"
//algorithms needed by polygon types
#include "detail/iterator_points_to_compact.hpp"
#include "detail/iterator_compact_to_points.hpp"
//polygons
#include "polygon_45_data.hpp"
#include "polygon_data.hpp"
#include "polygon_90_data.hpp"
#include "polygon_90_with_holes_data.hpp"
#include "polygon_45_with_holes_data.hpp"
#include "polygon_with_holes_data.hpp"
#include "polygon_traits.hpp"
//manhattan boolean algorithms
#include "detail/boolean_op.hpp"
#include "detail/polygon_formation.hpp"
#include "detail/rectangle_formation.hpp"
#include "detail/max_cover.hpp"
#include "detail/property_merge.hpp"
#include "detail/polygon_90_touch.hpp"
#include "detail/iterator_geometry_to_set.hpp"
//45 boolean op algorithms
#include "detail/boolean_op_45.hpp"
#include "detail/polygon_45_formation.hpp"
//polygon set data types
#include "polygon_90_set_data.hpp"
//polygon set trait types
#include "polygon_90_set_traits.hpp"
//polygon set concepts
#include "polygon_90_set_concept.hpp"
//boolean operator syntax
#include "detail/polygon_90_set_view.hpp"
//45 boolean op algorithms
#include "detail/polygon_45_touch.hpp"
#include "detail/property_merge_45.hpp"
#include "polygon_45_set_data.hpp"
#include "polygon_45_set_traits.hpp"
#include "polygon_45_set_concept.hpp"
#include "detail/polygon_45_set_view.hpp"
//arbitrary polygon algorithms
#include "detail/polygon_arbitrary_formation.hpp"
#include "polygon_set_data.hpp"
//general scanline
#include "detail/scan_arbitrary.hpp"
#include "polygon_set_traits.hpp"
#include "detail/polygon_set_view.hpp"
#include "polygon_set_concept.hpp"
#include "segment_utils.hpp"
#endif

View file

@ -0,0 +1,72 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_45_DATA_HPP
#define BOOST_POLYGON_POLYGON_45_DATA_HPP
#include "isotropy.hpp"
namespace boost { namespace polygon{
struct polygon_45_concept;
template <typename T> class polygon_data;
template <typename T>
class polygon_45_data {
public:
typedef polygon_45_concept geometry_type;
typedef T coordinate_type;
typedef typename std::vector<point_data<coordinate_type> >::const_iterator iterator_type;
typedef typename coordinate_traits<T>::coordinate_distance area_type;
typedef point_data<T> point_type;
inline polygon_45_data() : coords_() {} //do nothing default constructor
template<class iT>
inline polygon_45_data(iT input_begin, iT input_end) : coords_(input_begin, input_end) {}
template<class iT>
inline polygon_45_data& set(iT input_begin, iT input_end) {
coords_.clear(); //just in case there was some old data there
coords_.insert(coords_.end(), input_begin, input_end);
return *this;
}
// copy constructor (since we have dynamic memory)
inline polygon_45_data(const polygon_45_data& that) : coords_(that.coords_) {}
// assignment operator (since we have dynamic memory do a deep copy)
inline polygon_45_data& operator=(const polygon_45_data& that) {
coords_ = that.coords_;
return *this;
}
template <typename T2>
inline polygon_45_data& operator=(const T2& rvalue);
inline bool operator==(const polygon_45_data& that) const {
if(coords_.size() != that.coords_.size()) return false;
for(std::size_t i = 0; i < coords_.size(); ++i) {
if(coords_[i] != that.coords_[i]) return false;
}
return true;
}
inline bool operator!=(const polygon_45_data& that) const { return !((*this) == that); }
// get begin iterator, returns a pointer to a const Unit
inline iterator_type begin() const { return coords_.begin(); }
// get end iterator, returns a pointer to a const Unit
inline iterator_type end() const { return coords_.end(); }
inline std::size_t size() const { return coords_.size(); }
public:
std::vector<point_data<coordinate_type> > coords_;
};
}
}
#endif

View file

@ -0,0 +1,441 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_45_SET_CONCEPT_HPP
#define BOOST_POLYGON_POLYGON_45_SET_CONCEPT_HPP
#include "polygon_45_set_data.hpp"
#include "polygon_45_set_traits.hpp"
#include "detail/polygon_45_touch.hpp"
namespace boost { namespace polygon{
template <typename T, typename T2>
struct is_either_polygon_45_set_type {
typedef typename gtl_or<typename is_polygon_45_set_type<T>::type, typename is_polygon_45_set_type<T2>::type >::type type;
};
template <typename T>
struct is_polygon_45_or_90_set_type {
typedef typename gtl_or<typename is_polygon_45_set_type<T>::type, typename is_polygon_90_set_type<T>::type >::type type;
};
template <typename polygon_set_type>
typename enable_if< typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type>::type>::type,
typename polygon_45_set_traits<polygon_set_type>::iterator_type>::type
begin_45_set_data(const polygon_set_type& polygon_set) {
return polygon_45_set_traits<polygon_set_type>::begin(polygon_set);
}
template <typename polygon_set_type>
typename enable_if< typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type>::type>::type,
typename polygon_45_set_traits<polygon_set_type>::iterator_type>::type
end_45_set_data(const polygon_set_type& polygon_set) {
return polygon_45_set_traits<polygon_set_type>::end(polygon_set);
}
template <typename polygon_set_type>
typename enable_if< typename gtl_if<typename is_polygon_45_set_type<polygon_set_type>::type>::type,
bool>::type
clean(const polygon_set_type& polygon_set) {
return polygon_45_set_traits<polygon_set_type>::clean(polygon_set);
}
//assign
template <typename polygon_set_type_1, typename polygon_set_type_2>
typename enable_if< typename gtl_and< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type_1>::type>::type,
typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type_2>::type>::type>::type,
polygon_set_type_1>::type &
assign(polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) {
polygon_45_set_mutable_traits<polygon_set_type_1>::set(lvalue, begin_45_set_data(rvalue), end_45_set_data(rvalue));
return lvalue;
}
//get trapezoids
template <typename output_container_type, typename polygon_set_type>
typename enable_if< typename gtl_if<typename is_polygon_45_set_type<polygon_set_type>::type>::type,
void>::type
get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set) {
clean(polygon_set);
polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps;
assign(ps, polygon_set);
ps.get_trapezoids(output);
}
//get trapezoids
template <typename output_container_type, typename polygon_set_type>
typename enable_if< typename gtl_if<typename is_polygon_45_set_type<polygon_set_type>::type>::type,
void>::type
get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set, orientation_2d slicing_orientation) {
clean(polygon_set);
polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps;
assign(ps, polygon_set);
ps.get_trapezoids(output, slicing_orientation);
}
//equivalence
template <typename polygon_set_type_1, typename polygon_set_type_2>
typename enable_if< typename gtl_and_3<typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type_1>::type>::type,
typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type_2>::type>::type,
typename gtl_if<typename is_either_polygon_45_set_type<polygon_set_type_1,
polygon_set_type_2>::type>::type>::type,
bool>::type
equivalence(const polygon_set_type_1& lvalue,
const polygon_set_type_2& rvalue) {
polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type_1>::coordinate_type> ps1;
assign(ps1, lvalue);
polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type_2>::coordinate_type> ps2;
assign(ps2, rvalue);
return ps1 == ps2;
}
//clear
template <typename polygon_set_type>
typename enable_if< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type>::type>::type,
void>::type
clear(polygon_set_type& polygon_set) {
polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps;
assign(polygon_set, ps);
}
//empty
template <typename polygon_set_type>
typename enable_if< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type>::type>::type,
bool>::type
empty(const polygon_set_type& polygon_set) {
if(clean(polygon_set)) return begin_45_set_data(polygon_set) == end_45_set_data(polygon_set);
polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps;
assign(ps, polygon_set);
ps.clean();
return ps.empty();
}
//extents
template <typename polygon_set_type, typename rectangle_type>
typename enable_if<
typename gtl_and< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type>::type>::type,
typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
bool>::type
extents(rectangle_type& extents_rectangle,
const polygon_set_type& polygon_set) {
clean(polygon_set);
polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps;
assign(ps, polygon_set);
return ps.extents(extents_rectangle);
}
//area
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type,
typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::area_type>::type
area(const polygon_set_type& polygon_set) {
typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit;
typedef polygon_45_with_holes_data<Unit> p_type;
typedef typename coordinate_traits<Unit>::area_type area_type;
std::vector<p_type> polys;
assign(polys, polygon_set);
area_type retval = (area_type)0;
for(std::size_t i = 0; i < polys.size(); ++i) {
retval += area(polys[i]);
}
return retval;
}
//interact
template <typename polygon_set_type_1, typename polygon_set_type_2>
typename enable_if <
typename gtl_and< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type_1>::type>::type,
typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type_2>::type>::type >::type,
polygon_set_type_1>::type&
interact(polygon_set_type_1& polygon_set_1, const polygon_set_type_2& polygon_set_2) {
typedef typename polygon_45_set_traits<polygon_set_type_1>::coordinate_type Unit;
std::vector<polygon_45_data<Unit> > polys;
assign(polys, polygon_set_1);
std::vector<std::set<int> > graph(polys.size()+1, std::set<int>());
connectivity_extraction_45<Unit> ce;
ce.insert(polygon_set_2);
for(std::size_t i = 0; i < polys.size(); ++i){
ce.insert(polys[i]);
}
ce.extract(graph);
clear(polygon_set_1);
polygon_45_set_data<Unit> ps;
for(std::set<int>::iterator itr = graph[0].begin(); itr != graph[0].end(); ++itr){
ps.insert(polys[(*itr)-1]);
}
assign(polygon_set_1, ps);
return polygon_set_1;
}
// //self_intersect
// template <typename polygon_set_type>
// typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type>::type,
// polygon_set_type>::type &
// self_intersect(polygon_set_type& polygon_set) {
// typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit;
// //TODO
// }
template <typename polygon_set_type, typename coord_type>
typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type,
polygon_set_type>::type &
resize(polygon_set_type& polygon_set, coord_type resizing,
RoundingOption rounding = CLOSEST, CornerOption corner = INTERSECTION) {
typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit;
clean(polygon_set);
polygon_45_set_data<Unit> ps;
assign(ps, polygon_set);
ps.resize(resizing, rounding, corner);
assign(polygon_set, ps);
return polygon_set;
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type,
polygon_set_type>::type &
bloat(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
return resize(polygon_set, static_cast<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>(bloating));
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type,
polygon_set_type>::type &
shrink(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) {
return resize(polygon_set, -(typename polygon_45_set_traits<polygon_set_type>::coordinate_type)shrinking);
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type,
polygon_set_type>::type &
grow_and(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit;
std::vector<polygon_45_data<Unit> > polys;
assign(polys, polygon_set);
clear(polygon_set);
polygon_45_set_data<Unit> ps;
for(std::size_t i = 0; i < polys.size(); ++i) {
polygon_45_set_data<Unit> tmpPs;
tmpPs.insert(polys[i]);
bloat(tmpPs, bloating);
tmpPs.clean(); //apply implicit OR on tmp polygon set
ps.insert(tmpPs);
}
ps.self_intersect();
assign(polygon_set, ps);
return polygon_set;
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type,
polygon_set_type>::type &
scale_up(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type factor) {
typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit;
clean(polygon_set);
polygon_45_set_data<Unit> ps;
assign(ps, polygon_set);
ps.scale_up(factor);
assign(polygon_set, ps);
return polygon_set;
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type,
polygon_set_type>::type &
scale_down(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type factor) {
typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit;
clean(polygon_set);
polygon_45_set_data<Unit> ps;
assign(ps, polygon_set);
ps.scale_down(factor);
assign(polygon_set, ps);
return polygon_set;
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type,
polygon_set_type>::type &
scale(polygon_set_type& polygon_set, double factor) {
typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit;
clean(polygon_set);
polygon_45_set_data<Unit> ps;
assign(ps, polygon_set);
ps.scale(factor);
assign(polygon_set, ps);
return polygon_set;
}
//self_intersect
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type,
polygon_set_type>::type &
self_intersect(polygon_set_type& polygon_set) {
typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit;
polygon_45_set_data<Unit> ps;
assign(ps, polygon_set);
ps.self_intersect();
assign(polygon_set, ps);
return polygon_set;
}
//self_xor
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type,
polygon_set_type>::type &
self_xor(polygon_set_type& polygon_set) {
typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit;
polygon_45_set_data<Unit> ps;
assign(ps, polygon_set);
ps.self_xor();
assign(polygon_set, ps);
return polygon_set;
}
//transform
template <typename polygon_set_type, typename transformation_type>
typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type,
polygon_set_type>::type &
transform(polygon_set_type& polygon_set,
const transformation_type& transformation) {
typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit;
clean(polygon_set);
polygon_45_set_data<Unit> ps;
assign(ps, polygon_set);
ps.transform(transformation);
assign(polygon_set, ps);
return polygon_set;
}
//keep
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type,
polygon_set_type>::type &
keep(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::area_type min_area,
typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::area_type max_area,
typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_width,
typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_width,
typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_height,
typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_height) {
typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit;
typedef typename coordinate_traits<Unit>::unsigned_area_type uat;
std::list<polygon_45_data<Unit> > polys;
assign(polys, polygon_set);
typename std::list<polygon_45_data<Unit> >::iterator itr_nxt;
for(typename std::list<polygon_45_data<Unit> >::iterator itr = polys.begin(); itr != polys.end(); itr = itr_nxt){
itr_nxt = itr;
++itr_nxt;
rectangle_data<Unit> bbox;
extents(bbox, *itr);
uat pwidth = delta(bbox, HORIZONTAL);
if(pwidth > min_width && pwidth <= max_width){
uat pheight = delta(bbox, VERTICAL);
if(pheight > min_height && pheight <= max_height){
typename coordinate_traits<Unit>::area_type parea = area(*itr);
if(parea <= max_area && parea >= min_area) {
continue;
}
}
}
polys.erase(itr);
}
assign(polygon_set, polys);
return polygon_set;
}
template <typename T>
struct view_of<polygon_90_set_concept, T> {
typedef typename get_coordinate_type<T, typename geometry_concept<T>::type >::type coordinate_type;
T* tp;
std::vector<polygon_90_with_holes_data<coordinate_type> > polys;
view_of(T& obj) : tp(&obj), polys() {
std::vector<polygon_with_holes_data<coordinate_type> > gpolys;
assign(gpolys, obj);
for(typename std::vector<polygon_with_holes_data<coordinate_type> >::iterator itr = gpolys.begin();
itr != gpolys.end(); ++itr) {
polys.push_back(polygon_90_with_holes_data<coordinate_type>());
assign(polys.back(), view_as<polygon_90_with_holes_concept>(*itr));
}
}
view_of(const T& obj) : tp(), polys() {
std::vector<polygon_with_holes_data<coordinate_type> > gpolys;
assign(gpolys, obj);
for(typename std::vector<polygon_with_holes_data<coordinate_type> >::iterator itr = gpolys.begin();
itr != gpolys.end(); ++itr) {
polys.push_back(polygon_90_with_holes_data<coordinate_type>());
assign(polys.back(), view_as<polygon_90_with_holes_concept>(*itr));
}
}
typedef typename std::vector<polygon_90_with_holes_data<coordinate_type> >::const_iterator iterator_type;
typedef view_of operator_arg_type;
inline iterator_type begin() const {
return polys.begin();
}
inline iterator_type end() const {
return polys.end();
}
inline orientation_2d orient() const { return HORIZONTAL; }
inline bool clean() const { return false; }
inline bool sorted() const { return false; }
inline T& get() { return *tp; }
};
template <typename T>
struct polygon_90_set_traits<view_of<polygon_90_set_concept, T> > {
typedef typename view_of<polygon_90_set_concept, T>::coordinate_type coordinate_type;
typedef typename view_of<polygon_90_set_concept, T>::iterator_type iterator_type;
typedef view_of<polygon_90_set_concept, T> operator_arg_type;
static inline iterator_type begin(const view_of<polygon_90_set_concept, T>& polygon_set) {
return polygon_set.begin();
}
static inline iterator_type end(const view_of<polygon_90_set_concept, T>& polygon_set) {
return polygon_set.end();
}
static inline orientation_2d orient(const view_of<polygon_90_set_concept, T>& polygon_set) {
return polygon_set.orient(); }
static inline bool clean(const view_of<polygon_90_set_concept, T>& polygon_set) {
return polygon_set.clean(); }
static inline bool sorted(const view_of<polygon_90_set_concept, T>& polygon_set) {
return polygon_set.sorted(); }
};
template <typename T>
struct geometry_concept<view_of<polygon_90_set_concept, T> > {
typedef polygon_90_set_concept type;
};
template <typename T>
struct get_coordinate_type<view_of<polygon_90_set_concept, T>, polygon_90_set_concept> {
typedef typename view_of<polygon_90_set_concept, T>::coordinate_type type;
};
template <typename T>
struct get_iterator_type_2<view_of<polygon_90_set_concept, T>, polygon_90_set_concept> {
typedef typename view_of<polygon_90_set_concept, T>::iterator_type type;
static type begin(const view_of<polygon_90_set_concept, T>& t) { return t.begin(); }
static type end(const view_of<polygon_90_set_concept, T>& t) { return t.end(); }
};
}
}
#include "detail/polygon_45_set_view.hpp"
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,149 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_45_SET_TRAITS_HPP
#define BOOST_POLYGON_POLYGON_45_SET_TRAITS_HPP
namespace boost { namespace polygon{
//default definition of polygon 45 set traits works for any model of polygon 45, polygon 45 with holes or any vector or list thereof
template <typename T>
struct polygon_45_set_traits {
typedef typename get_coordinate_type<T, typename geometry_concept<T>::type >::type coordinate_type;
typedef typename get_iterator_type<T>::type iterator_type;
typedef T operator_arg_type;
static inline iterator_type begin(const T& polygon_set) {
return get_iterator_type<T>::begin(polygon_set);
}
static inline iterator_type end(const T& polygon_set) {
return get_iterator_type<T>::end(polygon_set);
}
static inline bool clean(const T& ) { return false; }
static inline bool sorted(const T& ) { return false; }
};
template <typename T>
struct is_45_polygonal_concept { typedef gtl_no type; };
template <>
struct is_45_polygonal_concept<polygon_45_concept> { typedef gtl_yes type; };
template <>
struct is_45_polygonal_concept<polygon_45_with_holes_concept> { typedef gtl_yes type; };
template <>
struct is_45_polygonal_concept<polygon_45_set_concept> { typedef gtl_yes type; };
template <typename T>
struct is_polygon_45_set_type {
typedef typename is_45_polygonal_concept<typename geometry_concept<T>::type>::type type;
};
template <typename T>
struct is_polygon_45_set_type<std::list<T> > {
typedef typename gtl_or<
typename is_45_polygonal_concept<typename geometry_concept<std::list<T> >::type>::type,
typename is_45_polygonal_concept<typename geometry_concept<typename std::list<T>::value_type>::type>::type>::type type;
};
template <typename T>
struct is_polygon_45_set_type<std::vector<T> > {
typedef typename gtl_or<
typename is_45_polygonal_concept<typename geometry_concept<std::vector<T> >::type>::type,
typename is_45_polygonal_concept<typename geometry_concept<typename std::vector<T>::value_type>::type>::type>::type type;
};
template <typename T>
struct is_mutable_polygon_45_set_type {
typedef typename gtl_same_type<polygon_45_set_concept, typename geometry_concept<T>::type>::type type;
};
template <typename T>
struct is_mutable_polygon_45_set_type<std::list<T> > {
typedef typename gtl_or<
typename gtl_same_type<polygon_45_set_concept, typename geometry_concept<std::list<T> >::type>::type,
typename is_45_polygonal_concept<typename geometry_concept<typename std::list<T>::value_type>::type>::type>::type type;
};
template <typename T>
struct is_mutable_polygon_45_set_type<std::vector<T> > {
typedef typename gtl_or<
typename gtl_same_type<polygon_45_set_concept, typename geometry_concept<std::vector<T> >::type>::type,
typename is_45_polygonal_concept<typename geometry_concept<typename std::vector<T>::value_type>::type>::type>::type type;
};
template <typename T>
bool fracture_holes_45_by_concept() { return false; }
template <>
inline bool fracture_holes_45_by_concept<polygon_45_concept>() { return true; }
template <typename T, typename iT>
void get_45_polygons_T(T& t, iT begin, iT end) {
typedef typename polygon_45_set_traits<T>::coordinate_type Unit;
typedef typename geometry_concept<typename T::value_type>::type CType;
typename polygon_45_formation<Unit>::Polygon45Formation pf(fracture_holes_45_by_concept<CType>());
//std::cout << "FORMING POLYGONS\n";
pf.scan(t, begin, end);
}
template <typename T>
struct polygon_45_set_mutable_traits {};
template <typename T>
struct polygon_45_set_mutable_traits<std::list<T> > {
template <typename input_iterator_type>
static inline void set(std::list<T>& polygon_set, input_iterator_type input_begin, input_iterator_type input_end) {
polygon_set.clear();
polygon_45_set_data<typename polygon_45_set_traits<std::list<T> >::coordinate_type> ps;
ps.reserve(std::distance(input_begin, input_end));
ps.insert(input_begin, input_end);
ps.sort();
ps.clean();
get_45_polygons_T(polygon_set, ps.begin(), ps.end());
}
};
template <typename T>
struct polygon_45_set_mutable_traits<std::vector<T> > {
template <typename input_iterator_type>
static inline void set(std::vector<T>& polygon_set, input_iterator_type input_begin, input_iterator_type input_end) {
polygon_set.clear();
size_t num_ele = std::distance(input_begin, input_end);
polygon_set.reserve(num_ele);
polygon_45_set_data<typename polygon_45_set_traits<std::list<T> >::coordinate_type> ps;
ps.reserve(num_ele);
ps.insert(input_begin, input_end);
ps.sort();
ps.clean();
get_45_polygons_T(polygon_set, ps.begin(), ps.end());
}
};
template <typename T>
struct polygon_45_set_mutable_traits<polygon_45_set_data<T> > {
template <typename input_iterator_type>
static inline void set(polygon_45_set_data<T>& polygon_set,
input_iterator_type input_begin, input_iterator_type input_end) {
polygon_set.set(input_begin, input_end);
}
};
template <typename T>
struct polygon_45_set_traits<polygon_45_set_data<T> > {
typedef typename polygon_45_set_data<T>::coordinate_type coordinate_type;
typedef typename polygon_45_set_data<T>::iterator_type iterator_type;
typedef typename polygon_45_set_data<T>::operator_arg_type operator_arg_type;
static inline iterator_type begin(const polygon_45_set_data<T>& polygon_set) {
return polygon_set.begin();
}
static inline iterator_type end(const polygon_45_set_data<T>& polygon_set) {
return polygon_set.end();
}
static inline bool clean(const polygon_45_set_data<T>& polygon_set) { polygon_set.clean(); return true; }
static inline bool sorted(const polygon_45_set_data<T>& polygon_set) { polygon_set.sort(); return true; }
};
}
}
#endif

View file

@ -0,0 +1,107 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_45_WITH_HOLES_DATA_HPP
#define BOOST_POLYGON_POLYGON_45_WITH_HOLES_DATA_HPP
#include "isotropy.hpp"
#include "polygon_45_data.hpp"
namespace boost { namespace polygon{
struct polygon_45_with_holes_concept;
template <typename T>
class polygon_45_with_holes_data {
public:
typedef polygon_45_with_holes_concept geometry_type;
typedef T coordinate_type;
typedef typename polygon_45_data<T>::iterator_type iterator_type;
typedef typename std::list<polygon_45_data<coordinate_type> >::const_iterator iterator_holes_type;
typedef polygon_45_data<coordinate_type> hole_type;
typedef typename coordinate_traits<T>::coordinate_distance area_type;
typedef point_data<T> point_type;
// default constructor of point does not initialize x and y
inline polygon_45_with_holes_data() : self_(), holes_() {} //do nothing default constructor
template<class iT>
inline polygon_45_with_holes_data(iT input_begin, iT input_end) : self_(), holes_() {
set(input_begin, input_end);
}
template<class iT, typename hiT>
inline polygon_45_with_holes_data(iT input_begin, iT input_end, hiT holes_begin, hiT holes_end) : self_(), holes_() {
set(input_begin, input_end);
set_holes(holes_begin, holes_end);
}
template<class iT>
inline polygon_45_with_holes_data& set(iT input_begin, iT input_end) {
self_.set(input_begin, input_end);
return *this;
}
// initialize a polygon from x,y values, it is assumed that the first is an x
// and that the input is a well behaved polygon
template<class iT>
inline polygon_45_with_holes_data& set_holes(iT input_begin, iT input_end) {
holes_.clear(); //just in case there was some old data there
for( ; input_begin != input_end; ++ input_begin) {
holes_.push_back(hole_type());
holes_.back().set((*input_begin).begin(), (*input_begin).end());
}
return *this;
}
// copy constructor (since we have dynamic memory)
inline polygon_45_with_holes_data(const polygon_45_with_holes_data& that) : self_(that.self_),
holes_(that.holes_) {}
// assignment operator (since we have dynamic memory do a deep copy)
inline polygon_45_with_holes_data& operator=(const polygon_45_with_holes_data& that) {
self_ = that.self_;
holes_ = that.holes_;
return *this;
}
template <typename T2>
inline polygon_45_with_holes_data& operator=(const T2& rvalue);
// get begin iterator, returns a pointer to a const coordinate_type
inline const iterator_type begin() const {
return self_.begin();
}
// get end iterator, returns a pointer to a const coordinate_type
inline const iterator_type end() const {
return self_.end();
}
inline std::size_t size() const {
return self_.size();
}
// get begin iterator, returns a pointer to a const polygon
inline const iterator_holes_type begin_holes() const {
return holes_.begin();
}
// get end iterator, returns a pointer to a const polygon
inline const iterator_holes_type end_holes() const {
return holes_.end();
}
inline std::size_t size_holes() const {
return holes_.size();
}
public:
polygon_45_data<coordinate_type> self_;
std::list<hole_type> holes_;
};
}
}
#endif

View file

@ -0,0 +1,79 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_90_DATA_HPP
#define BOOST_POLYGON_POLYGON_90_DATA_HPP
namespace boost { namespace polygon{
struct polygon_90_concept;
template <typename T>
class polygon_90_data {
public:
typedef polygon_90_concept geometry_type;
typedef T coordinate_type;
typedef typename std::vector<coordinate_type>::const_iterator compact_iterator_type;
typedef iterator_compact_to_points<compact_iterator_type, point_data<coordinate_type> > iterator_type;
typedef typename coordinate_traits<T>::area_type area_type;
inline polygon_90_data() : coords_() {} //do nothing default constructor
// initialize a polygon from x,y values, it is assumed that the first is an x
// and that the input is a well behaved polygon
template<class iT>
inline polygon_90_data& set(iT begin_point, iT end_point) {
return set_compact(iterator_points_to_compact<iT, typename std::iterator_traits<iT>::value_type>(begin_point, end_point),
iterator_points_to_compact<iT, typename std::iterator_traits<iT>::value_type>(end_point, end_point));
}
template<class iT>
inline polygon_90_data& set_compact(iT input_begin, iT input_end) {
coords_.clear(); //just in case there was some old data there
while(input_begin != input_end) {
coords_.insert(coords_.end(), *input_begin);
++input_begin;
}
return *this;
}
// copy constructor (since we have dynamic memory)
inline polygon_90_data(const polygon_90_data& that) : coords_(that.coords_) {}
// assignment operator (since we have dynamic memory do a deep copy)
inline polygon_90_data& operator=(const polygon_90_data& that) {
coords_ = that.coords_;
return *this;
}
template <typename T2>
inline polygon_90_data& operator=(const T2& rvalue);
// assignment operator (since we have dynamic memory do a deep copy)
inline bool operator==(const polygon_90_data& that) const {
return coords_ == that.coords_;
}
// get begin iterator, returns a pointer to a const Unit
inline iterator_type begin() const { return iterator_type(coords_.begin(), coords_.end()); }
// get end iterator, returns a pointer to a const Unit
inline iterator_type end() const { return iterator_type(coords_.end(), coords_.end()); }
// get begin iterator, returns a pointer to a const Unit
inline compact_iterator_type begin_compact() const { return coords_.begin(); }
// get end iterator, returns a pointer to a const Unit
inline compact_iterator_type end_compact() const { return coords_.end(); }
inline std::size_t size() const { return coords_.size(); }
private:
std::vector<coordinate_type> coords_;
};
}
}
#endif

View file

@ -0,0 +1,551 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_90_SET_CONCEPT_HPP
#define BOOST_POLYGON_POLYGON_90_SET_CONCEPT_HPP
#include "polygon_90_set_data.hpp"
#include "polygon_90_set_traits.hpp"
namespace boost { namespace polygon{
template <typename polygon_set_type>
typename enable_if< typename is_polygon_90_set_type<polygon_set_type>::type,
typename polygon_90_set_traits<polygon_set_type>::iterator_type>::type
begin_90_set_data(const polygon_set_type& polygon_set) {
return polygon_90_set_traits<polygon_set_type>::begin(polygon_set);
}
template <typename polygon_set_type>
typename enable_if< typename is_polygon_90_set_type<polygon_set_type>::type,
typename polygon_90_set_traits<polygon_set_type>::iterator_type>::type
end_90_set_data(const polygon_set_type& polygon_set) {
return polygon_90_set_traits<polygon_set_type>::end(polygon_set);
}
template <typename polygon_set_type>
typename enable_if< typename is_polygon_90_set_type<polygon_set_type>::type,
orientation_2d>::type
scanline_orientation(const polygon_set_type& polygon_set) {
return polygon_90_set_traits<polygon_set_type>::orient(polygon_set);
}
template <typename polygon_set_type>
typename enable_if< typename is_polygon_90_set_type<polygon_set_type>::type,
bool>::type
clean(const polygon_set_type& polygon_set) {
return polygon_90_set_traits<polygon_set_type>::clean(polygon_set);
}
//assign
template <typename polygon_set_type_1, typename polygon_set_type_2>
typename enable_if <
typename gtl_and<
typename is_mutable_polygon_90_set_type<polygon_set_type_1>::type,
typename is_polygon_90_set_type<polygon_set_type_2>::type>::type,
polygon_set_type_1>::type &
assign(polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) {
polygon_90_set_mutable_traits<polygon_set_type_1>::set(lvalue, begin_90_set_data(rvalue), end_90_set_data(rvalue),
scanline_orientation(rvalue));
return lvalue;
}
template <typename T1, typename T2>
struct are_not_both_rectangle_concept { typedef gtl_yes type; };
template <>
struct are_not_both_rectangle_concept<rectangle_concept, rectangle_concept> { typedef gtl_no type; };
//equivalence
template <typename polygon_set_type_1, typename polygon_set_type_2>
typename enable_if< typename gtl_and_3<
typename is_polygon_90_set_type<polygon_set_type_1>::type,
typename is_polygon_90_set_type<polygon_set_type_2>::type,
typename are_not_both_rectangle_concept<typename geometry_concept<polygon_set_type_1>::type,
typename geometry_concept<polygon_set_type_2>::type>::type>::type,
bool>::type
equivalence(const polygon_set_type_1& lvalue,
const polygon_set_type_2& rvalue) {
polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type_1>::coordinate_type> ps1;
assign(ps1, lvalue);
polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type_2>::coordinate_type> ps2;
assign(ps2, rvalue);
return ps1 == ps2;
}
//get rectangle tiles (slicing orientation is vertical)
template <typename output_container_type, typename polygon_set_type>
typename enable_if< typename gtl_if<typename is_polygon_90_set_type<polygon_set_type>::type>::type,
void>::type
get_rectangles(output_container_type& output, const polygon_set_type& polygon_set) {
clean(polygon_set);
polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> ps(VERTICAL);
assign(ps, polygon_set);
ps.get_rectangles(output);
}
//get rectangle tiles
template <typename output_container_type, typename polygon_set_type>
typename enable_if< typename gtl_if<typename is_polygon_90_set_type<polygon_set_type>::type>::type,
void>::type
get_rectangles(output_container_type& output, const polygon_set_type& polygon_set, orientation_2d slicing_orientation) {
clean(polygon_set);
polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> ps;
assign(ps, polygon_set);
ps.get_rectangles(output, slicing_orientation);
}
//get: min_rectangles max_rectangles
template <typename output_container_type, typename polygon_set_type>
typename enable_if <typename gtl_and<
typename is_polygon_90_set_type<polygon_set_type>::type,
typename gtl_same_type<rectangle_concept,
typename geometry_concept
<typename std::iterator_traits
<typename output_container_type::iterator>::value_type>::type>::type>::type,
void>::type
get_max_rectangles(output_container_type& output, const polygon_set_type& polygon_set) {
std::vector<rectangle_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> > rects;
assign(rects, polygon_set);
MaxCover<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::getMaxCover(output, rects, scanline_orientation(polygon_set));
}
//clear
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
void>::type
clear(polygon_set_type& polygon_set) {
polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> ps(scanline_orientation(polygon_set));
assign(polygon_set, ps);
}
//empty
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
bool>::type
empty(const polygon_set_type& polygon_set) {
if(clean(polygon_set)) return begin_90_set_data(polygon_set) == end_90_set_data(polygon_set);
polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> ps;
assign(ps, polygon_set);
ps.clean();
return ps.empty();
}
//extents
template <typename polygon_set_type, typename rectangle_type>
typename enable_if <typename gtl_and< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
bool>::type
extents(rectangle_type& extents_rectangle,
const polygon_set_type& polygon_set) {
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
polygon_90_set_data<Unit> ps;
assign(ps, polygon_set);
return ps.extents(extents_rectangle);
}
//area
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::manhattan_area_type>::type
area(const polygon_set_type& polygon_set) {
typedef rectangle_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> rectangle_type;
typedef typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::manhattan_area_type area_type;
std::vector<rectangle_type> rects;
assign(rects, polygon_set);
area_type retval = (area_type)0;
for(std::size_t i = 0; i < rects.size(); ++i) {
retval += (area_type)area(rects[i]);
}
return retval;
}
//interact
template <typename polygon_set_type_1, typename polygon_set_type_2>
typename enable_if <typename gtl_and< typename is_mutable_polygon_90_set_type<polygon_set_type_1>::type,
typename is_mutable_polygon_90_set_type<polygon_set_type_2>::type>::type,
polygon_set_type_1>::type&
interact(polygon_set_type_1& polygon_set_1, const polygon_set_type_2& polygon_set_2) {
typedef typename polygon_90_set_traits<polygon_set_type_1>::coordinate_type Unit;
polygon_90_set_data<Unit> ps(scanline_orientation(polygon_set_2));
polygon_90_set_data<Unit> ps2(ps);
ps.insert(polygon_set_1);
ps2.insert(polygon_set_2);
ps.interact(ps2);
assign(polygon_set_1, ps);
return polygon_set_1;
}
//self_intersect
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
self_intersect(polygon_set_type& polygon_set) {
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
polygon_90_set_data<Unit> ps;
assign(ps, polygon_set);
ps.self_intersect();
assign(polygon_set, ps);
return polygon_set;
}
//self_xor
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
self_xor(polygon_set_type& polygon_set) {
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
polygon_90_set_data<Unit> ps;
assign(ps, polygon_set);
ps.self_xor();
assign(polygon_set, ps);
return polygon_set;
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
bloat(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
return bloat(polygon_set, bloating, bloating, bloating, bloating);
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
bloat(polygon_set_type& polygon_set, orientation_2d orient,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
if(orient == orientation_2d(HORIZONTAL))
return bloat(polygon_set, bloating, bloating, 0, 0);
return bloat(polygon_set, 0, 0, bloating, bloating);
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
bloat(polygon_set_type& polygon_set, orientation_2d orient,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type low_bloating,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type high_bloating) {
if(orient == orientation_2d(HORIZONTAL))
return bloat(polygon_set, low_bloating, high_bloating, 0, 0);
return bloat(polygon_set, 0, 0, low_bloating, high_bloating);
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
bloat(polygon_set_type& polygon_set, direction_2d dir,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
if(dir == direction_2d(EAST))
return bloat(polygon_set, 0, bloating, 0, 0);
if(dir == direction_2d(WEST))
return bloat(polygon_set, bloating, 0, 0, 0);
if(dir == direction_2d(SOUTH))
return bloat(polygon_set, 0, 0, bloating, 0);
return bloat(polygon_set, 0, 0, 0, bloating);
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
bloat(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type west_bloating,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type east_bloating,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type south_bloating,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type north_bloating) {
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
polygon_90_set_data<Unit> ps;
assign(ps, polygon_set);
ps.bloat(west_bloating, east_bloating, south_bloating, north_bloating);
ps.clean();
assign(polygon_set, ps);
return polygon_set;
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
shrink(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) {
return shrink(polygon_set, shrinking, shrinking, shrinking, shrinking);
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
shrink(polygon_set_type& polygon_set, orientation_2d orient,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) {
if(orient == orientation_2d(HORIZONTAL))
return shrink(polygon_set, shrinking, shrinking, 0, 0);
return shrink(polygon_set, 0, 0, shrinking, shrinking);
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
shrink(polygon_set_type& polygon_set, orientation_2d orient,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type low_shrinking,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type high_shrinking) {
if(orient == orientation_2d(HORIZONTAL))
return shrink(polygon_set, low_shrinking, high_shrinking, 0, 0);
return shrink(polygon_set, 0, 0, low_shrinking, high_shrinking);
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
shrink(polygon_set_type& polygon_set, direction_2d dir,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) {
if(dir == direction_2d(EAST))
return shrink(polygon_set, 0, shrinking, 0, 0);
if(dir == direction_2d(WEST))
return shrink(polygon_set, shrinking, 0, 0, 0);
if(dir == direction_2d(SOUTH))
return shrink(polygon_set, 0, 0, shrinking, 0);
return shrink(polygon_set, 0, 0, 0, shrinking);
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
shrink(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type west_shrinking,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type east_shrinking,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type south_shrinking,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type north_shrinking) {
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
polygon_90_set_data<Unit> ps;
assign(ps, polygon_set);
ps.shrink(west_shrinking, east_shrinking, south_shrinking, north_shrinking);
ps.clean();
assign(polygon_set, ps);
return polygon_set;
}
template <typename polygon_set_type, typename coord_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
resize(polygon_set_type& polygon_set, coord_type resizing) {
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
if(resizing > 0) {
return bloat(polygon_set, resizing);
}
if(resizing < 0) {
return shrink(polygon_set, -resizing);
}
return polygon_set;
}
//positive or negative values allow for any and all directions of sizing
template <typename polygon_set_type, typename coord_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
resize(polygon_set_type& polygon_set, coord_type west, coord_type east, coord_type south, coord_type north) {
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
polygon_90_set_data<Unit> ps;
assign(ps, polygon_set);
ps.resize(west, east, south, north);
assign(polygon_set, ps);
return polygon_set;
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
grow_and(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
return grow_and(polygon_set, bloating, bloating, bloating, bloating);
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
grow_and(polygon_set_type& polygon_set, orientation_2d orient,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
if(orient == orientation_2d(HORIZONTAL))
return grow_and(polygon_set, bloating, bloating, 0, 0);
return grow_and(polygon_set, 0, 0, bloating, bloating);
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
grow_and(polygon_set_type& polygon_set, orientation_2d orient,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type low_bloating,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type high_bloating) {
if(orient == orientation_2d(HORIZONTAL))
return grow_and(polygon_set, low_bloating, high_bloating, 0, 0);
return grow_and(polygon_set, 0, 0, low_bloating, high_bloating);
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
grow_and(polygon_set_type& polygon_set, direction_2d dir,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
if(dir == direction_2d(EAST))
return grow_and(polygon_set, 0, bloating, 0, 0);
if(dir == direction_2d(WEST))
return grow_and(polygon_set, bloating, 0, 0, 0);
if(dir == direction_2d(SOUTH))
return grow_and(polygon_set, 0, 0, bloating, 0);
return grow_and(polygon_set, 0, 0, 0, bloating);
}
template <typename polygon_set_type>
typename enable_if< typename gtl_if<typename is_mutable_polygon_90_set_type<polygon_set_type>::type>::type,
polygon_set_type>::type &
grow_and(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type west_bloating,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type east_bloating,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type south_bloating,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type north_bloating) {
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
std::vector<polygon_90_data<Unit> > polys;
assign(polys, polygon_set);
clear(polygon_set);
polygon_90_set_data<Unit> ps(scanline_orientation(polygon_set));
for(std::size_t i = 0; i < polys.size(); ++i) {
polygon_90_set_data<Unit> tmpPs(scanline_orientation(polygon_set));
tmpPs.insert(polys[i]);
bloat(tmpPs, west_bloating, east_bloating, south_bloating, north_bloating);
tmpPs.clean(); //apply implicit OR on tmp polygon set
ps.insert(tmpPs);
}
self_intersect(ps);
assign(polygon_set, ps);
return polygon_set;
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
scale_up(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>
::unsigned_area_type factor) {
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
polygon_90_set_data<Unit> ps;
assign(ps, polygon_set);
ps.scale_up(factor);
assign(polygon_set, ps);
return polygon_set;
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
scale_down(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>
::unsigned_area_type factor) {
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
polygon_90_set_data<Unit> ps;
assign(ps, polygon_set);
ps.scale_down(factor);
assign(polygon_set, ps);
return polygon_set;
}
template <typename polygon_set_type, typename scaling_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
scale(polygon_set_type& polygon_set,
const scaling_type& scaling) {
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
polygon_90_set_data<Unit> ps;
assign(ps, polygon_set);
ps.scale(scaling);
assign(polygon_set, ps);
return polygon_set;
}
struct y_p_s_move : gtl_yes {};
//move
template <typename polygon_set_type>
typename enable_if< typename gtl_and<y_p_s_move, typename gtl_if<typename is_mutable_polygon_90_set_type<polygon_set_type>::type>::type>::type,
polygon_set_type>::type &
move(polygon_set_type& polygon_set,
orientation_2d orient, typename polygon_90_set_traits<polygon_set_type>::coordinate_type displacement) {
if(orient == HORIZONTAL)
return move(polygon_set, displacement, 0);
else
return move(polygon_set, 0, displacement);
}
struct y_p_s_move2 : gtl_yes {};
template <typename polygon_set_type>
typename enable_if< typename gtl_and<y_p_s_move2, typename gtl_if<typename is_mutable_polygon_90_set_type<polygon_set_type>::type>::type>::type,
polygon_set_type>::type &
move(polygon_set_type& polygon_set, typename polygon_90_set_traits<polygon_set_type>::coordinate_type x_displacement,
typename polygon_90_set_traits<polygon_set_type>::coordinate_type y_displacement) {
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
polygon_90_set_data<Unit> ps;
assign(ps, polygon_set);
ps.move(x_displacement, y_displacement);
ps.clean();
assign(polygon_set, ps);
return polygon_set;
}
//transform
template <typename polygon_set_type, typename transformation_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
transform(polygon_set_type& polygon_set,
const transformation_type& transformation) {
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
polygon_90_set_data<Unit> ps;
assign(ps, polygon_set);
ps.transform(transformation);
ps.clean();
assign(polygon_set, ps);
return polygon_set;
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
}
//keep
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
polygon_set_type>::type &
keep(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_area,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_area,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_width,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_width,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_height,
typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_height) {
typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
typedef typename coordinate_traits<Unit>::unsigned_area_type uat;
std::list<polygon_90_data<Unit> > polys;
assign(polys, polygon_set);
clear(polygon_set);
typename std::list<polygon_90_data<Unit> >::iterator itr_nxt;
for(typename std::list<polygon_90_data<Unit> >::iterator itr = polys.begin(); itr != polys.end(); itr = itr_nxt){
itr_nxt = itr;
++itr_nxt;
rectangle_data<Unit> bbox;
extents(bbox, *itr);
uat pwidth = delta(bbox, HORIZONTAL);
if(pwidth > min_width && pwidth <= max_width){
uat pheight = delta(bbox, VERTICAL);
if(pheight > min_height && pheight <= max_height){
uat parea = area(*itr);
if(parea <= max_area && parea >= min_area) {
continue;
}
}
}
polys.erase(itr);
}
assign(polygon_set, polys);
return polygon_set;
}
}
}
#include "detail/polygon_90_set_view.hpp"
#endif

View file

@ -0,0 +1,989 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_90_SET_DATA_HPP
#define BOOST_POLYGON_POLYGON_90_SET_DATA_HPP
#include "isotropy.hpp"
#include "point_concept.hpp"
#include "transform.hpp"
#include "interval_concept.hpp"
#include "rectangle_concept.hpp"
#include "segment_concept.hpp"
#include "detail/iterator_points_to_compact.hpp"
#include "detail/iterator_compact_to_points.hpp"
#include "polygon_traits.hpp"
//manhattan boolean algorithms
#include "detail/boolean_op.hpp"
#include "detail/polygon_formation.hpp"
#include "detail/rectangle_formation.hpp"
#include "detail/max_cover.hpp"
#include "detail/property_merge.hpp"
#include "detail/polygon_90_touch.hpp"
#include "detail/iterator_geometry_to_set.hpp"
namespace boost { namespace polygon{
template <typename ltype, typename rtype, typename op_type>
class polygon_90_set_view;
template <typename T>
class polygon_90_set_data {
public:
typedef T coordinate_type;
typedef std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > > value_type;
typedef typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::const_iterator iterator_type;
typedef polygon_90_set_data operator_arg_type;
// default constructor
inline polygon_90_set_data() : orient_(HORIZONTAL), data_(), dirty_(false), unsorted_(false) {}
// constructor
inline polygon_90_set_data(orientation_2d orient) : orient_(orient), data_(), dirty_(false), unsorted_(false) {}
// constructor from an iterator pair over vertex data
template <typename iT>
inline polygon_90_set_data(orientation_2d orient, iT input_begin, iT input_end) :
orient_(HORIZONTAL), data_(), dirty_(false), unsorted_(false) {
dirty_ = true;
unsorted_ = true;
for( ; input_begin != input_end; ++input_begin) { insert(*input_begin); }
}
// copy constructor
inline polygon_90_set_data(const polygon_90_set_data& that) :
orient_(that.orient_), data_(that.data_), dirty_(that.dirty_), unsorted_(that.unsorted_) {}
template <typename ltype, typename rtype, typename op_type>
inline polygon_90_set_data(const polygon_90_set_view<ltype, rtype, op_type>& that);
// copy with orientation change constructor
inline polygon_90_set_data(orientation_2d orient, const polygon_90_set_data& that) :
orient_(orient), data_(), dirty_(false), unsorted_(false) {
insert(that, false, that.orient_);
}
// destructor
inline ~polygon_90_set_data() {}
// assignement operator
inline polygon_90_set_data& operator=(const polygon_90_set_data& that) {
if(this == &that) return *this;
orient_ = that.orient_;
data_ = that.data_;
dirty_ = that.dirty_;
unsorted_ = that.unsorted_;
return *this;
}
template <typename ltype, typename rtype, typename op_type>
inline polygon_90_set_data& operator=(const polygon_90_set_view<ltype, rtype, op_type>& that);
template <typename geometry_object>
inline polygon_90_set_data& operator=(const geometry_object& geometry) {
data_.clear();
insert(geometry);
return *this;
}
// insert iterator range
inline void insert(iterator_type input_begin, iterator_type input_end, orientation_2d orient = HORIZONTAL) {
if(input_begin == input_end || (!data_.empty() && &(*input_begin) == &(*(data_.begin())))) return;
dirty_ = true;
unsorted_ = true;
if(orient == orient_)
data_.insert(data_.end(), input_begin, input_end);
else {
for( ; input_begin != input_end; ++input_begin) {
insert(*input_begin, false, orient);
}
}
}
// insert iterator range
template <typename iT>
inline void insert(iT input_begin, iT input_end, orientation_2d orient = HORIZONTAL) {
if(input_begin == input_end) return;
dirty_ = true;
unsorted_ = true;
for( ; input_begin != input_end; ++input_begin) {
insert(*input_begin, false, orient);
}
}
inline void insert(const polygon_90_set_data& polygon_set) {
insert(polygon_set.begin(), polygon_set.end(), polygon_set.orient());
}
inline void insert(const std::pair<std::pair<point_data<coordinate_type>, point_data<coordinate_type> >, int>& edge, bool is_hole = false,
orientation_2d orient = HORIZONTAL) {
std::pair<coordinate_type, std::pair<coordinate_type, int> > vertex;
vertex.first = edge.first.first.x();
vertex.second.first = edge.first.first.y();
vertex.second.second = edge.second * (is_hole ? -1 : 1);
insert(vertex, false, VERTICAL);
vertex.first = edge.first.second.x();
vertex.second.first = edge.first.second.y();
vertex.second.second *= -1;
insert(vertex, false, VERTICAL);
}
template <typename geometry_type>
inline void insert(const geometry_type& geometry_object, bool is_hole = false, orientation_2d = HORIZONTAL) {
iterator_geometry_to_set<typename geometry_concept<geometry_type>::type, geometry_type>
begin_input(geometry_object, LOW, orient_, is_hole), end_input(geometry_object, HIGH, orient_, is_hole);
insert(begin_input, end_input, orient_);
}
inline void insert(const std::pair<coordinate_type, std::pair<coordinate_type, int> >& vertex, bool is_hole = false,
orientation_2d orient = HORIZONTAL) {
data_.push_back(vertex);
if(orient != orient_) std::swap(data_.back().first, data_.back().second.first);
if(is_hole) data_.back().second.second *= -1;
dirty_ = true;
unsorted_ = true;
}
inline void insert(coordinate_type major_coordinate, const std::pair<interval_data<coordinate_type>, int>& edge) {
std::pair<coordinate_type, std::pair<coordinate_type, int> > vertex;
vertex.first = major_coordinate;
vertex.second.first = edge.first.get(LOW);
vertex.second.second = edge.second;
insert(vertex, false, orient_);
vertex.second.first = edge.first.get(HIGH);
vertex.second.second *= -1;
insert(vertex, false, orient_);
}
template <typename output_container>
inline void get(output_container& output) const {
get_dispatch(output, typename geometry_concept<typename output_container::value_type>::type());
}
template <typename output_container>
inline void get(output_container& output, size_t vthreshold) const {
get_dispatch(output, typename geometry_concept<typename output_container::value_type>::type(), vthreshold);
}
template <typename output_container>
inline void get_polygons(output_container& output) const {
get_dispatch(output, polygon_90_concept());
}
template <typename output_container>
inline void get_rectangles(output_container& output) const {
clean();
form_rectangles(output, data_.begin(), data_.end(), orient_, rectangle_concept());
}
template <typename output_container>
inline void get_rectangles(output_container& output, orientation_2d slicing_orientation) const {
if(slicing_orientation == orient_) {
get_rectangles(output);
} else {
polygon_90_set_data<coordinate_type> ps(*this);
ps.transform(axis_transformation(axis_transformation::SWAP_XY));
output_container result;
ps.get_rectangles(result);
for(typename output_container::iterator itr = result.begin(); itr != result.end(); ++itr) {
::boost::polygon::transform(*itr, axis_transformation(axis_transformation::SWAP_XY));
}
output.insert(output.end(), result.begin(), result.end());
}
}
// equivalence operator
inline bool operator==(const polygon_90_set_data& p) const {
if(orient_ == p.orient()) {
clean();
p.clean();
return data_ == p.data_;
} else {
return false;
}
}
// inequivalence operator
inline bool operator!=(const polygon_90_set_data& p) const {
return !((*this) == p);
}
// get iterator to begin vertex data
inline iterator_type begin() const {
return data_.begin();
}
// get iterator to end vertex data
inline iterator_type end() const {
return data_.end();
}
const value_type& value() const {
return data_;
}
// clear the contents of the polygon_90_set_data
inline void clear() { data_.clear(); dirty_ = unsorted_ = false; }
// find out if Polygon set is empty
inline bool empty() const { clean(); return data_.empty(); }
// get the Polygon set size in vertices
inline std::size_t size() const { clean(); return data_.size(); }
// get the current Polygon set capacity in vertices
inline std::size_t capacity() const { return data_.capacity(); }
// reserve size of polygon set in vertices
inline void reserve(std::size_t size) { return data_.reserve(size); }
// find out if Polygon set is sorted
inline bool sorted() const { return !unsorted_; }
// find out if Polygon set is clean
inline bool dirty() const { return dirty_; }
// get the scanline orientation of the polygon set
inline orientation_2d orient() const { return orient_; }
// Start BM
// The problem: If we have two polygon sets with two different scanline orientations:
// I tried changing the orientation of one to coincide with other (If not, resulting boolean operation
// produces spurious results).
// First I tried copying polygon data from one of the sets into another set with corrected orientation
// using one of the copy constructor that takes in orientation (see somewhere above in this file) --> copy constructor throws error
// Then I tried another approach:(see below). This approach also fails to produce the desired results when test case is run.
// Here is the part that beats me: If I comment out the whole section, I can do all the operations (^=, -=, &= )these commented out
// operations perform. So then why do we need them?. Hence, I commented out this whole section.
// End BM
// polygon_90_set_data<coordinate_type>& operator-=(const polygon_90_set_data& that) {
// sort();
// that.sort();
// value_type data;
// std::swap(data, data_);
// applyBooleanBinaryOp(data.begin(), data.end(),
// that.begin(), that.end(), boolean_op::BinaryCount<boolean_op::BinaryNot>());
// return *this;
// }
// polygon_90_set_data<coordinate_type>& operator^=(const polygon_90_set_data& that) {
// sort();
// that.sort();
// value_type data;
// std::swap(data, data_);
// applyBooleanBinaryOp(data.begin(), data.end(),
// that.begin(), that.end(), boolean_op::BinaryCount<boolean_op::BinaryXor>());
// return *this;
// }
// polygon_90_set_data<coordinate_type>& operator&=(const polygon_90_set_data& that) {
// sort();
// that.sort();
// value_type data;
// std::swap(data, data_);
// applyBooleanBinaryOp(data.begin(), data.end(),
// that.begin(), that.end(), boolean_op::BinaryCount<boolean_op::BinaryAnd>());
// return *this;
// }
// polygon_90_set_data<coordinate_type>& operator|=(const polygon_90_set_data& that) {
// insert(that);
// return *this;
// }
void clean() const {
sort();
if(dirty_) {
boolean_op::default_arg_workaround<int>::applyBooleanOr(data_);
dirty_ = false;
}
}
void sort() const{
if(unsorted_) {
polygon_sort(data_.begin(), data_.end());
unsorted_ = false;
}
}
template <typename input_iterator_type>
void set(input_iterator_type input_begin, input_iterator_type input_end, orientation_2d orient) {
data_.clear();
reserve(std::distance(input_begin, input_end));
data_.insert(data_.end(), input_begin, input_end);
orient_ = orient;
dirty_ = true;
unsorted_ = true;
}
void set(const value_type& value, orientation_2d orient) {
data_ = value;
orient_ = orient;
dirty_ = true;
unsorted_ = true;
}
//extents
template <typename rectangle_type>
bool
extents(rectangle_type& extents_rectangle) const {
clean();
if(data_.empty()) return false;
if(orient_ == HORIZONTAL)
set_points(extents_rectangle, point_data<coordinate_type>(data_[0].second.first, data_[0].first),
point_data<coordinate_type>(data_[data_.size() - 1].second.first, data_[data_.size() - 1].first));
else
set_points(extents_rectangle, point_data<coordinate_type>(data_[0].first, data_[0].second.first),
point_data<coordinate_type>(data_[data_.size() - 1].first, data_[data_.size() - 1].second.first));
for(std::size_t i = 1; i < data_.size() - 1; ++i) {
if(orient_ == HORIZONTAL)
encompass(extents_rectangle, point_data<coordinate_type>(data_[i].second.first, data_[i].first));
else
encompass(extents_rectangle, point_data<coordinate_type>(data_[i].first, data_[i].second.first));
}
return true;
}
polygon_90_set_data&
bloat2(typename coordinate_traits<coordinate_type>::unsigned_area_type west_bloating,
typename coordinate_traits<coordinate_type>::unsigned_area_type east_bloating,
typename coordinate_traits<coordinate_type>::unsigned_area_type south_bloating,
typename coordinate_traits<coordinate_type>::unsigned_area_type north_bloating) {
std::vector<rectangle_data<coordinate_type> > rects;
clean();
rects.reserve(data_.size() / 2);
get(rects);
rectangle_data<coordinate_type> convolutionRectangle(interval_data<coordinate_type>(-((coordinate_type)west_bloating),
(coordinate_type)east_bloating),
interval_data<coordinate_type>(-((coordinate_type)south_bloating),
(coordinate_type)north_bloating));
for(typename std::vector<rectangle_data<coordinate_type> >::iterator itr = rects.begin();
itr != rects.end(); ++itr) {
convolve(*itr, convolutionRectangle);
}
clear();
insert(rects.begin(), rects.end());
return *this;
}
static void modify_pt(point_data<coordinate_type>& pt, const point_data<coordinate_type>& prev_pt,
const point_data<coordinate_type>& current_pt, const point_data<coordinate_type>& next_pt,
coordinate_type west_bloating,
coordinate_type east_bloating,
coordinate_type south_bloating,
coordinate_type north_bloating) {
bool pxl = prev_pt.x() < current_pt.x();
bool pyl = prev_pt.y() < current_pt.y();
bool nxl = next_pt.x() < current_pt.x();
bool nyl = next_pt.y() < current_pt.y();
bool pxg = prev_pt.x() > current_pt.x();
bool pyg = prev_pt.y() > current_pt.y();
bool nxg = next_pt.x() > current_pt.x();
bool nyg = next_pt.y() > current_pt.y();
//two of the four if statements will execute
if(pxl)
pt.y(current_pt.y() - south_bloating);
if(pxg)
pt.y(current_pt.y() + north_bloating);
if(nxl)
pt.y(current_pt.y() + north_bloating);
if(nxg)
pt.y(current_pt.y() - south_bloating);
if(pyl)
pt.x(current_pt.x() + east_bloating);
if(pyg)
pt.x(current_pt.x() - west_bloating);
if(nyl)
pt.x(current_pt.x() - west_bloating);
if(nyg)
pt.x(current_pt.x() + east_bloating);
}
static void resize_poly_up(std::vector<point_data<coordinate_type> >& poly,
coordinate_type west_bloating,
coordinate_type east_bloating,
coordinate_type south_bloating,
coordinate_type north_bloating) {
point_data<coordinate_type> first_pt = poly[0];
point_data<coordinate_type> second_pt = poly[1];
point_data<coordinate_type> prev_pt = poly[0];
point_data<coordinate_type> current_pt = poly[1];
for(std::size_t i = 2; i < poly.size(); ++i) {
point_data<coordinate_type> next_pt = poly[i];
modify_pt(poly[i-1], prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating);
prev_pt = current_pt;
current_pt = next_pt;
}
point_data<coordinate_type> next_pt = first_pt;
modify_pt(poly.back(), prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating);
prev_pt = current_pt;
current_pt = next_pt;
next_pt = second_pt;
modify_pt(poly[0], prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating);
remove_colinear_pts(poly);
}
static bool resize_poly_down(std::vector<point_data<coordinate_type> >& poly,
coordinate_type west_shrinking,
coordinate_type east_shrinking,
coordinate_type south_shrinking,
coordinate_type north_shrinking) {
rectangle_data<coordinate_type> extents_rectangle;
set_points(extents_rectangle, poly[0], poly[0]);
point_data<coordinate_type> first_pt = poly[0];
point_data<coordinate_type> second_pt = poly[1];
point_data<coordinate_type> prev_pt = poly[0];
point_data<coordinate_type> current_pt = poly[1];
encompass(extents_rectangle, current_pt);
for(std::size_t i = 2; i < poly.size(); ++i) {
point_data<coordinate_type> next_pt = poly[i];
encompass(extents_rectangle, next_pt);
modify_pt(poly[i-1], prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking);
prev_pt = current_pt;
current_pt = next_pt;
}
if(delta(extents_rectangle, HORIZONTAL) < std::abs(west_shrinking + east_shrinking))
return false;
if(delta(extents_rectangle, VERTICAL) < std::abs(north_shrinking + south_shrinking))
return false;
point_data<coordinate_type> next_pt = first_pt;
modify_pt(poly.back(), prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking);
prev_pt = current_pt;
current_pt = next_pt;
next_pt = second_pt;
modify_pt(poly[0], prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking);
return remove_colinear_pts(poly);
}
static bool remove_colinear_pts(std::vector<point_data<coordinate_type> >& poly) {
bool found_colinear = true;
while(found_colinear && poly.size() >= 4) {
found_colinear = false;
typename std::vector<point_data<coordinate_type> >::iterator itr = poly.begin();
itr += poly.size() - 1; //get last element position
typename std::vector<point_data<coordinate_type> >::iterator itr2 = poly.begin();
typename std::vector<point_data<coordinate_type> >::iterator itr3 = itr2;
++itr3;
std::size_t count = 0;
for( ; itr3 < poly.end(); ++itr3) {
if(((*itr).x() == (*itr2).x() && (*itr).x() == (*itr3).x()) ||
((*itr).y() == (*itr2).y() && (*itr).y() == (*itr3).y()) ) {
++count;
found_colinear = true;
} else {
itr = itr2;
++itr2;
}
*itr2 = *itr3;
}
itr3 = poly.begin();
if(((*itr).x() == (*itr2).x() && (*itr).x() == (*itr3).x()) ||
((*itr).y() == (*itr2).y() && (*itr).y() == (*itr3).y()) ) {
++count;
found_colinear = true;
}
poly.erase(poly.end() - count, poly.end());
}
return poly.size() >= 4;
}
polygon_90_set_data&
bloat(typename coordinate_traits<coordinate_type>::unsigned_area_type west_bloating,
typename coordinate_traits<coordinate_type>::unsigned_area_type east_bloating,
typename coordinate_traits<coordinate_type>::unsigned_area_type south_bloating,
typename coordinate_traits<coordinate_type>::unsigned_area_type north_bloating) {
std::list<polygon_45_with_holes_data<coordinate_type> > polys;
get(polys);
clear();
for(typename std::list<polygon_45_with_holes_data<coordinate_type> >::iterator itr = polys.begin();
itr != polys.end(); ++itr) {
//polygon_90_set_data<coordinate_type> psref;
//psref.insert(view_as<polygon_90_concept>((*itr).self_));
//rectangle_data<coordinate_type> prerect;
//psref.extents(prerect);
resize_poly_up((*itr).self_.coords_, (coordinate_type)west_bloating, (coordinate_type)east_bloating,
(coordinate_type)south_bloating, (coordinate_type)north_bloating);
iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
begin_input(view_as<polygon_90_concept>((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE),
end_input(view_as<polygon_90_concept>((*itr).self_), HIGH, orient_, false, true, COUNTERCLOCKWISE);
insert(begin_input, end_input, orient_);
//polygon_90_set_data<coordinate_type> pstest;
//pstest.insert(view_as<polygon_90_concept>((*itr).self_));
//psref.bloat2(west_bloating, east_bloating, south_bloating, north_bloating);
//if(!equivalence(psref, pstest)) {
// std::cout << "test failed\n";
//}
for(typename std::list<polygon_45_data<coordinate_type> >::iterator itrh = (*itr).holes_.begin();
itrh != (*itr).holes_.end(); ++itrh) {
//rectangle_data<coordinate_type> rect;
//psref.extents(rect);
//polygon_90_set_data<coordinate_type> psrefhole;
//psrefhole.insert(prerect);
//psrefhole.insert(view_as<polygon_90_concept>(*itrh), true);
//polygon_45_data<coordinate_type> testpoly(*itrh);
if(resize_poly_down((*itrh).coords_,(coordinate_type)west_bloating, (coordinate_type)east_bloating,
(coordinate_type)south_bloating, (coordinate_type)north_bloating)) {
iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
begin_input2(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true),
end_input2(view_as<polygon_90_concept>(*itrh), HIGH, orient_, true, true);
insert(begin_input2, end_input2, orient_);
//polygon_90_set_data<coordinate_type> pstesthole;
//pstesthole.insert(rect);
//iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
// begin_input2(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true);
//pstesthole.insert(begin_input2, end_input, orient_);
//psrefhole.bloat2(west_bloating, east_bloating, south_bloating, north_bloating);
//if(!equivalence(psrefhole, pstesthole)) {
// std::cout << (winding(testpoly) == CLOCKWISE) << std::endl;
// std::cout << (winding(*itrh) == CLOCKWISE) << std::endl;
// polygon_90_set_data<coordinate_type> c(psrefhole);
// c.clean();
// polygon_90_set_data<coordinate_type> a(pstesthole);
// polygon_90_set_data<coordinate_type> b(pstesthole);
// a.sort();
// b.clean();
// std::cout << "test hole failed\n";
// //std::cout << testpoly << std::endl;
//}
}
}
}
return *this;
}
polygon_90_set_data&
shrink(typename coordinate_traits<coordinate_type>::unsigned_area_type west_shrinking,
typename coordinate_traits<coordinate_type>::unsigned_area_type east_shrinking,
typename coordinate_traits<coordinate_type>::unsigned_area_type south_shrinking,
typename coordinate_traits<coordinate_type>::unsigned_area_type north_shrinking) {
std::list<polygon_45_with_holes_data<coordinate_type> > polys;
get(polys);
clear();
for(typename std::list<polygon_45_with_holes_data<coordinate_type> >::iterator itr = polys.begin();
itr != polys.end(); ++itr) {
//polygon_90_set_data<coordinate_type> psref;
//psref.insert(view_as<polygon_90_concept>((*itr).self_));
//rectangle_data<coordinate_type> prerect;
//psref.extents(prerect);
//polygon_45_data<coordinate_type> testpoly((*itr).self_);
if(resize_poly_down((*itr).self_.coords_, -(coordinate_type)west_shrinking, -(coordinate_type)east_shrinking,
-(coordinate_type)south_shrinking, -(coordinate_type)north_shrinking)) {
iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
begin_input(view_as<polygon_90_concept>((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE),
end_input(view_as<polygon_90_concept>((*itr).self_), HIGH, orient_, false, true, COUNTERCLOCKWISE);
insert(begin_input, end_input, orient_);
//iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
// begin_input2(view_as<polygon_90_concept>((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE);
//polygon_90_set_data<coordinate_type> pstest;
//pstest.insert(begin_input2, end_input, orient_);
//psref.shrink2(west_shrinking, east_shrinking, south_shrinking, north_shrinking);
//if(!equivalence(psref, pstest)) {
// std::cout << "test failed\n";
//}
for(typename std::list<polygon_45_data<coordinate_type> >::iterator itrh = (*itr).holes_.begin();
itrh != (*itr).holes_.end(); ++itrh) {
//rectangle_data<coordinate_type> rect;
//psref.extents(rect);
//polygon_90_set_data<coordinate_type> psrefhole;
//psrefhole.insert(prerect);
//psrefhole.insert(view_as<polygon_90_concept>(*itrh), true);
//polygon_45_data<coordinate_type> testpoly(*itrh);
resize_poly_up((*itrh).coords_, -(coordinate_type)west_shrinking, -(coordinate_type)east_shrinking,
-(coordinate_type)south_shrinking, -(coordinate_type)north_shrinking);
iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
begin_input2(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true),
end_input2(view_as<polygon_90_concept>(*itrh), HIGH, orient_, true, true);
insert(begin_input2, end_input2, orient_);
//polygon_90_set_data<coordinate_type> pstesthole;
//pstesthole.insert(rect);
//iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
// begin_input2(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true);
//pstesthole.insert(begin_input2, end_input, orient_);
//psrefhole.shrink2(west_shrinking, east_shrinking, south_shrinking, north_shrinking);
//if(!equivalence(psrefhole, pstesthole)) {
// std::cout << (winding(testpoly) == CLOCKWISE) << std::endl;
// std::cout << (winding(*itrh) == CLOCKWISE) << std::endl;
// polygon_90_set_data<coordinate_type> c(psrefhole);
// c.clean();
// polygon_90_set_data<coordinate_type> a(pstesthole);
// polygon_90_set_data<coordinate_type> b(pstesthole);
// a.sort();
// b.clean();
// std::cout << "test hole failed\n";
// //std::cout << testpoly << std::endl;
//}
}
}
}
return *this;
}
polygon_90_set_data&
shrink2(typename coordinate_traits<coordinate_type>::unsigned_area_type west_shrinking,
typename coordinate_traits<coordinate_type>::unsigned_area_type east_shrinking,
typename coordinate_traits<coordinate_type>::unsigned_area_type south_shrinking,
typename coordinate_traits<coordinate_type>::unsigned_area_type north_shrinking) {
rectangle_data<coordinate_type> externalBoundary;
if(!extents(externalBoundary)) return *this;
::boost::polygon::bloat(externalBoundary, 10); //bloat by diferential ammount
//insert a hole that encompasses the data
insert(externalBoundary, true); //note that the set is in a dirty state now
sort(); //does not apply implicit OR operation
std::vector<rectangle_data<coordinate_type> > rects;
rects.reserve(data_.size() / 2);
//begin does not apply implicit or operation, this is a dirty range
form_rectangles(rects, data_.begin(), data_.end(), orient_, rectangle_concept());
clear();
rectangle_data<coordinate_type> convolutionRectangle(interval_data<coordinate_type>(-((coordinate_type)east_shrinking),
(coordinate_type)west_shrinking),
interval_data<coordinate_type>(-((coordinate_type)north_shrinking),
(coordinate_type)south_shrinking));
for(typename std::vector<rectangle_data<coordinate_type> >::iterator itr = rects.begin();
itr != rects.end(); ++itr) {
rectangle_data<coordinate_type>& rect = *itr;
convolve(rect, convolutionRectangle);
//insert rectangle as a hole
insert(rect, true);
}
convolve(externalBoundary, convolutionRectangle);
//insert duplicate of external boundary as solid to cancel out the external hole boundaries
insert(externalBoundary);
clean(); //we have negative values in the set, so we need to apply an OR operation to make it valid input to a boolean
return *this;
}
polygon_90_set_data&
shrink(direction_2d dir, typename coordinate_traits<coordinate_type>::unsigned_area_type shrinking) {
if(dir == WEST)
return shrink(shrinking, 0, 0, 0);
if(dir == EAST)
return shrink(0, shrinking, 0, 0);
if(dir == SOUTH)
return shrink(0, 0, shrinking, 0);
return shrink(0, 0, 0, shrinking);
}
polygon_90_set_data&
bloat(direction_2d dir, typename coordinate_traits<coordinate_type>::unsigned_area_type shrinking) {
if(dir == WEST)
return bloat(shrinking, 0, 0, 0);
if(dir == EAST)
return bloat(0, shrinking, 0, 0);
if(dir == SOUTH)
return bloat(0, 0, shrinking, 0);
return bloat(0, 0, 0, shrinking);
}
polygon_90_set_data&
resize(coordinate_type west, coordinate_type east, coordinate_type south, coordinate_type north);
polygon_90_set_data& move(coordinate_type x_delta, coordinate_type y_delta) {
for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator
itr = data_.begin(); itr != data_.end(); ++itr) {
if(orient_ == orientation_2d(VERTICAL)) {
(*itr).first += x_delta;
(*itr).second.first += y_delta;
} else {
(*itr).second.first += x_delta;
(*itr).first += y_delta;
}
}
return *this;
}
// transform set
template <typename transformation_type>
polygon_90_set_data& transform(const transformation_type& transformation) {
direction_2d dir1, dir2;
transformation.get_directions(dir1, dir2);
int sign = dir1.get_sign() * dir2.get_sign();
for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator
itr = data_.begin(); itr != data_.end(); ++itr) {
if(orient_ == orientation_2d(VERTICAL)) {
transformation.transform((*itr).first, (*itr).second.first);
} else {
transformation.transform((*itr).second.first, (*itr).first);
}
(*itr).second.second *= sign;
}
if(dir1 != EAST || dir2 != NORTH)
unsorted_ = true; //some mirroring or rotation must have happened
return *this;
}
// scale set
polygon_90_set_data& scale_up(typename coordinate_traits<coordinate_type>::unsigned_area_type factor) {
for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator
itr = data_.begin(); itr != data_.end(); ++itr) {
(*itr).first *= (coordinate_type)factor;
(*itr).second.first *= (coordinate_type)factor;
}
return *this;
}
polygon_90_set_data& scale_down(typename coordinate_traits<coordinate_type>::unsigned_area_type factor) {
typedef typename coordinate_traits<coordinate_type>::coordinate_distance dt;
for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator
itr = data_.begin(); itr != data_.end(); ++itr) {
(*itr).first = scaling_policy<coordinate_type>::round((dt)((*itr).first) / (dt)factor);
(*itr).second.first = scaling_policy<coordinate_type>::round((dt)((*itr).second.first) / (dt)factor);
}
unsorted_ = true; //scaling down can make coordinates equal that were not previously equal
return *this;
}
template <typename scaling_type>
polygon_90_set_data& scale(const anisotropic_scale_factor<scaling_type>& scaling) {
for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator
itr = data_.begin(); itr != data_.end(); ++itr) {
if(orient_ == orientation_2d(VERTICAL)) {
scaling.scale((*itr).first, (*itr).second.first);
} else {
scaling.scale((*itr).second.first, (*itr).first);
}
}
unsorted_ = true;
return *this;
}
template <typename scaling_type>
polygon_90_set_data& scale_with(const scaling_type& scaling) {
for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator
itr = data_.begin(); itr != data_.end(); ++itr) {
if(orient_ == orientation_2d(VERTICAL)) {
scaling.scale((*itr).first, (*itr).second.first);
} else {
scaling.scale((*itr).second.first, (*itr).first);
}
}
unsorted_ = true;
return *this;
}
polygon_90_set_data& scale(double factor) {
typedef typename coordinate_traits<coordinate_type>::coordinate_distance dt;
for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator
itr = data_.begin(); itr != data_.end(); ++itr) {
(*itr).first = scaling_policy<coordinate_type>::round((dt)((*itr).first) * (dt)factor);
(*itr).second.first = scaling_policy<coordinate_type>::round((dt)((*itr).second.first) * (dt)factor);
}
unsorted_ = true; //scaling make coordinates equal that were not previously equal
return *this;
}
polygon_90_set_data& self_xor() {
sort();
if(dirty_) { //if it is clean it is a no-op
boolean_op::default_arg_workaround<boolean_op::UnaryCount>::applyBooleanOr(data_);
dirty_ = false;
}
return *this;
}
polygon_90_set_data& self_intersect() {
sort();
if(dirty_) { //if it is clean it is a no-op
interval_data<coordinate_type> ivl((std::numeric_limits<coordinate_type>::min)(), (std::numeric_limits<coordinate_type>::max)());
rectangle_data<coordinate_type> rect(ivl, ivl);
insert(rect, true);
clean();
}
return *this;
}
inline polygon_90_set_data& interact(const polygon_90_set_data& that) {
typedef coordinate_type Unit;
if(that.dirty_) that.clean();
typename touch_90_operation<Unit>::TouchSetData tsd;
touch_90_operation<Unit>::populateTouchSetData(tsd, that.data_, 0);
std::vector<polygon_90_data<Unit> > polys;
get(polys);
std::vector<std::set<int> > graph(polys.size()+1, std::set<int>());
for(std::size_t i = 0; i < polys.size(); ++i){
polygon_90_set_data<Unit> psTmp(that.orient_);
psTmp.insert(polys[i]);
psTmp.clean();
touch_90_operation<Unit>::populateTouchSetData(tsd, psTmp.data_, i+1);
}
touch_90_operation<Unit>::performTouch(graph, tsd);
clear();
for(std::set<int>::iterator itr = graph[0].begin(); itr != graph[0].end(); ++itr){
insert(polys[(*itr)-1]);
}
dirty_ = false;
return *this;
}
template <class T2, typename iterator_type_1, typename iterator_type_2>
void applyBooleanBinaryOp(iterator_type_1 itr1, iterator_type_1 itr1_end,
iterator_type_2 itr2, iterator_type_2 itr2_end,
T2 defaultCount) {
data_.clear();
boolean_op::applyBooleanBinaryOp(data_, itr1, itr1_end, itr2, itr2_end, defaultCount);
}
private:
orientation_2d orient_;
mutable value_type data_;
mutable bool dirty_;
mutable bool unsorted_;
private:
//functions
template <typename output_container>
void get_dispatch(output_container& output, rectangle_concept ) const {
clean();
form_rectangles(output, data_.begin(), data_.end(), orient_, rectangle_concept());
}
template <typename output_container>
void get_dispatch(output_container& output, polygon_90_concept tag) const {
get_fracture(output, true, tag);
}
template <typename output_container>
void get_dispatch(output_container& output, polygon_90_concept tag,
size_t vthreshold) const {
get_fracture(output, true, tag, vthreshold);
}
template <typename output_container>
void get_dispatch(output_container& output, polygon_90_with_holes_concept tag) const {
get_fracture(output, false, tag);
}
template <typename output_container>
void get_dispatch(output_container& output, polygon_90_with_holes_concept tag,
size_t vthreshold) const {
get_fracture(output, false, tag, vthreshold);
}
template <typename output_container>
void get_dispatch(output_container& output, polygon_45_concept tag) const {
get_fracture(output, true, tag);
}
template <typename output_container>
void get_dispatch(output_container& output, polygon_45_with_holes_concept tag) const {
get_fracture(output, false, tag);
}
template <typename output_container>
void get_dispatch(output_container& output, polygon_concept tag) const {
get_fracture(output, true, tag);
}
template <typename output_container>
void get_dispatch(output_container& output, polygon_with_holes_concept tag) const {
get_fracture(output, false, tag);
}
template <typename output_container, typename concept_type>
void get_fracture(output_container& container, bool fracture_holes, concept_type tag) const {
clean();
::boost::polygon::get_polygons(container, data_.begin(), data_.end(), orient_, fracture_holes, tag);
}
template <typename output_container, typename concept_type>
void get_fracture(output_container& container, bool fracture_holes, concept_type tag,
size_t vthreshold) const {
clean();
::boost::polygon::get_polygons(container, data_.begin(), data_.end(), orient_, fracture_holes, tag, vthreshold);
}
};
template <typename coordinate_type>
polygon_90_set_data<coordinate_type>&
polygon_90_set_data<coordinate_type>::resize(coordinate_type west,
coordinate_type east,
coordinate_type south,
coordinate_type north) {
move(-west, -south);
coordinate_type e_total = west + east;
coordinate_type n_total = south + north;
if((e_total < 0) ^ (n_total < 0)) {
//different signs
if(e_total < 0) {
shrink(0, -e_total, 0, 0);
if(n_total != 0)
return bloat(0, 0, 0, n_total);
else
return (*this);
} else {
shrink(0, 0, 0, -n_total); //shrink first
if(e_total != 0)
return bloat(0, e_total, 0, 0);
else
return (*this);
}
} else {
if(e_total < 0) {
return shrink(0, -e_total, 0, -n_total);
}
return bloat(0, e_total, 0, n_total);
}
}
template <typename coordinate_type, typename property_type>
class property_merge_90 {
private:
std::vector<std::pair<property_merge_point<coordinate_type>, std::pair<property_type, int> > > pmd_;
public:
inline property_merge_90() : pmd_() {}
inline property_merge_90(const property_merge_90& that) : pmd_(that.pmd_) {}
inline property_merge_90& operator=(const property_merge_90& that) { pmd_ = that.pmd_; return *this; }
inline void insert(const polygon_90_set_data<coordinate_type>& ps, const property_type& property) {
merge_scanline<coordinate_type, property_type, polygon_90_set_data<coordinate_type> >::
populate_property_merge_data(pmd_, ps.begin(), ps.end(), property, ps.orient());
}
template <class GeoObjT>
inline void insert(const GeoObjT& geoObj, const property_type& property) {
polygon_90_set_data<coordinate_type> ps;
ps.insert(geoObj);
insert(ps, property);
}
//merge properties of input geometries and store the resulting geometries of regions
//with unique sets of merged properties to polygons sets in a map keyed by sets of properties
// T = std::map<std::set<property_type>, polygon_90_set_data<coordiante_type> > or
// T = std::map<std::vector<property_type>, polygon_90_set_data<coordiante_type> >
template <typename ResultType>
inline void merge(ResultType& result) {
merge_scanline<coordinate_type, property_type, polygon_90_set_data<coordinate_type>, typename ResultType::key_type> ms;
ms.perform_merge(result, pmd_);
}
};
//ConnectivityExtraction computes the graph of connectivity between rectangle, polygon and
//polygon set graph nodes where an edge is created whenever the geometry in two nodes overlap
template <typename coordinate_type>
class connectivity_extraction_90 {
private:
typedef typename touch_90_operation<coordinate_type>::TouchSetData tsd;
tsd tsd_;
unsigned int nodeCount_;
public:
inline connectivity_extraction_90() : tsd_(), nodeCount_(0) {}
inline connectivity_extraction_90(const connectivity_extraction_90& that) : tsd_(that.tsd_),
nodeCount_(that.nodeCount_) {}
inline connectivity_extraction_90& operator=(const connectivity_extraction_90& that) {
tsd_ = that.tsd_;
nodeCount_ = that.nodeCount_; {}
return *this;
}
//insert a polygon set graph node, the value returned is the id of the graph node
inline unsigned int insert(const polygon_90_set_data<coordinate_type>& ps) {
ps.clean();
touch_90_operation<coordinate_type>::populateTouchSetData(tsd_, ps.begin(), ps.end(), nodeCount_);
return nodeCount_++;
}
template <class GeoObjT>
inline unsigned int insert(const GeoObjT& geoObj) {
polygon_90_set_data<coordinate_type> ps;
ps.insert(geoObj);
return insert(ps);
}
//extract connectivity and store the edges in the graph
//graph must be indexable by graph node id and the indexed value must be a std::set of
//graph node id
template <class GraphT>
inline void extract(GraphT& graph) {
touch_90_operation<coordinate_type>::performTouch(graph, tsd_);
}
};
}
}
#endif

View file

@ -0,0 +1,366 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_90_SET_TRAITS_HPP
#define BOOST_POLYGON_POLYGON_90_SET_TRAITS_HPP
namespace boost { namespace polygon{
struct polygon_90_set_concept {};
template <typename T, typename T2>
struct traits_by_concept {};
template <typename T>
struct traits_by_concept<T, coordinate_concept> { typedef coordinate_traits<T> type; };
template <typename T>
struct traits_by_concept<T, interval_concept> { typedef interval_traits<T> type; };
template <typename T>
struct traits_by_concept<T, point_concept> { typedef point_traits<T> type; };
template <typename T>
struct traits_by_concept<T, rectangle_concept> { typedef rectangle_traits<T> type; };
template <typename T>
struct traits_by_concept<T, segment_concept> { typedef segment_traits<T> type; };
template <typename T>
struct traits_by_concept<T, polygon_90_concept> { typedef polygon_traits<T> type; };
template <typename T>
struct traits_by_concept<T, polygon_90_with_holes_concept> { typedef polygon_traits<T> type; };
template <typename T>
struct traits_by_concept<T, polygon_45_concept> { typedef polygon_traits<T> type; };
template <typename T>
struct traits_by_concept<T, polygon_45_with_holes_concept> { typedef polygon_traits<T> type; };
template <typename T>
struct traits_by_concept<T, polygon_concept> { typedef polygon_traits<T> type; };
template <typename T>
struct traits_by_concept<T, polygon_with_holes_concept> { typedef polygon_traits<T> type; };
struct polygon_45_set_concept;
struct polygon_set_concept;
template <typename T>
struct polygon_90_set_traits;
template <typename T>
struct polygon_45_set_traits;
template <typename T>
struct polygon_set_traits;
template <typename T>
struct traits_by_concept<T, polygon_90_set_concept> { typedef polygon_90_set_traits<T> type; };
template <typename T>
struct traits_by_concept<T, polygon_45_set_concept> { typedef polygon_45_set_traits<T> type; };
template <typename T>
struct traits_by_concept<T, polygon_set_concept> { typedef polygon_set_traits<T> type; };
template <typename T, typename T2>
struct get_coordinate_type {
typedef typename traits_by_concept<T, T2>::type traits_type;
typedef typename traits_type::coordinate_type type;
};
//want to prevent recursive template definition syntax errors, so duplicate get_coordinate_type
template <typename T, typename T2>
struct get_coordinate_type_2 {
typedef typename traits_by_concept<T, T2>::type traits_type;
typedef typename traits_type::coordinate_type type;
};
template <typename T>
struct get_coordinate_type<T, undefined_concept> {
typedef typename get_coordinate_type_2<typename std::iterator_traits
<typename T::iterator>::value_type,
typename geometry_concept<typename std::iterator_traits
<typename T::iterator>::value_type>::type>::type type; };
template <typename T, typename T2>
struct get_iterator_type_2 {
typedef const T* type;
static type begin(const T& t) { return &t; }
static type end(const T& t) { const T* tp = &t; ++tp; return tp; }
};
template <typename T>
struct get_iterator_type {
typedef get_iterator_type_2<T, typename geometry_concept<T>::type> indirect_type;
typedef typename indirect_type::type type;
static type begin(const T& t) { return indirect_type::begin(t); }
static type end(const T& t) { return indirect_type::end(t); }
};
template <typename T>
struct get_iterator_type_2<T, undefined_concept> {
typedef typename T::const_iterator type;
static type begin(const T& t) { return t.begin(); }
static type end(const T& t) { return t.end(); }
};
// //helpers for allowing polygon 45 and containers of polygon 45 to behave interchangably in polygon_45_set_traits
// template <typename T, typename T2>
// struct get_coordinate_type_45 {};
// template <typename T, typename T2>
// struct get_coordinate_type_2_45 {};
// template <typename T>
// struct get_coordinate_type_45<T, void> {
// typedef typename get_coordinate_type_2_45< typename T::value_type, typename geometry_concept<typename T::value_type>::type >::type type; };
// template <typename T>
// struct get_coordinate_type_45<T, polygon_45_concept> { typedef typename polygon_traits<T>::coordinate_type type; };
// template <typename T>
// struct get_coordinate_type_45<T, polygon_45_with_holes_concept> { typedef typename polygon_traits<T>::coordinate_type type; };
// template <typename T>
// struct get_coordinate_type_2_45<T, polygon_45_concept> { typedef typename polygon_traits<T>::coordinate_type type; };
// template <typename T>
// struct get_coordinate_type_2_45<T, polygon_45_with_holes_concept> { typedef typename polygon_traits<T>::coordinate_type type; };
// template <typename T, typename T2>
// struct get_iterator_type_45 {};
// template <typename T>
// struct get_iterator_type_45<T, void> {
// typedef typename T::const_iterator type;
// static type begin(const T& t) { return t.begin(); }
// static type end(const T& t) { return t.end(); }
// };
// template <typename T>
// struct get_iterator_type_45<T, polygon_45_concept> {
// typedef const T* type;
// static type begin(const T& t) { return &t; }
// static type end(const T& t) { const T* tp = &t; ++tp; return tp; }
// };
// template <typename T>
// struct get_iterator_type_45<T, polygon_45_with_holes_concept> {
// typedef const T* type;
// static type begin(const T& t) { return &t; }
// static type end(const T& t) { const T* tp = &t; ++tp; return tp; }
// };
// template <typename T>
// struct get_iterator_type_45<T, polygon_90_set_concept> {
// typedef const T* type;
// static type begin(const T& t) { return &t; }
// static type end(const T& t) { const T* tp = &t; ++tp; return tp; }
// };
template <typename T>
struct polygon_90_set_traits {
typedef typename get_coordinate_type<T, typename geometry_concept<T>::type >::type coordinate_type;
typedef get_iterator_type<T> indirection_type;
typedef typename get_iterator_type<T>::type iterator_type;
typedef T operator_arg_type;
static inline iterator_type begin(const T& polygon_set) {
return indirection_type::begin(polygon_set);
}
static inline iterator_type end(const T& polygon_set) {
return indirection_type::end(polygon_set);
}
static inline orientation_2d orient(const T&) { return HORIZONTAL; }
static inline bool clean(const T&) { return false; }
static inline bool sorted(const T&) { return false; }
};
template <typename T>
struct is_manhattan_polygonal_concept { typedef gtl_no type; };
template <>
struct is_manhattan_polygonal_concept<rectangle_concept> { typedef gtl_yes type; };
template <>
struct is_manhattan_polygonal_concept<polygon_90_concept> { typedef gtl_yes type; };
template <>
struct is_manhattan_polygonal_concept<polygon_90_with_holes_concept> { typedef gtl_yes type; };
template <>
struct is_manhattan_polygonal_concept<polygon_90_set_concept> { typedef gtl_yes type; };
template <typename T>
struct is_polygon_90_set_type {
typedef typename is_manhattan_polygonal_concept<typename geometry_concept<T>::type>::type type;
};
template <typename T>
struct is_polygon_90_set_type<std::list<T> > {
typedef typename gtl_or<
typename is_manhattan_polygonal_concept<typename geometry_concept<std::list<T> >::type>::type,
typename is_manhattan_polygonal_concept<typename geometry_concept<typename std::list<T>::value_type>::type>::type>::type type;
};
template <typename T>
struct is_polygon_90_set_type<std::vector<T> > {
typedef typename gtl_or<
typename is_manhattan_polygonal_concept<typename geometry_concept<std::vector<T> >::type>::type,
typename is_manhattan_polygonal_concept<typename geometry_concept<typename std::vector<T>::value_type>::type>::type>::type type;
};
template <typename T>
struct is_mutable_polygon_90_set_type {
typedef typename gtl_same_type<polygon_90_set_concept, typename geometry_concept<T>::type>::type type;
};
template <typename T>
struct is_mutable_polygon_90_set_type<std::list<T> > {
typedef typename gtl_or<
typename gtl_same_type<polygon_90_set_concept, typename geometry_concept<std::list<T> >::type>::type,
typename is_manhattan_polygonal_concept<typename geometry_concept<typename std::list<T>::value_type>::type>::type>::type type;
};
template <typename T>
struct is_mutable_polygon_90_set_type<std::vector<T> > {
typedef typename gtl_or<
typename gtl_same_type<polygon_90_set_concept, typename geometry_concept<std::vector<T> >::type>::type,
typename is_manhattan_polygonal_concept<typename geometry_concept<typename std::vector<T>::value_type>::type>::type>::type type;
};
// //specialization for rectangle, polygon_90 and polygon_90_with_holes types
// template <typename T>
// struct polygon_90_set_traits
// typedef typename geometry_concept<T>::type concept_type;
// typedef typename get_coordinate_type<T, concept_type>::type coordinate_type;
// typedef iterator_geometry_to_set<concept_type, T> iterator_type;
// typedef T operator_arg_type;
// static inline iterator_type begin(const T& polygon_set) {
// return iterator_geometry_to_set<concept_type, T>(polygon_set, LOW, HORIZONTAL);
// }
// static inline iterator_type end(const T& polygon_set) {
// return iterator_geometry_to_set<concept_type, T>(polygon_set, HIGH, HORIZONTAL);
// }
// static inline orientation_2d orient(const T& polygon_set) { return HORIZONTAL; }
// static inline bool clean(const T& polygon_set) { return false; }
// static inline bool sorted(const T& polygon_set) { return false; }
// };
// //specialization for containers of recangle, polygon_90, polygon_90_with_holes
// template <typename T>
// struct polygon_90_set_traits<T, typename is_manhattan_polygonal_concept<typename std::iterator_traits<typename T::iterator>::value_type>::type> {
// typedef typename std::iterator_traits<typename T::iterator>::value_type geometry_type;
// typedef typename geometry_concept<geometry_type>::type concept_type;
// typedef typename get_coordinate_type<geometry_type, concept_type>::type coordinate_type;
// typedef iterator_geometry_range_to_set<concept_type, typename T::const_iterator> iterator_type;
// typedef T operator_arg_type;
// static inline iterator_type begin(const T& polygon_set) {
// return iterator_type(polygon_set.begin(), HORIZONTAL);
// }
// static inline iterator_type end(const T& polygon_set) {
// return iterator_type(polygon_set.end(), HORIZONTAL);
// }
// static inline orientation_2d orient(const T& polygon_set) { return HORIZONTAL; }
// static inline bool clean(const T& polygon_set) { return false; }
// static inline bool sorted(const T& polygon_set) { return false; }
// };
//get dispatch functions
template <typename output_container_type, typename pst>
void get_90_dispatch(output_container_type& output, const pst& ps,
orientation_2d orient, rectangle_concept ) {
form_rectangles(output, ps.begin(), ps.end(), orient, rectangle_concept());
}
template <typename output_container_type, typename pst>
void get_90_dispatch(output_container_type& output, const pst& ps,
orientation_2d orient, polygon_90_concept tag) {
get_polygons(output, ps.begin(), ps.end(), orient, true, tag);
}
template <typename output_container_type, typename pst>
void get_90_dispatch(output_container_type& output, const pst& ps,
orientation_2d orient, polygon_90_with_holes_concept tag) {
get_polygons(output, ps.begin(), ps.end(), orient, false, tag);
}
//by default works with containers of rectangle, polygon or polygon with holes
//must be specialized to work with anything else
template <typename T>
struct polygon_90_set_mutable_traits {};
template <typename T>
struct polygon_90_set_mutable_traits<std::list<T> > {
typedef typename geometry_concept<T>::type concept_type;
template <typename input_iterator_type>
static inline void set(std::list<T>& polygon_set, input_iterator_type input_begin, input_iterator_type input_end, orientation_2d orient) {
polygon_set.clear();
polygon_90_set_data<typename polygon_90_set_traits<std::list<T> >::coordinate_type> ps(orient);
ps.reserve(std::distance(input_begin, input_end));
ps.insert(input_begin, input_end, orient);
ps.clean();
get_90_dispatch(polygon_set, ps, orient, concept_type());
}
};
template <typename T>
struct polygon_90_set_mutable_traits<std::vector<T> > {
typedef typename geometry_concept<T>::type concept_type;
template <typename input_iterator_type>
static inline void set(std::vector<T>& polygon_set, input_iterator_type input_begin, input_iterator_type input_end, orientation_2d orient) {
polygon_set.clear();
size_t num_ele = std::distance(input_begin, input_end);
polygon_set.reserve(num_ele);
polygon_90_set_data<typename polygon_90_set_traits<std::list<T> >::coordinate_type> ps(orient);
ps.reserve(num_ele);
ps.insert(input_begin, input_end, orient);
ps.clean();
get_90_dispatch(polygon_set, ps, orient, concept_type());
}
};
template <typename T>
struct polygon_90_set_mutable_traits<polygon_90_set_data<T> > {
template <typename input_iterator_type>
static inline void set(polygon_90_set_data<T>& polygon_set,
input_iterator_type input_begin, input_iterator_type input_end,
orientation_2d orient) {
polygon_set.clear();
polygon_set.reserve(std::distance(input_begin, input_end));
polygon_set.insert(input_begin, input_end, orient);
}
};
template <typename T>
struct polygon_90_set_traits<polygon_90_set_data<T> > {
typedef typename polygon_90_set_data<T>::coordinate_type coordinate_type;
typedef typename polygon_90_set_data<T>::iterator_type iterator_type;
typedef typename polygon_90_set_data<T>::operator_arg_type operator_arg_type;
static inline iterator_type begin(const polygon_90_set_data<T>& polygon_set) {
return polygon_set.begin();
}
static inline iterator_type end(const polygon_90_set_data<T>& polygon_set) {
return polygon_set.end();
}
static inline orientation_2d orient(const polygon_90_set_data<T>& polygon_set) { return polygon_set.orient(); }
static inline bool clean(const polygon_90_set_data<T>& polygon_set) { polygon_set.clean(); return true; }
static inline bool sorted(const polygon_90_set_data<T>& polygon_set) { polygon_set.sort(); return true; }
};
template <typename T>
struct is_polygon_90_set_concept { };
template <>
struct is_polygon_90_set_concept<polygon_90_set_concept> { typedef gtl_yes type; };
template <>
struct is_polygon_90_set_concept<rectangle_concept> { typedef gtl_yes type; };
template <>
struct is_polygon_90_set_concept<polygon_90_concept> { typedef gtl_yes type; };
template <>
struct is_polygon_90_set_concept<polygon_90_with_holes_concept> { typedef gtl_yes type; };
template <typename T>
struct is_mutable_polygon_90_set_concept { typedef gtl_no type; };
template <>
struct is_mutable_polygon_90_set_concept<polygon_90_set_concept> { typedef gtl_yes type; };
template <typename T>
struct geometry_concept<polygon_90_set_data<T> > { typedef polygon_90_set_concept type; };
//template <typename T>
//typename enable_if<typename is_polygon_90_set_type<T>::type, void>::type
//print_is_polygon_90_set_concept(const T& t) { std::cout << "is polygon 90 set concept\n"; }
//template <typename T>
//typename enable_if<typename is_mutable_polygon_90_set_type<T>::type, void>::type
//print_is_mutable_polygon_90_set_concept(const T& t) { std::cout << "is mutable polygon 90 set concept\n"; }
}
}
#endif

View file

@ -0,0 +1,115 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_90_WITH_HOLES_DATA_HPP
#define BOOST_POLYGON_POLYGON_90_WITH_HOLES_DATA_HPP
namespace boost { namespace polygon{
#include "isotropy.hpp"
#include "polygon_90_data.hpp"
struct polygon_90_with_holes_concept;
template <typename T>
class polygon_90_with_holes_data {
public:
typedef polygon_90_with_holes_concept geometry_type;
typedef T coordinate_type;
typedef typename polygon_90_data<T>::iterator_type iterator_type;
typedef typename polygon_90_data<T>::compact_iterator_type compact_iterator_type;
typedef typename std::list<polygon_90_data<coordinate_type> >::const_iterator iterator_holes_type;
typedef polygon_90_data<coordinate_type> hole_type;
typedef typename coordinate_traits<T>::area_type area_type;
typedef point_data<T> point_type;
// default constructor of point does not initialize x and y
inline polygon_90_with_holes_data() : self_(), holes_() {} //do nothing default constructor
// initialize a polygon from x,y values, it is assumed that the first is an x
// and that the input is a well behaved polygon
template<class iT>
inline polygon_90_with_holes_data& set(iT input_begin, iT input_end) {
self_.set(input_begin, input_end);
return *this;
}
// initialize a polygon from x,y values, it is assumed that the first is an x
// and that the input is a well behaved polygon
template<class iT>
inline polygon_90_with_holes_data& set_compact(iT input_begin, iT input_end) {
self_.set_compact(input_begin, input_end);
return *this;
}
// initialize a polygon from x,y values, it is assumed that the first is an x
// and that the input is a well behaved polygon
template<class iT>
inline polygon_90_with_holes_data& set_holes(iT input_begin, iT input_end) {
holes_.clear(); //just in case there was some old data there
for( ; input_begin != input_end; ++ input_begin) {
holes_.push_back(hole_type());
holes_.back().set_compact((*input_begin).begin_compact(), (*input_begin).end_compact());
}
return *this;
}
// copy constructor (since we have dynamic memory)
inline polygon_90_with_holes_data(const polygon_90_with_holes_data& that) : self_(that.self_),
holes_(that.holes_) {}
// assignment operator (since we have dynamic memory do a deep copy)
inline polygon_90_with_holes_data& operator=(const polygon_90_with_holes_data& that) {
self_ = that.self_;
holes_ = that.holes_;
return *this;
}
template <typename T2>
inline polygon_90_with_holes_data& operator=(const T2& rvalue);
// get begin iterator, returns a pointer to a const coordinate_type
inline const iterator_type begin() const {
return self_.begin();
}
// get end iterator, returns a pointer to a const coordinate_type
inline const iterator_type end() const {
return self_.end();
}
// get begin iterator, returns a pointer to a const coordinate_type
inline const compact_iterator_type begin_compact() const {
return self_.begin_compact();
}
// get end iterator, returns a pointer to a const coordinate_type
inline const compact_iterator_type end_compact() const {
return self_.end_compact();
}
inline std::size_t size() const {
return self_.size();
}
// get begin iterator, returns a pointer to a const polygon
inline const iterator_holes_type begin_holes() const {
return holes_.begin();
}
// get end iterator, returns a pointer to a const polygon
inline const iterator_holes_type end_holes() const {
return holes_.end();
}
inline std::size_t size_holes() const {
return holes_.size();
}
private:
polygon_90_data<coordinate_type> self_;
std::list<hole_type> holes_;
};
}
}
#endif

View file

@ -0,0 +1,69 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_DATA_HPP
#define BOOST_POLYGON_POLYGON_DATA_HPP
namespace boost { namespace polygon{
struct polygon_concept;
template <typename T>
class polygon_data {
public:
typedef polygon_concept geometry_type;
typedef T coordinate_type;
typedef typename std::vector<point_data<coordinate_type> >::const_iterator iterator_type;
typedef typename coordinate_traits<T>::coordinate_distance area_type;
typedef point_data<T> point_type;
inline polygon_data() : coords_() {} //do nothing default constructor
template<class iT>
inline polygon_data(iT input_begin, iT input_end) : coords_(input_begin, input_end) {}
template<class iT>
inline polygon_data& set(iT input_begin, iT input_end) {
coords_.clear(); //just in case there was some old data there
coords_.insert(coords_.end(), input_begin, input_end);
return *this;
}
// copy constructor (since we have dynamic memory)
inline polygon_data(const polygon_data& that) : coords_(that.coords_) {}
// assignment operator (since we have dynamic memory do a deep copy)
inline polygon_data& operator=(const polygon_data& that) {
coords_ = that.coords_;
return *this;
}
template <typename T2>
inline polygon_data& operator=(const T2& rvalue);
inline bool operator==(const polygon_data& that) const {
if(coords_.size() != that.coords_.size()) return false;
for(std::size_t i = 0; i < coords_.size(); ++i) {
if(coords_[i] != that.coords_[i]) return false;
}
return true;
}
inline bool operator!=(const polygon_data& that) const { return !((*this) == that); }
// get begin iterator, returns a pointer to a const Unit
inline iterator_type begin() const { return coords_.begin(); }
// get end iterator, returns a pointer to a const Unit
inline iterator_type end() const { return coords_.end(); }
inline std::size_t size() const { return coords_.size(); }
public:
std::vector<point_data<coordinate_type> > coords_;
};
}
}
#endif

View file

@ -0,0 +1,581 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_SET_CONCEPT_HPP
#define BOOST_POLYGON_POLYGON_SET_CONCEPT_HPP
#include "polygon_set_data.hpp"
#include "detail/polygon_simplify.hpp"
namespace boost { namespace polygon{
template <typename T, typename T2>
struct is_either_polygon_set_type {
typedef typename gtl_or<typename is_polygon_set_type<T>::type, typename is_polygon_set_type<T2>::type >::type type;
};
template <typename T>
struct is_any_polygon_set_type {
typedef typename gtl_or<typename is_polygon_45_or_90_set_type<T>::type, typename is_polygon_set_type<T>::type >::type type;
};
template <typename polygon_set_type>
typename enable_if< typename is_any_polygon_set_type<polygon_set_type>::type,
typename polygon_set_traits<polygon_set_type>::iterator_type>::type
begin_polygon_set_data(const polygon_set_type& polygon_set) {
return polygon_set_traits<polygon_set_type>::begin(polygon_set);
}
template <typename polygon_set_type>
typename enable_if< typename is_any_polygon_set_type<polygon_set_type>::type,
typename polygon_set_traits<polygon_set_type>::iterator_type>::type
end_polygon_set_data(const polygon_set_type& polygon_set) {
return polygon_set_traits<polygon_set_type>::end(polygon_set);
}
template <typename polygon_set_type>
typename enable_if< typename is_polygon_set_type<polygon_set_type>::type,
bool>::type
clean(const polygon_set_type& polygon_set) {
return polygon_set_traits<polygon_set_type>::clean(polygon_set);
}
//assign
template <typename polygon_set_type_1, typename polygon_set_type_2>
typename enable_if< typename gtl_and<
typename is_mutable_polygon_set_type<polygon_set_type_1>::type,
typename is_any_polygon_set_type<polygon_set_type_2>::type>::type,
polygon_set_type_1>::type &
assign(polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) {
if(clean(rvalue))
polygon_set_mutable_traits<polygon_set_type_1>::set(lvalue, begin_polygon_set_data(rvalue), end_polygon_set_data(rvalue));
else {
polygon_set_data<typename polygon_set_traits<polygon_set_type_2>::coordinate_type> ps;
ps.insert(begin_polygon_set_data(rvalue), end_polygon_set_data(rvalue));
ps.clean();
polygon_set_mutable_traits<polygon_set_type_1>::set(lvalue, ps.begin(), ps.end());
}
return lvalue;
}
//get trapezoids
template <typename output_container_type, typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
void>::type
get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set) {
polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps;
assign(ps, polygon_set);
ps.get_trapezoids(output);
}
//get trapezoids
template <typename output_container_type, typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
void>::type
get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set,
orientation_2d orient) {
polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps;
assign(ps, polygon_set);
ps.get_trapezoids(output, orient);
}
//equivalence
template <typename polygon_set_type_1, typename polygon_set_type_2>
typename enable_if< typename gtl_and_3 <
typename is_any_polygon_set_type<polygon_set_type_1>::type,
typename is_any_polygon_set_type<polygon_set_type_2>::type,
typename is_either_polygon_set_type<polygon_set_type_1, polygon_set_type_2>::type>::type,
bool>::type
equivalence(const polygon_set_type_1& lvalue,
const polygon_set_type_2& rvalue) {
polygon_set_data<typename polygon_set_traits<polygon_set_type_1>::coordinate_type> ps1;
assign(ps1, lvalue);
polygon_set_data<typename polygon_set_traits<polygon_set_type_2>::coordinate_type> ps2;
assign(ps2, rvalue);
return ps1 == ps2;
}
//clear
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
void>::type
clear(polygon_set_type& polygon_set) {
polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps;
assign(polygon_set, ps);
}
//empty
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
bool>::type
empty(const polygon_set_type& polygon_set) {
if(clean(polygon_set)) return begin_polygon_set_data(polygon_set) == end_polygon_set_data(polygon_set);
polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps;
assign(ps, polygon_set);
ps.clean();
return ps.empty();
}
//extents
template <typename polygon_set_type, typename rectangle_type>
typename enable_if< typename gtl_and<
typename is_mutable_polygon_set_type<polygon_set_type>::type,
typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
bool>::type
extents(rectangle_type& extents_rectangle,
const polygon_set_type& polygon_set) {
clean(polygon_set);
polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps;
assign(ps, polygon_set);
return ps.extents(extents_rectangle);
}
//area
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::area_type>::type
area(const polygon_set_type& polygon_set) {
typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit;
typedef polygon_with_holes_data<Unit> p_type;
typedef typename coordinate_traits<Unit>::area_type area_type;
std::vector<p_type> polys;
assign(polys, polygon_set);
area_type retval = (area_type)0;
for(std::size_t i = 0; i < polys.size(); ++i) {
retval += area(polys[i]);
}
return retval;
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
std::size_t>::type
simplify(polygon_set_type& polygon_set, typename coordinate_traits<
typename polygon_set_traits<polygon_set_type>::coordinate_type
>::coordinate_distance threshold) {
typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit;
typedef polygon_with_holes_data<Unit> p_type;
std::vector<p_type> polys;
assign(polys, polygon_set);
std::size_t retval = 0;
for(std::size_t i = 0; i < polys.size(); ++i) {
retval += detail::simplify_detail::simplify(polys[i].self_.coords_,
polys[i].self_.coords_, threshold);
for(typename std::list<polygon_data<Unit> >::iterator itrh =
polys[i].holes_.begin(); itrh != (polys[i].holes_.end()); ++itrh) {
retval += detail::simplify_detail::simplify((*itrh).coords_,
(*itrh).coords_, threshold);
}
}
assign(polygon_set, polys);
return retval;
}
template <typename polygon_set_type, typename coord_type>
typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
polygon_set_type>::type &
resize(polygon_set_type& polygon_set, coord_type resizing, bool corner_fill_arcs = false, int num_circle_segments = 0) {
typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit;
clean(polygon_set);
polygon_set_data<Unit> ps;
assign(ps, polygon_set);
ps.resize(resizing, corner_fill_arcs,num_circle_segments);
assign(polygon_set, ps);
return polygon_set;
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
polygon_set_type>::type &
bloat(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
return resize(polygon_set, bloating);
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
polygon_set_type>::type &
shrink(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) {
return resize(polygon_set, -(typename polygon_set_traits<polygon_set_type>::coordinate_type)shrinking);
}
//interact
template <typename polygon_set_type_1, typename polygon_set_type_2>
typename enable_if< typename gtl_and_3 <
typename is_any_polygon_set_type<polygon_set_type_1>::type,
typename is_any_polygon_set_type<polygon_set_type_2>::type,
typename is_either_polygon_set_type<polygon_set_type_1, polygon_set_type_2>::type>::type,
polygon_set_type_1>::type&
interact(polygon_set_type_1& polygon_set_1, const polygon_set_type_2& polygon_set_2) {
polygon_set_data<typename polygon_set_traits<polygon_set_type_1>::coordinate_type> ps1;
assign(ps1, polygon_set_1);
polygon_set_data<typename polygon_set_traits<polygon_set_type_2>::coordinate_type> ps2;
assign(ps2, polygon_set_2);
ps1.interact(ps2);
assign(polygon_set_1, ps1);
return polygon_set_1;
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
polygon_set_type>::type &
scale_up(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type factor) {
typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit;
clean(polygon_set);
polygon_set_data<Unit> ps;
assign(ps, polygon_set);
ps.scale_up(factor);
assign(polygon_set, ps);
return polygon_set;
}
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
polygon_set_type>::type &
scale_down(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type factor) {
typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit;
clean(polygon_set);
polygon_set_data<Unit> ps;
assign(ps, polygon_set);
ps.scale_down(factor);
assign(polygon_set, ps);
return polygon_set;
}
//transform
template <typename polygon_set_type, typename transformation_type>
typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
polygon_set_type>::type &
transform(polygon_set_type& polygon_set,
const transformation_type& transformation) {
typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit;
clean(polygon_set);
polygon_set_data<Unit> ps;
assign(ps, polygon_set);
ps.transform(transformation);
assign(polygon_set, ps);
return polygon_set;
}
//keep
template <typename polygon_set_type>
typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
polygon_set_type>::type &
keep(polygon_set_type& polygon_set,
typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::area_type min_area,
typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::area_type max_area,
typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_width,
typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_width,
typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_height,
typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_height) {
typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit;
typedef typename coordinate_traits<Unit>::unsigned_area_type uat;
std::list<polygon_with_holes_data<Unit> > polys;
assign(polys, polygon_set);
typename std::list<polygon_with_holes_data<Unit> >::iterator itr_nxt;
for(typename std::list<polygon_with_holes_data<Unit> >::iterator itr = polys.begin(); itr != polys.end(); itr = itr_nxt){
itr_nxt = itr;
++itr_nxt;
rectangle_data<Unit> bbox;
extents(bbox, *itr);
uat pwidth = delta(bbox, HORIZONTAL);
if(pwidth > min_width && pwidth <= max_width){
uat pheight = delta(bbox, VERTICAL);
if(pheight > min_height && pheight <= max_height){
typename coordinate_traits<Unit>::area_type parea = area(*itr);
if(parea <= max_area && parea >= min_area) {
continue;
}
}
}
polys.erase(itr);
}
assign(polygon_set, polys);
return polygon_set;
}
namespace operators {
struct yes_ps_ob : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_4 < yes_ps_ob, typename is_any_polygon_set_type<geometry_type_1>::type,
typename is_any_polygon_set_type<geometry_type_2>::type,
typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type,
polygon_set_view<geometry_type_1, geometry_type_2, 0> >::type
operator|(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_set_view<geometry_type_1, geometry_type_2, 0>
(lvalue, rvalue);
}
struct yes_ps_op : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_4 < yes_ps_op,
typename gtl_if<typename is_any_polygon_set_type<geometry_type_1>::type>::type,
typename gtl_if<typename is_any_polygon_set_type<geometry_type_2>::type>::type,
typename gtl_if<typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type>
::type, polygon_set_view<geometry_type_1, geometry_type_2, 0> >::type
operator+(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_set_view<geometry_type_1, geometry_type_2, 0>
(lvalue, rvalue);
}
struct yes_ps_os : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_4 < yes_ps_os,
typename is_any_polygon_set_type<geometry_type_1>::type,
typename is_any_polygon_set_type<geometry_type_2>::type,
typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type,
polygon_set_view<geometry_type_1, geometry_type_2, 1> >::type
operator*(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_set_view<geometry_type_1, geometry_type_2, 1>
(lvalue, rvalue);
}
struct yes_ps_oa : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_4 < yes_ps_oa,
typename is_any_polygon_set_type<geometry_type_1>::type,
typename is_any_polygon_set_type<geometry_type_2>::type,
typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type,
polygon_set_view<geometry_type_1, geometry_type_2, 1> >::type
operator&(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_set_view<geometry_type_1, geometry_type_2, 1>
(lvalue, rvalue);
}
struct yes_ps_ox : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_4 < yes_ps_ox,
typename is_any_polygon_set_type<geometry_type_1>::type,
typename is_any_polygon_set_type<geometry_type_2>::type,
typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type,
polygon_set_view<geometry_type_1, geometry_type_2, 2> >::type
operator^(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_set_view<geometry_type_1, geometry_type_2, 2>
(lvalue, rvalue);
}
struct yes_ps_om : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_4 < yes_ps_om,
typename gtl_if<typename is_any_polygon_set_type<geometry_type_1>::type>::type,
typename gtl_if<typename is_any_polygon_set_type<geometry_type_2>::type>::type,
typename gtl_if<typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type>
::type, polygon_set_view<geometry_type_1, geometry_type_2, 3> >::type
operator-(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return polygon_set_view<geometry_type_1, geometry_type_2, 3>
(lvalue, rvalue);
}
struct yes_ps_ope : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_4< yes_ps_ope, gtl_yes, typename is_mutable_polygon_set_type<geometry_type_1>::type,
typename is_any_polygon_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator+=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 0>(lvalue, rvalue);
}
struct yes_ps_obe : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3< yes_ps_obe, typename is_mutable_polygon_set_type<geometry_type_1>::type,
typename is_any_polygon_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator|=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 0>(lvalue, rvalue);
}
struct yes_ps_ose : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3< yes_ps_ose, typename is_mutable_polygon_set_type<geometry_type_1>::type,
typename is_any_polygon_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator*=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 1>(lvalue, rvalue);
}
struct yes_ps_oae : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if<
typename gtl_and_3< yes_ps_oae, typename is_mutable_polygon_set_type<geometry_type_1>::type,
typename is_any_polygon_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator&=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 1>(lvalue, rvalue);
}
struct yes_ps_oxe : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if< typename gtl_and_3< yes_ps_oxe, typename is_mutable_polygon_set_type<geometry_type_1>::type,
typename is_any_polygon_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator^=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 2>(lvalue, rvalue);
}
struct yes_ps_ome : gtl_yes {};
template <typename geometry_type_1, typename geometry_type_2>
typename enable_if<
typename gtl_and_3< yes_ps_ome, typename is_mutable_polygon_set_type<geometry_type_1>::type,
typename is_any_polygon_set_type<geometry_type_2>::type>::type,
geometry_type_1>::type &
operator-=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 3>(lvalue, rvalue);
}
// TODO: Dafna, test these four resizing operators
struct y_ps_rpe : gtl_yes {};
template <typename geometry_type_1, typename coordinate_type_1>
typename enable_if< typename gtl_and_3< y_ps_rpe, typename is_mutable_polygon_set_type<geometry_type_1>::type,
typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type,
coordinate_concept>::type>::type,
geometry_type_1>::type &
operator+=(geometry_type_1& lvalue, coordinate_type_1 rvalue) {
return resize(lvalue, rvalue);
}
struct y_ps_rme : gtl_yes {};
template <typename geometry_type_1, typename coordinate_type_1>
typename enable_if< typename gtl_and_3<y_ps_rme, typename gtl_if<typename is_mutable_polygon_set_type<geometry_type_1>::type>::type,
typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type,
coordinate_concept>::type>::type,
geometry_type_1>::type &
operator-=(geometry_type_1& lvalue, coordinate_type_1 rvalue) {
return resize(lvalue, -rvalue);
}
struct y_ps_rp : gtl_yes {};
template <typename geometry_type_1, typename coordinate_type_1>
typename enable_if< typename gtl_and_3<y_ps_rp, typename gtl_if<typename is_mutable_polygon_set_type<geometry_type_1>::type>::type,
typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type,
coordinate_concept>::type>
::type, geometry_type_1>::type
operator+(const geometry_type_1& lvalue, coordinate_type_1 rvalue) {
geometry_type_1 retval(lvalue);
retval += rvalue;
return retval;
}
struct y_ps_rm : gtl_yes {};
template <typename geometry_type_1, typename coordinate_type_1>
typename enable_if< typename gtl_and_3<y_ps_rm, typename gtl_if<typename is_mutable_polygon_set_type<geometry_type_1>::type>::type,
typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type,
coordinate_concept>::type>
::type, geometry_type_1>::type
operator-(const geometry_type_1& lvalue, coordinate_type_1 rvalue) {
geometry_type_1 retval(lvalue);
retval -= rvalue;
return retval;
}
} //end operators namespace
template <typename T>
struct view_of<polygon_45_set_concept, T> {
typedef typename get_coordinate_type<T, typename geometry_concept<T>::type >::type coordinate_type;
T* tp;
std::vector<polygon_45_with_holes_data<coordinate_type> > polys;
view_of(const T& obj) : tp(), polys() {
std::vector<polygon_with_holes_data<coordinate_type> > gpolys;
assign(gpolys, obj);
for(typename std::vector<polygon_with_holes_data<coordinate_type> >::iterator itr = gpolys.begin();
itr != gpolys.end(); ++itr) {
polys.push_back(polygon_45_with_holes_data<coordinate_type>());
assign(polys.back(), view_as<polygon_45_with_holes_concept>(*itr));
}
}
view_of(T& obj) : tp(&obj), polys() {
std::vector<polygon_with_holes_data<coordinate_type> > gpolys;
assign(gpolys, obj);
for(typename std::vector<polygon_with_holes_data<coordinate_type> >::iterator itr = gpolys.begin();
itr != gpolys.end(); ++itr) {
polys.push_back(polygon_45_with_holes_data<coordinate_type>());
assign(polys.back(), view_as<polygon_45_with_holes_concept>(*itr));
}
}
typedef typename std::vector<polygon_45_with_holes_data<coordinate_type> >::const_iterator iterator_type;
typedef view_of operator_arg_type;
inline iterator_type begin() const {
return polys.begin();
}
inline iterator_type end() const {
return polys.end();
}
inline orientation_2d orient() const { return HORIZONTAL; }
inline bool clean() const { return false; }
inline bool sorted() const { return false; }
inline T& get() { return *tp; }
};
template <typename T>
struct polygon_45_set_traits<view_of<polygon_45_set_concept, T> > {
typedef typename view_of<polygon_45_set_concept, T>::coordinate_type coordinate_type;
typedef typename view_of<polygon_45_set_concept, T>::iterator_type iterator_type;
typedef view_of<polygon_45_set_concept, T> operator_arg_type;
static inline iterator_type begin(const view_of<polygon_45_set_concept, T>& polygon_set) {
return polygon_set.begin();
}
static inline iterator_type end(const view_of<polygon_45_set_concept, T>& polygon_set) {
return polygon_set.end();
}
static inline orientation_2d orient(const view_of<polygon_45_set_concept, T>& polygon_set) {
return polygon_set.orient(); }
static inline bool clean(const view_of<polygon_45_set_concept, T>& polygon_set) {
return polygon_set.clean(); }
static inline bool sorted(const view_of<polygon_45_set_concept, T>& polygon_set) {
return polygon_set.sorted(); }
};
template <typename T>
struct geometry_concept<view_of<polygon_45_set_concept, T> > {
typedef polygon_45_set_concept type;
};
template <typename T>
struct get_coordinate_type<view_of<polygon_45_set_concept, T>, polygon_45_set_concept> {
typedef typename view_of<polygon_45_set_concept, T>::coordinate_type type;
};
template <typename T>
struct get_iterator_type_2<view_of<polygon_45_set_concept, T>, polygon_45_set_concept> {
typedef typename view_of<polygon_45_set_concept, T>::iterator_type type;
static type begin(const view_of<polygon_45_set_concept, T>& t) { return t.begin(); }
static type end(const view_of<polygon_45_set_concept, T>& t) { return t.end(); }
};
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,133 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_SET_TRAITS_HPP
#define BOOST_POLYGON_POLYGON_SET_TRAITS_HPP
namespace boost { namespace polygon{
struct polygon_set_concept {};
//default definition of polygon set traits works for any model of polygon , polygon with holes or any vector or list thereof
template <typename T>
struct polygon_set_traits {
typedef typename get_coordinate_type<T, typename geometry_concept<T>::type >::type coordinate_type;
typedef typename get_iterator_type<T>::type iterator_type;
typedef T operator_arg_type;
static inline iterator_type begin(const T& polygon_set) {
return get_iterator_type<T>::begin(polygon_set);
}
static inline iterator_type end(const T& polygon_set) {
return get_iterator_type<T>::end(polygon_set);
}
static inline bool clean(const T& ) { return false; }
static inline bool sorted(const T& ) { return false; }
};
template <typename T>
struct is_polygonal_concept { typedef gtl_no type; };
template <>
struct is_polygonal_concept<polygon_concept> { typedef gtl_yes type; };
template <>
struct is_polygonal_concept<polygon_with_holes_concept> { typedef gtl_yes type; };
template <>
struct is_polygonal_concept<polygon_set_concept> { typedef gtl_yes type; };
template <typename T>
struct is_polygon_set_type {
typedef typename is_polygonal_concept<typename geometry_concept<T>::type>::type type;
};
template <typename T>
struct is_polygon_set_type<std::list<T> > {
typedef typename gtl_or<
typename is_polygonal_concept<typename geometry_concept<std::list<T> >::type>::type,
typename is_polygonal_concept<typename geometry_concept<typename std::list<T>::value_type>::type>::type>::type type;
};
template <typename T>
struct is_polygon_set_type<std::vector<T> > {
typedef typename gtl_or<
typename is_polygonal_concept<typename geometry_concept<std::vector<T> >::type>::type,
typename is_polygonal_concept<typename geometry_concept<typename std::vector<T>::value_type>::type>::type>::type type;
};
template <typename T>
struct is_mutable_polygon_set_type {
typedef typename gtl_same_type<polygon_set_concept, typename geometry_concept<T>::type>::type type;
};
template <typename T>
struct is_mutable_polygon_set_type<std::list<T> > {
typedef typename gtl_or<
typename gtl_same_type<polygon_set_concept, typename geometry_concept<std::list<T> >::type>::type,
typename is_polygonal_concept<typename geometry_concept<typename std::list<T>::value_type>::type>::type>::type type;
};
template <typename T>
struct is_mutable_polygon_set_type<std::vector<T> > {
typedef typename gtl_or<
typename gtl_same_type<polygon_set_concept, typename geometry_concept<std::vector<T> >::type>::type,
typename is_polygonal_concept<typename geometry_concept<typename std::vector<T>::value_type>::type>::type>::type type;
};
template <typename T>
struct polygon_set_mutable_traits {};
template <typename T>
struct polygon_set_mutable_traits<std::list<T> > {
template <typename input_iterator_type>
static inline void set(std::list<T>& polygon_set, input_iterator_type input_begin, input_iterator_type input_end) {
polygon_set.clear();
polygon_set_data<typename polygon_set_traits<std::list<T> >::coordinate_type> ps;
ps.reserve(std::distance(input_begin, input_end));
ps.insert(input_begin, input_end);
ps.get(polygon_set);
}
};
template <typename T>
struct polygon_set_mutable_traits<std::vector<T> > {
template <typename input_iterator_type>
static inline void set(std::vector<T>& polygon_set, input_iterator_type input_begin, input_iterator_type input_end) {
polygon_set.clear();
size_t num_ele = std::distance(input_begin, input_end);
polygon_set.reserve(num_ele);
polygon_set_data<typename polygon_set_traits<std::list<T> >::coordinate_type> ps;
ps.reserve(num_ele);
ps.insert(input_begin, input_end);
ps.get(polygon_set);
}
};
template <typename T>
struct polygon_set_mutable_traits<polygon_set_data<T> > {
template <typename input_iterator_type>
static inline void set(polygon_set_data<T>& polygon_set,
input_iterator_type input_begin, input_iterator_type input_end) {
polygon_set.set(input_begin, input_end);
}
};
template <typename T>
struct polygon_set_traits<polygon_set_data<T> > {
typedef typename polygon_set_data<T>::coordinate_type coordinate_type;
typedef typename polygon_set_data<T>::iterator_type iterator_type;
typedef typename polygon_set_data<T>::operator_arg_type operator_arg_type;
static inline iterator_type begin(const polygon_set_data<T>& polygon_set) {
return polygon_set.begin();
}
static inline iterator_type end(const polygon_set_data<T>& polygon_set) {
return polygon_set.end();
}
static inline bool clean(const polygon_set_data<T>& polygon_set) { polygon_set.clean(); return true; }
static inline bool sorted(const polygon_set_data<T>& polygon_set) { polygon_set.sort(); return true; }
};
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,107 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_POLYGON_WITH_HOLES_DATA_HPP
#define BOOST_POLYGON_POLYGON_WITH_HOLES_DATA_HPP
#include "isotropy.hpp"
#include "polygon_data.hpp"
namespace boost { namespace polygon{
struct polygon_with_holes_concept;
template <typename T>
class polygon_with_holes_data {
public:
typedef polygon_with_holes_concept geometry_type;
typedef T coordinate_type;
typedef typename polygon_data<T>::iterator_type iterator_type;
typedef typename std::list<polygon_data<coordinate_type> >::const_iterator iterator_holes_type;
typedef polygon_data<coordinate_type> hole_type;
typedef typename coordinate_traits<T>::coordinate_distance area_type;
typedef point_data<T> point_type;
// default constructor of point does not initialize x and y
inline polygon_with_holes_data() : self_(), holes_() {} //do nothing default constructor
template<class iT>
inline polygon_with_holes_data(iT input_begin, iT input_end) : self_(), holes_() {
set(input_begin, input_end);
}
template<class iT, typename hiT>
inline polygon_with_holes_data(iT input_begin, iT input_end, hiT holes_begin, hiT holes_end) : self_(), holes_() {
set(input_begin, input_end);
set_holes(holes_begin, holes_end);
}
template<class iT>
inline polygon_with_holes_data& set(iT input_begin, iT input_end) {
self_.set(input_begin, input_end);
return *this;
}
// initialize a polygon from x,y values, it is assumed that the first is an x
// and that the input is a well behaved polygon
template<class iT>
inline polygon_with_holes_data& set_holes(iT input_begin, iT input_end) {
holes_.clear(); //just in case there was some old data there
for( ; input_begin != input_end; ++ input_begin) {
holes_.push_back(hole_type());
holes_.back().set((*input_begin).begin(), (*input_begin).end());
}
return *this;
}
// copy constructor (since we have dynamic memory)
inline polygon_with_holes_data(const polygon_with_holes_data& that) : self_(that.self_),
holes_(that.holes_) {}
// assignment operator (since we have dynamic memory do a deep copy)
inline polygon_with_holes_data& operator=(const polygon_with_holes_data& that) {
self_ = that.self_;
holes_ = that.holes_;
return *this;
}
template <typename T2>
inline polygon_with_holes_data& operator=(const T2& rvalue);
// get begin iterator, returns a pointer to a const coordinate_type
inline const iterator_type begin() const {
return self_.begin();
}
// get end iterator, returns a pointer to a const coordinate_type
inline const iterator_type end() const {
return self_.end();
}
inline std::size_t size() const {
return self_.size();
}
// get begin iterator, returns a pointer to a const polygon
inline const iterator_holes_type begin_holes() const {
return holes_.begin();
}
// get end iterator, returns a pointer to a const polygon
inline const iterator_holes_type end_holes() const {
return holes_.end();
}
inline std::size_t size_holes() const {
return holes_.size();
}
public:
polygon_data<coordinate_type> self_;
std::list<hole_type> holes_;
};
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,63 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_RECTANGLE_DATA_HPP
#define BOOST_POLYGON_RECTANGLE_DATA_HPP
#include "isotropy.hpp"
//interval
#include "interval_data.hpp"
namespace boost { namespace polygon{
template <typename T>
class rectangle_data {
public:
typedef T coordinate_type;
typedef interval_data<T> interval_type;
inline rectangle_data():ranges_() {}
inline rectangle_data(T xl, T yl, T xh, T yh):ranges_() {
if(xl > xh) std::swap(xl, xh);
if(yl > yh) std::swap(yl, yh);
ranges_[HORIZONTAL] = interval_data<T>(xl, xh);
ranges_[VERTICAL] = interval_data<T>(yl, yh);
}
template <typename interval_type_1, typename interval_type_2>
inline rectangle_data(const interval_type_1& hrange,
const interval_type_2& vrange):ranges_() {
set(HORIZONTAL, hrange); set(VERTICAL, vrange); }
inline rectangle_data(const rectangle_data& that):ranges_() { (*this) = that; }
inline rectangle_data& operator=(const rectangle_data& that) {
ranges_[0] = that.ranges_[0]; ranges_[1] = that.ranges_[1]; return *this;
}
template <typename T2>
inline rectangle_data& operator=(const T2& rvalue);
template <typename T2>
inline bool operator==(const T2& rvalue) const;
template <typename T2>
inline bool operator!=(const T2& rvalue) const { return !((*this) == rvalue); }
inline interval_data<coordinate_type> get(orientation_2d orient) const {
return ranges_[orient.to_int()]; }
inline coordinate_type get(direction_2d dir) const {
return ranges_[orientation_2d(dir).to_int()].get(direction_1d(dir));
}
inline void set(direction_2d dir, coordinate_type value) {
return ranges_[orientation_2d(dir).to_int()].set(direction_1d(dir), value);
}
template <typename interval_type_1>
inline void set(orientation_2d orient, const interval_type_1& interval);
private:
interval_data<coordinate_type> ranges_[2];
};
}
}
#endif

View file

@ -0,0 +1,37 @@
/*
Copyright 2008 Intel Corporation
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_RECTANGLE_TRAITS_HPP
#define BOOST_POLYGON_RECTANGLE_TRAITS_HPP
namespace boost { namespace polygon{
template <typename T, typename enable = gtl_yes>
struct rectangle_traits {};
template <typename T>
struct rectangle_traits<T, gtl_no> {};
template <typename T>
struct rectangle_traits<T, typename gtl_same_type<typename T::interval_type, typename T::interval_type>::type> {
typedef typename T::coordinate_type coordinate_type;
typedef typename T::interval_type interval_type;
static inline interval_type get(const T& rectangle, orientation_2d orient) {
return rectangle.get(orient); }
};
template <typename T>
struct rectangle_mutable_traits {
template <typename T2>
static inline void set(T& rectangle, orientation_2d orient, const T2& interval) {
rectangle.set(orient, interval); }
template <typename T2, typename T3>
static inline T construct(const T2& interval_horizontal,
const T3& interval_vertical) {
return T(interval_horizontal, interval_vertical); }
};
}
}
#endif

View file

@ -0,0 +1,696 @@
// Boost.Polygon library segment_concept.hpp header file
// Copyright (c) Intel Corporation 2008.
// Copyright (c) 2008-2012 Simonson Lucanus.
// Copyright (c) 2012-2012 Andrii Sydorchuk.
// See http://www.boost.org for updates, documentation, and revision history.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_POLYGON_SEGMENT_CONCEPT_HPP
#define BOOST_POLYGON_SEGMENT_CONCEPT_HPP
#include "isotropy.hpp"
#include "segment_traits.hpp"
#include "rectangle_concept.hpp"
namespace boost {
namespace polygon {
struct segment_concept {};
template <typename ConceptType>
struct is_segment_concept {
typedef gtl_no type;
};
template <>
struct is_segment_concept<segment_concept> {
typedef gtl_yes type;
};
template <typename ConceptType>
struct is_mutable_segment_concept {
typedef gtl_no type;
};
template <>
struct is_mutable_segment_concept<segment_concept> {
typedef gtl_yes type;
};
template <typename GeometryType, typename BoolType>
struct segment_distance_type_by_concept {
typedef void type;
};
template <typename GeometryType>
struct segment_distance_type_by_concept<GeometryType, gtl_yes> {
typedef typename coordinate_traits<
typename segment_traits<GeometryType>::coordinate_type
>::coordinate_distance type;
};
template <typename GeometryType>
struct segment_distance_type {
typedef typename segment_distance_type_by_concept<
GeometryType,
typename is_segment_concept<
typename geometry_concept<GeometryType>::type
>::type
>::type type;
};
template <typename GeometryType, typename BoolType>
struct segment_point_type_by_concept {
typedef void type;
};
template <typename GeometryType>
struct segment_point_type_by_concept<GeometryType, gtl_yes> {
typedef typename segment_traits<GeometryType>::point_type type;
};
template <typename GeometryType>
struct segment_point_type {
typedef typename segment_point_type_by_concept<
GeometryType,
typename is_segment_concept<
typename geometry_concept<GeometryType>::type
>::type
>::type type;
};
template <typename GeometryType, typename BoolType>
struct segment_coordinate_type_by_concept {
typedef void type;
};
template <typename GeometryType>
struct segment_coordinate_type_by_concept<GeometryType, gtl_yes> {
typedef typename segment_traits<GeometryType>::coordinate_type type;
};
template <typename GeometryType>
struct segment_coordinate_type {
typedef typename segment_coordinate_type_by_concept<
GeometryType,
typename is_segment_concept<
typename geometry_concept<GeometryType>::type
>::type
>::type type;
};
struct y_s_get : gtl_yes {};
template <typename Segment>
typename enable_if<
typename gtl_and<
y_s_get,
typename is_segment_concept<
typename geometry_concept<Segment>::type
>::type
>::type,
typename segment_point_type<Segment>::type>::type
get(const Segment& segment, direction_1d dir) {
return segment_traits<Segment>::get(segment, dir);
}
struct y_s_set : gtl_yes {};
template <typename Segment, typename Point>
typename enable_if<
typename gtl_and_3<
y_s_set,
typename is_mutable_segment_concept<
typename geometry_concept<Segment>::type
>::type,
typename is_point_concept<
typename geometry_concept<Point>::type
>::type
>::type,
void>::type set(Segment& segment, direction_1d dir, const Point& point) {
segment_mutable_traits<Segment>::set(segment, dir, point);
}
struct y_s_construct : gtl_yes {};
template <typename Segment, typename Point1, typename Point2>
typename enable_if<
typename gtl_and_4<
y_s_construct,
typename is_mutable_segment_concept<
typename geometry_concept<Segment>::type
>::type,
typename is_point_concept<
typename geometry_concept<Point1>::type
>::type,
typename is_point_concept<
typename geometry_concept<Point2>::type
>::type
>::type,
Segment>::type construct(const Point1& low, const Point2& high) {
return segment_mutable_traits<Segment>::construct(low, high);
}
struct y_s_copy_construct : gtl_yes {};
template <typename Segment1, typename Segment2>
typename enable_if<
typename gtl_and_3<
y_s_copy_construct,
typename is_mutable_segment_concept<
typename geometry_concept<Segment1>::type
>::type,
typename is_segment_concept<
typename geometry_concept<Segment2>::type
>::type
>::type,
Segment1>::type copy_construct(const Segment2& segment) {
return construct<Segment1>(get(segment, LOW), get(segment, HIGH));
}
struct y_s_assign : gtl_yes {};
template <typename Segment1, typename Segment2>
typename enable_if<
typename gtl_and_3<
y_s_assign,
typename is_mutable_segment_concept<
typename geometry_concept<Segment1>::type
>::type,
typename is_segment_concept<
typename geometry_concept<Segment2>::type
>::type
>::type,
Segment1>::type& assign(Segment1& segment1, const Segment2& segment2) {
return segment1 = copy_construct<Segment1>(segment2);
}
struct y_s_equivalence : gtl_yes {};
template <typename Segment1, typename Segment2>
typename enable_if<
typename gtl_and_3<
y_s_equivalence,
typename is_segment_concept<
typename geometry_concept<Segment1>::type
>::type,
typename is_segment_concept<
typename geometry_concept<Segment2>::type
>::type
>::type,
bool>::type equivalence(const Segment1& segment1, const Segment2& segment2) {
return get(segment1, LOW) == get(segment2, LOW) &&
get(segment1, HIGH) == get(segment2, HIGH);
}
struct y_s_low : gtl_yes {};
template <typename Segment>
typename enable_if<
typename gtl_and<
y_s_low,
typename is_segment_concept<
typename geometry_concept<Segment>::type
>::type
>::type,
typename segment_point_type<Segment>::type>::type low(const Segment& segment) {
return get(segment, LOW);
}
struct y_s_high : gtl_yes {};
template <typename Segment>
typename enable_if<
typename gtl_and<
y_s_high,
typename is_segment_concept<
typename geometry_concept<Segment>::type
>::type
>::type,
typename segment_point_type<Segment>::type>::type high(const Segment& segment) {
return get(segment, HIGH);
}
struct y_s_center : gtl_yes {};
template <typename Segment>
typename enable_if<
typename gtl_and<
y_s_center,
typename is_segment_concept<
typename geometry_concept<Segment>::type
>::type
>::type,
typename segment_point_type<Segment>::type>::type
center(const Segment& segment) {
return construct<typename segment_point_type<Segment>::type>(
(x(high(segment)) + x(low(segment)))/2,
(y(high(segment)) + y(low(segment)))/2);
}
struct y_s_low2 : gtl_yes {};
template <typename Segment, typename Point>
typename enable_if<
typename gtl_and_3<
y_s_low2,
typename is_mutable_segment_concept<
typename geometry_concept<Segment>::type
>::type,
typename is_point_concept<
typename geometry_concept<Point>::type
>::type
>::type,
void>::type low(Segment& segment, const Point& point) {
set(segment, LOW, point);
}
struct y_s_high2 : gtl_yes {};
template <typename Segment, typename Point>
typename enable_if<
typename gtl_and_3<
y_s_high2,
typename is_mutable_segment_concept<
typename geometry_concept<Segment>::type
>::type,
typename is_point_concept<
typename geometry_concept<Point>::type
>::type
>::type,
void>::type high(Segment& segment, const Point& point) {
set(segment, HIGH, point);
}
struct y_s_orientation1 : gtl_yes {};
// -1 for CW, 0 for collinear and 1 for CCW.
template <typename Segment1, typename Segment2>
typename enable_if<
typename gtl_and_3<
y_s_orientation1,
typename is_segment_concept<
typename geometry_concept<Segment1>::type
>::type,
typename is_segment_concept<
typename geometry_concept<Segment2>::type
>::type
>::type,
int>::type orientation(const Segment1& segment1, const Segment2& segment2) {
typedef typename coordinate_traits<
typename segment_traits<Segment1>::coordinate_type
>::manhattan_area_type int_x2;
typedef typename coordinate_traits<
typename segment_traits<Segment1>::coordinate_type
>::unsigned_area_type uint_x2;
int_x2 a1 = (int_x2)x(high(segment1)) - (int_x2)x(low(segment1));
int_x2 b1 = (int_x2)y(high(segment1)) - (int_x2)y(low(segment1));
int_x2 a2 = (int_x2)x(high(segment2)) - (int_x2)x(low(segment2));
int_x2 b2 = (int_x2)y(high(segment2)) - (int_x2)y(low(segment2));
int sign1 = 0;
int sign2 = 0;
if (a1 && b2)
sign1 = ((a1 > 0) ^ (b2 > 0)) ? -1 : 1;
if (a2 && b1)
sign2 = ((a2 > 0) ^ (b1 > 0)) ? -1 : 1;
if (sign1 != sign2)
return (sign1 < sign2) ? -1 : 1;
uint_x2 a3 = (uint_x2)(a1 < 0 ? -a1 : a1) * (uint_x2)(b2 < 0 ? -b2 : b2);
uint_x2 b3 = (uint_x2)(b1 < 0 ? -b1 : b1) * (uint_x2)(a2 < 0 ? -a2 : a2);
if (a3 == b3)
return 0;
return ((a3 < b3) ^ (sign1 == 1)) ? 1 : -1;
}
struct y_s_orientation2 : gtl_yes {};
// -1 for right, 0 for collinear and 1 for left.
template <typename Segment, typename Point>
typename enable_if<
typename gtl_and_3<
y_s_orientation2,
typename is_segment_concept<
typename geometry_concept<Segment>::type
>::type,
typename is_point_concept<
typename geometry_concept<Point>::type
>::type
>::type,
int>::type orientation(const Segment& segment, const Point& point) {
Segment segment2 = construct<Segment>(high(segment), point);
return orientation(segment, segment2);
}
struct y_s_contains : gtl_yes {};
template <typename Segment, typename Point>
typename enable_if<
typename gtl_and_3<
y_s_contains,
typename is_segment_concept<
typename geometry_concept<Segment>::type
>::type,
typename is_point_concept<
typename geometry_concept<Point>::type
>::type
>::type,
bool>::type contains(const Segment& segment,
const Point& point, bool consider_touch = true ) {
if (orientation(segment, point))
return false;
rectangle_data<typename segment_coordinate_type<Segment>::type> rect;
set_points(rect, low(segment), high(segment));
if (!contains(rect, point, true))
return false;
if (!consider_touch &&
(equivalence(low(segment), point) ||
equivalence(high(segment), point)))
return false;
return true;
}
struct y_s_contains2 : gtl_yes {};
template <typename Segment1, typename Segment2>
typename enable_if<
typename gtl_and_3<
y_s_contains2,
typename is_segment_concept<
typename geometry_concept<Segment1>::type
>::type,
typename is_segment_concept<
typename geometry_concept<Segment2>::type
>::type
>::type,
bool>::type contains(const Segment1& segment1,
const Segment2& segment2, bool consider_touch = true) {
return contains(segment1, get(segment2, LOW), consider_touch) &&
contains(segment1, get(segment2, HIGH), consider_touch);
}
struct y_s_length : gtl_yes {};
template <typename Segment>
typename enable_if<
typename gtl_and<
y_s_length,
typename is_segment_concept<
typename geometry_concept<Segment>::type
>::type
>::type,
typename segment_distance_type<Segment>::type>::type
length(const Segment& segment) {
return euclidean_distance(low(segment), high(segment));
}
struct y_s_scale_up : gtl_yes {};
template <typename Segment>
typename enable_if<
typename gtl_and<
y_s_scale_up,
typename is_mutable_segment_concept<
typename geometry_concept<Segment>::type
>::type
>::type,
Segment>::type& scale_up(Segment& segment,
typename coordinate_traits<
typename segment_coordinate_type<Segment>::type
>::unsigned_area_type factor) {
typename segment_point_type<Segment>::type l = low(segment);
typename segment_point_type<Segment>::type h = high(segment);
low(segment, scale_up(l, factor));
high(segment, scale_up(h, factor));
return segment;
}
struct y_s_scale_down : gtl_yes {};
template <typename Segment>
typename enable_if<
typename gtl_and<
y_s_scale_down,
typename is_mutable_segment_concept<
typename geometry_concept<Segment>::type
>::type
>::type,
Segment>::type& scale_down(Segment& segment,
typename coordinate_traits<
typename segment_coordinate_type<Segment>::type
>::unsigned_area_type factor) {
typename segment_point_type<Segment>::type l = low(segment);
typename segment_point_type<Segment>::type h = high(segment);
low(segment, scale_down(l, factor));
high(segment, scale_down(h, factor));
return segment;
}
struct y_s_scale : gtl_yes {};
template <typename Segment, typename Scale>
typename enable_if<
typename gtl_and<
y_s_scale,
typename is_mutable_segment_concept<
typename geometry_concept<Segment>::type
>::type
>::type,
Segment>::type& scale(Segment& segment, const Scale& sc) {
typename segment_point_type<Segment>::type l = low(segment);
typename segment_point_type<Segment>::type h = high(segment);
low(segment, scale(l, sc));
high(segment, scale(h, sc));
return segment;
}
struct y_s_transform : gtl_yes {};
template <typename Segment, typename Transform>
typename enable_if<
typename gtl_and<
y_s_transform,
typename is_mutable_segment_concept<
typename geometry_concept<Segment>::type
>::type
>::type,
Segment>::type& transform(Segment& segment, const Transform& tr) {
typename segment_point_type<Segment>::type l = low(segment);
typename segment_point_type<Segment>::type h = high(segment);
low(segment, transform(l, tr));
high(segment, transform(h, tr));
return segment;
}
struct y_s_move : gtl_yes {};
template <typename Segment>
typename enable_if<
typename gtl_and<
y_s_move,
typename is_mutable_segment_concept<
typename geometry_concept<Segment>::type
>::type
>::type,
Segment>::type& move(Segment& segment, orientation_2d orient,
typename segment_coordinate_type<Segment>::type displacement) {
typename segment_point_type<Segment>::type l = low(segment);
typename segment_point_type<Segment>::type h = high(segment);
low(segment, move(l, orient, displacement));
high(segment, move(h, orient, displacement));
return segment;
}
struct y_s_convolve : gtl_yes {};
template <typename Segment, typename Point>
typename enable_if<
typename gtl_and_3<
y_s_convolve,
typename is_mutable_segment_concept<
typename geometry_concept<Segment>::type
>::type,
typename is_point_concept<
typename geometry_concept<Point>::type
>::type
>::type,
Segment>::type& convolve(Segment& segment, const Point& point) {
typename segment_point_type<Segment>::type l = low(segment);
typename segment_point_type<Segment>::type h = high(segment);
low(segment, convolve(l, point));
high(segment, convolve(h, point));
return segment;
}
struct y_s_deconvolve : gtl_yes {};
template <typename Segment, typename Point>
typename enable_if<
typename gtl_and_3<
y_s_deconvolve,
typename is_mutable_segment_concept<
typename geometry_concept<Segment>::type
>::type,
typename is_point_concept<
typename geometry_concept<Point>::type
>::type
>::type,
Segment>::type& deconvolve(Segment& segment, const Point& point) {
typename segment_point_type<Segment>::type l = low(segment);
typename segment_point_type<Segment>::type h = high(segment);
low(segment, deconvolve(l, point));
high(segment, deconvolve(h, point));
return segment;
}
struct y_s_abuts1 : gtl_yes {};
template <typename Segment1, typename Segment2>
typename enable_if<
typename gtl_and_3<
y_s_abuts1,
typename is_segment_concept<
typename geometry_concept<Segment1>::type
>::type,
typename is_segment_concept<
typename geometry_concept<Segment2>::type
>::type
>::type,
bool>::type abuts(const Segment1& segment1,
const Segment2& segment2, direction_1d dir) {
return dir.to_int() ? equivalence(low(segment2) , high(segment1)) :
equivalence(low(segment1) , high(segment2));
}
struct y_s_abuts2 : gtl_yes {};
template <typename Segment1, typename Segment2>
typename enable_if<
typename gtl_and_3<
y_s_abuts2,
typename is_segment_concept<
typename geometry_concept<Segment1>::type
>::type,
typename is_segment_concept<
typename geometry_concept<Segment2>::type
>::type
>::type,
bool>::type abuts(const Segment1& segment1, const Segment2& segment2) {
return abuts(segment1, segment2, HIGH) || abuts(segment1, segment2, LOW);
}
struct y_s_e_intersects : gtl_yes {};
template <typename Segment1, typename Segment2>
typename enable_if<
typename gtl_and_3<
y_s_e_intersects,
typename is_segment_concept<
typename geometry_concept<Segment1>::type
>::type,
typename is_segment_concept<
typename geometry_concept<Segment2>::type
>::type
>::type,
bool
>::type intersects(const Segment1& segment1, const Segment2& segment2,
bool consider_touch = true) {
rectangle_data<typename segment_coordinate_type<Segment1>::type> rect1, rect2;
set_points(rect1, low(segment1), high(segment1));
set_points(rect2, low(segment2), high(segment2));
// Check if axis-parallel rectangles containing segments intersect.
if (!intersects(rect1, rect2, true))
return false;
int or1_1 = orientation(segment1, low(segment2));
int or1_2 = orientation(segment1, high(segment2));
if (or1_1 * or1_2 > 0)
return false;
int or2_1 = orientation(segment2, low(segment1));
int or2_2 = orientation(segment2, high(segment1));
if (or2_1 * or2_2 > 0)
return false;
if (consider_touch || (or1_1 && or1_2) || (or2_1 && or2_2))
return true;
if (or1_1 || or1_2)
return false;
return intersects(vertical(rect1), vertical(rect2), false) ||
intersects(horizontal(rect1), horizontal(rect2), false);
}
struct y_s_e_dist : gtl_yes {};
template <typename Segment, typename Point>
typename enable_if<
typename gtl_and_3<
y_s_e_dist,
typename is_segment_concept<
typename geometry_concept<Segment>::type
>::type,
typename is_point_concept<
typename geometry_concept<Point>::type
>::type
>::type,
typename segment_distance_type<Segment>::type>::type
euclidean_distance(const Segment& segment, const Point& point) {
typedef typename segment_distance_type<Segment>::type Unit;
Unit x1 = x(low(segment));
Unit y1 = y(low(segment));
Unit x2 = x(high(segment));
Unit y2 = y(high(segment));
Unit X = x(point);
Unit Y = y(point);
Unit A = X - x1;
Unit B = Y - y1;
Unit C = x2 - x1;
Unit D = y2 - y1;
Unit param = (A * C + B * D);
Unit length_sq = C * C + D * D;
if (param > length_sq) {
return euclidean_distance(high(segment), point);
} else if (param < 0.0) {
return euclidean_distance(low(segment), point);
}
if (length_sq == 0.0)
return 0.0;
Unit denom = std::sqrt(length_sq);
Unit result = (A * D - C * B) / denom;
return (result < 0.0) ? -result : result;
}
struct y_s_e_dist2 : gtl_yes {};
template <typename Segment1, typename Segment2>
typename enable_if<
typename gtl_and_3<
y_s_e_dist2,
typename is_segment_concept<
typename geometry_concept<Segment1>::type
>::type,
typename is_segment_concept<
typename geometry_concept<Segment2>::type
>::type
>::type,
typename segment_distance_type<Segment1>::type>::type
euclidean_distance(const Segment1& segment1, const Segment2& segment2) {
if (intersects(segment1, segment2))
return 0.0;
typename segment_distance_type<Segment1>::type
result1 = euclidean_distance(segment1, low(segment2)),
result2 = euclidean_distance(segment1, high(segment2)),
result3 = euclidean_distance(segment2, low(segment1)),
result4 = euclidean_distance(segment2, high(segment1));
if (result2 < result1)
result1 = result2;
if (result4 < result3)
result3 = result4;
return (result1 < result3) ? result1 : result3;
}
} // polygon
} // boost
#endif // BOOST_POLYGON_SEGMENT_CONCEPT_HPP

View file

@ -0,0 +1,121 @@
// Boost.Polygon library segment_data.hpp header file
// Copyright (c) Intel Corporation 2008.
// Copyright (c) 2008-2012 Simonson Lucanus.
// Copyright (c) 2012-2012 Andrii Sydorchuk.
// See http://www.boost.org for updates, documentation, and revision history.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_POLYGON_SEGMENT_DATA_HPP
#define BOOST_POLYGON_SEGMENT_DATA_HPP
#include "isotropy.hpp"
#include "segment_concept.hpp"
namespace boost {
namespace polygon {
template <typename T>
class segment_data {
public:
typedef T coordinate_type;
typedef point_data<T> point_type;
segment_data()
#ifndef BOOST_POLYGON_MSVC
: points_()
#endif
{}
segment_data(const point_type& low, const point_type& high) {
points_[LOW] = low;
points_[HIGH] = high;
}
segment_data(const segment_data& that) {
points_[0] = that.points_[0];
points_[1] = that.points_[1];
}
segment_data& operator=(const segment_data& that) {
points_[0] = that.points_[0];
points_[1] = that.points_[1];
return *this;
}
template <typename SegmentType>
segment_data& operator=(const SegmentType& that) {
assign(*this, that);
return *this;
}
point_type get(direction_1d dir) const {
return points_[dir.to_int()];
}
void set(direction_1d dir, const point_type& point) {
points_[dir.to_int()] = point;
}
point_type low() const {
return points_[LOW];
}
segment_data& low(const point_type& point) {
points_[LOW] = point;
return *this;
}
point_type high() const {
return points_[HIGH];
}
segment_data& high(const point_type& point) {
points_[HIGH] = point;
return *this;
}
bool operator==(const segment_data& that) const {
return (points_[0] == that.points_[0]) &&
(points_[1] == that.points_[1]);
}
bool operator!=(const segment_data& that) const {
return (points_[0] != that.points_[0]) ||
(points_[1] != that.points_[1]);
}
bool operator<(const segment_data& that) const {
if (points_[0] != that.points_[0]) {
points_[0] < that.points_[0];
}
return points_[1] < that.points_[1];
}
bool operator<=(const segment_data& that) const {
return !(that < *this);
}
bool operator>(const segment_data& that) const {
return that < *this;
}
bool operator>=(const segment_data& that) const {
return !((*this) < that);
}
private:
point_type points_[2];
};
template <typename CType>
struct geometry_concept<segment_data<CType> > {
typedef segment_concept type;
};
} // polygon
} // boost
#endif // BOOST_POLYGON_SEGMENT_DATA_HPP

View file

@ -0,0 +1,50 @@
// Boost.Polygon library segment_traits.hpp header file
// Copyright (c) Intel Corporation 2008.
// Copyright (c) 2008-2012 Simonson Lucanus.
// Copyright (c) 2012-2012 Andrii Sydorchuk.
// See http://www.boost.org for updates, documentation, and revision history.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_POLYGON_SEGMENT_TRAITS_HPP
#define BOOST_POLYGON_SEGMENT_TRAITS_HPP
#include "isotropy.hpp"
namespace boost {
namespace polygon {
template <typename Segment>
struct segment_traits {
typedef Segment segment_type;
typedef typename segment_type::point_type point_type;
typedef typename segment_type::coordinate_type coordinate_type;
static point_type get(
const segment_type& segment, direction_1d dir) {
return segment.get(dir);
}
};
template <typename Segment>
struct segment_mutable_traits {
typedef Segment segment_type;
typedef typename segment_type::point_type point_type;
typedef typename segment_type::coordinate_type coordinate_type;
static void set(
segment_type& segment, direction_1d dir, const point_type& point) {
segment.set(dir, point);
}
static segment_type construct(const point_type& low, const point_type& high) {
return segment_type(low, high);
}
};
} // polygon
} // boost
#endif // BOOST_POLYGON_SEGMENT_TRAITS_HPP

View file

@ -0,0 +1,159 @@
/*
Copyright 2012 Lucanus Simonson
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_SEGMENT_UTILS_HPP
#define BOOST_POLYGON_SEGMENT_UTILS_HPP
#include <set>
#include <vector>
#include <utility>
namespace boost {
namespace polygon {
template <typename Segment, typename SegmentIterator>
typename enable_if<
typename gtl_and<
typename gtl_if<
typename is_segment_concept<
typename geometry_concept<
typename std::iterator_traits<SegmentIterator>::value_type
>::type
>::type
>::type,
typename gtl_if<
typename is_segment_concept<
typename geometry_concept<Segment>::type
>::type
>::type
>::type,
void
>::type
intersect_segments(
std::vector<std::pair<std::size_t, Segment> >& result,
SegmentIterator first, SegmentIterator last) {
typedef typename segment_traits<Segment>::coordinate_type Unit;
typedef typename scanline_base<Unit>::Point Point;
typedef typename scanline_base<Unit>::half_edge half_edge;
typedef int segment_id;
std::vector<std::pair<half_edge, segment_id> > half_edges;
std::vector<std::pair<half_edge, segment_id> > half_edges_out;
segment_id id_in = 0;
half_edges.reserve(std::distance(first, last));
for (; first != last; ++first) {
Point l, h;
assign(l, low(*first));
assign(h, high(*first));
half_edges.push_back(std::make_pair(half_edge(l, h), id_in++));
}
half_edges_out.reserve(half_edges.size());
// Apparently no need to pre-sort data when calling validate_scan.
if (half_edges.size() != 0) {
line_intersection<Unit>::validate_scan(
half_edges_out, half_edges.begin(), half_edges.end());
}
result.reserve(result.size() + half_edges_out.size());
for (std::size_t i = 0; i < half_edges_out.size(); ++i) {
std::size_t id = (std::size_t)(half_edges_out[i].second);
Point l = half_edges_out[i].first.first;
Point h = half_edges_out[i].first.second;
result.push_back(std::make_pair(id, construct<Segment>(l, h)));
}
}
template <typename SegmentContainer, typename SegmentIterator>
typename enable_if<
typename gtl_and<
typename gtl_if<
typename is_segment_concept<
typename geometry_concept<
typename std::iterator_traits<SegmentIterator>::value_type
>::type
>::type
>::type,
typename gtl_if<
typename is_segment_concept<
typename geometry_concept<
typename SegmentContainer::value_type
>::type
>::type
>::type
>::type,
void
>::type
intersect_segments(
SegmentContainer& result,
SegmentIterator first,
SegmentIterator last) {
typedef typename SegmentContainer::value_type segment_type;
typedef typename segment_traits<segment_type>::coordinate_type Unit;
typedef typename scanline_base<Unit>::Point Point;
typedef typename scanline_base<Unit>::half_edge half_edge;
typedef int segment_id;
std::vector<std::pair<half_edge, segment_id> > half_edges;
std::vector<std::pair<half_edge, segment_id> > half_edges_out;
segment_id id_in = 0;
half_edges.reserve(std::distance(first, last));
for (; first != last; ++first) {
Point l, h;
assign(l, low(*first));
assign(h, high(*first));
half_edges.push_back(std::make_pair(half_edge(l, h), id_in++));
}
half_edges_out.reserve(half_edges.size());
// Apparently no need to pre-sort data when calling validate_scan.
if (half_edges.size() != 0) {
line_intersection<Unit>::validate_scan(
half_edges_out, half_edges.begin(), half_edges.end());
}
result.reserve(result.size() + half_edges_out.size());
for (std::size_t i = 0; i < half_edges_out.size(); ++i) {
Point l = half_edges_out[i].first.first;
Point h = half_edges_out[i].first.second;
result.push_back(construct<segment_type>(l, h));
}
}
template <typename Rectangle, typename SegmentIterator>
typename enable_if<
typename gtl_and<
typename gtl_if<
typename is_rectangle_concept<
typename geometry_concept<Rectangle>::type
>::type
>::type,
typename gtl_if<
typename is_segment_concept<
typename geometry_concept<
typename std::iterator_traits<SegmentIterator>::value_type
>::type
>::type
>::type
>::type,
bool
>::type
envelope_segments(
Rectangle& rect,
SegmentIterator first,
SegmentIterator last) {
for (SegmentIterator it = first; it != last; ++it) {
if (it == first) {
set_points(rect, low(*it), high(*it));
} else {
encompass(rect, low(*it));
encompass(rect, high(*it));
}
}
return first != last;
}
} // polygon
} // boost
#endif // BOOST_POLYGON_SEGMENT_UTILS_HPP

View file

@ -0,0 +1,466 @@
// Boost.Polygon library point_data.hpp header file
// Copyright (c) Intel Corporation 2008.
// Copyright (c) 2008-2012 Simonson Lucanus.
// Copyright (c) 2012-2012 Andrii Sydorchuk.
// See http://www.boost.org for updates, documentation, and revision history.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_POLYGON_TRANSFORM_HPP
#define BOOST_POLYGON_TRANSFORM_HPP
#include "isotropy.hpp"
namespace boost {
namespace polygon {
// Transformation of Coordinate System.
// Enum meaning:
// Select which direction_2d to change the positive direction of each
// axis in the old coordinate system to map it to the new coordiante system.
// The first direction_2d listed for each enum is the direction to map the
// positive horizontal direction to.
// The second direction_2d listed for each enum is the direction to map the
// positive vertical direction to.
// The zero position bit (LSB) indicates whether the horizontal axis flips
// when transformed.
// The 1st postion bit indicates whether the vertical axis flips when
// transformed.
// The 2nd position bit indicates whether the horizontal and vertical axis
// swap positions when transformed.
// Enum Values:
// 000 EAST NORTH
// 001 WEST NORTH
// 010 EAST SOUTH
// 011 WEST SOUTH
// 100 NORTH EAST
// 101 SOUTH EAST
// 110 NORTH WEST
// 111 SOUTH WEST
class axis_transformation {
public:
enum ATR {
NULL_TRANSFORM = 0,
BEGIN_TRANSFORM = 0,
EN = 0, EAST_NORTH = 0,
WN = 1, WEST_NORTH = 1, FLIP_X = 1,
ES = 2, EAST_SOUTH = 2, FLIP_Y = 2,
WS = 3, WEST_SOUTH = 3, FLIP_XY = 3,
NE = 4, NORTH_EAST = 4, SWAP_XY = 4,
SE = 5, SOUTH_EAST = 5, ROTATE_LEFT = 5,
NW = 6, NORTH_WEST = 6, ROTATE_RIGHT = 6,
SW = 7, SOUTH_WEST = 7, FLIP_SWAP_XY = 7,
END_TRANSFORM = 7
};
// Individual axis enum values indicate which axis an implicit individual
// axis will be mapped to.
// The value of the enum paired with an axis provides the information
// about what the axis will transform to.
// Three individual axis values, one for each axis, are equivalent to one
// ATR enum value, but easier to work with because they are independent.
// Converting to and from the individual axis values from the ATR value
// is a convenient way to implement tranformation related functionality.
// Enum meanings:
// PX: map to positive x axis
// NX: map to negative x axis
// PY: map to positive y axis
// NY: map to negative y axis
enum INDIVIDUAL_AXIS {
PX = 0,
NX = 1,
PY = 2,
NY = 3
};
axis_transformation() : atr_(NULL_TRANSFORM) {}
explicit axis_transformation(ATR atr) : atr_(atr) {}
axis_transformation(const axis_transformation& atr) : atr_(atr.atr_) {}
explicit axis_transformation(const orientation_2d& orient) {
const ATR tmp[2] = {
NORTH_EAST, // sort x, then y
EAST_NORTH // sort y, then x
};
atr_ = tmp[orient.to_int()];
}
explicit axis_transformation(const direction_2d& dir) {
const ATR tmp[4] = {
SOUTH_EAST, // sort x, then y
NORTH_EAST, // sort x, then y
EAST_SOUTH, // sort y, then x
EAST_NORTH // sort y, then x
};
atr_ = tmp[dir.to_int()];
}
// assignment operator
axis_transformation& operator=(const axis_transformation& a) {
atr_ = a.atr_;
return *this;
}
// assignment operator
axis_transformation& operator=(const ATR& atr) {
atr_ = atr;
return *this;
}
// equivalence operator
bool operator==(const axis_transformation& a) const {
return atr_ == a.atr_;
}
// inequivalence operator
bool operator!=(const axis_transformation& a) const {
return !(*this == a);
}
// ordering
bool operator<(const axis_transformation& a) const {
return atr_ < a.atr_;
}
// concatenate this with that
axis_transformation& operator+=(const axis_transformation& a) {
bool abit2 = (a.atr_ & 4) != 0;
bool abit1 = (a.atr_ & 2) != 0;
bool abit0 = (a.atr_ & 1) != 0;
bool bit2 = (atr_ & 4) != 0;
bool bit1 = (atr_ & 2) != 0;
bool bit0 = (atr_ & 1) != 0;
int indexes[2][2] = {
{ (int)bit2, (int)(!bit2) },
{ (int)abit2, (int)(!abit2) }
};
int zero_bits[2][2] = {
{bit0, bit1}, {abit0, abit1}
};
int nbit1 = zero_bits[0][1] ^ zero_bits[1][indexes[0][1]];
int nbit0 = zero_bits[0][0] ^ zero_bits[1][indexes[0][0]];
indexes[0][0] = indexes[1][indexes[0][0]];
indexes[0][1] = indexes[1][indexes[0][1]];
int nbit2 = indexes[0][0] & 1; // swap xy
atr_ = (ATR)((nbit2 << 2) + (nbit1 << 1) + nbit0);
return *this;
}
// concatenation operator
axis_transformation operator+(const axis_transformation& a) const {
axis_transformation retval(*this);
return retval+=a;
}
// populate_axis_array writes the three INDIVIDUAL_AXIS values that the
// ATR enum value of 'this' represent into axis_array
void populate_axis_array(INDIVIDUAL_AXIS axis_array[]) const {
bool bit2 = (atr_ & 4) != 0;
bool bit1 = (atr_ & 2) != 0;
bool bit0 = (atr_ & 1) != 0;
axis_array[1] = (INDIVIDUAL_AXIS)(((int)(!bit2) << 1) + bit1);
axis_array[0] = (INDIVIDUAL_AXIS)(((int)(bit2) << 1) + bit0);
}
// it is recommended that the directions stored in an array
// in the caller code for easier isotropic access by orientation value
void get_directions(direction_2d& horizontal_dir,
direction_2d& vertical_dir) const {
bool bit2 = (atr_ & 4) != 0;
bool bit1 = (atr_ & 2) != 0;
bool bit0 = (atr_ & 1) != 0;
vertical_dir = direction_2d((direction_2d_enum)(((int)(!bit2) << 1) + !bit1));
horizontal_dir = direction_2d((direction_2d_enum)(((int)(bit2) << 1) + !bit0));
}
// combine_axis_arrays concatenates this_array and that_array overwriting
// the result into this_array
static void combine_axis_arrays(INDIVIDUAL_AXIS this_array[],
const INDIVIDUAL_AXIS that_array[]) {
int indexes[2] = { this_array[0] >> 1, this_array[1] >> 1 };
int zero_bits[2][2] = {
{ this_array[0] & 1, this_array[1] & 1 },
{ that_array[0] & 1, that_array[1] & 1 }
};
this_array[0] = (INDIVIDUAL_AXIS)((int)this_array[0] |
((int)zero_bits[0][0] ^
(int)zero_bits[1][indexes[0]]));
this_array[1] = (INDIVIDUAL_AXIS)((int)this_array[1] |
((int)zero_bits[0][1] ^
(int)zero_bits[1][indexes[1]]));
}
// write_back_axis_array converts an array of three INDIVIDUAL_AXIS values
// to the ATR enum value and sets 'this' to that value
void write_back_axis_array(const INDIVIDUAL_AXIS this_array[]) {
int bit2 = ((int)this_array[0] & 2) != 0; // swap xy
int bit1 = ((int)this_array[1] & 1);
int bit0 = ((int)this_array[0] & 1);
atr_ = ATR((bit2 << 2) + (bit1 << 1) + bit0);
}
// behavior is deterministic but undefined in the case where illegal
// combinations of directions are passed in.
axis_transformation& set_directions(const direction_2d& horizontal_dir,
const direction_2d& vertical_dir) {
int bit2 = (static_cast<orientation_2d>(horizontal_dir).to_int()) != 0;
int bit1 = !(vertical_dir.to_int() & 1);
int bit0 = !(horizontal_dir.to_int() & 1);
atr_ = ATR((bit2 << 2) + (bit1 << 1) + bit0);
return *this;
}
// transform the three coordinates by reference
template <typename coordinate_type>
void transform(coordinate_type& x, coordinate_type& y) const {
int bit2 = (atr_ & 4) != 0;
int bit1 = (atr_ & 2) != 0;
int bit0 = (atr_ & 1) != 0;
x *= -((bit0 << 1) - 1);
y *= -((bit1 << 1) - 1);
predicated_swap(bit2 != 0, x, y);
}
// invert this axis_transformation
axis_transformation& invert() {
int bit2 = ((atr_ & 4) != 0);
int bit1 = ((atr_ & 2) != 0);
int bit0 = ((atr_ & 1) != 0);
// swap bit 0 and bit 1 if bit2 is 1
predicated_swap(bit2 != 0, bit0, bit1);
bit1 = bit1 << 1;
atr_ = (ATR)(atr_ & (32+16+8+4)); // mask away bit0 and bit1
atr_ = (ATR)(atr_ | bit0 | bit1);
return *this;
}
// get the inverse axis_transformation of this
axis_transformation inverse() const {
axis_transformation retval(*this);
return retval.invert();
}
private:
ATR atr_;
};
// Scaling object to be used to store the scale factor for each axis.
// For use by the transformation object, in that context the scale factor
// is the amount that each axis scales by when transformed.
template <typename scale_factor_type>
class anisotropic_scale_factor {
public:
anisotropic_scale_factor() {
scale_[0] = 1;
scale_[1] = 1;
}
anisotropic_scale_factor(scale_factor_type xscale,
scale_factor_type yscale) {
scale_[0] = xscale;
scale_[1] = yscale;
}
// get a component of the anisotropic_scale_factor by orientation
scale_factor_type get(orientation_2d orient) const {
return scale_[orient.to_int()];
}
// set a component of the anisotropic_scale_factor by orientation
void set(orientation_2d orient, scale_factor_type value) {
scale_[orient.to_int()] = value;
}
scale_factor_type x() const {
return scale_[HORIZONTAL];
}
scale_factor_type y() const {
return scale_[VERTICAL];
}
void x(scale_factor_type value) {
scale_[HORIZONTAL] = value;
}
void y(scale_factor_type value) {
scale_[VERTICAL] = value;
}
// concatination operator (convolve scale factors)
anisotropic_scale_factor operator+(const anisotropic_scale_factor& s) const {
anisotropic_scale_factor<scale_factor_type> retval(*this);
return retval += s;
}
// concatinate this with that
const anisotropic_scale_factor& operator+=(
const anisotropic_scale_factor& s) {
scale_[0] *= s.scale_[0];
scale_[1] *= s.scale_[1];
return *this;
}
// transform this scale with an axis_transform
anisotropic_scale_factor& transform(axis_transformation atr) {
direction_2d dirs[2];
atr.get_directions(dirs[0], dirs[1]);
scale_factor_type tmp[2] = {scale_[0], scale_[1]};
for (int i = 0; i < 2; ++i) {
scale_[orientation_2d(dirs[i]).to_int()] = tmp[i];
}
return *this;
}
// scale the two coordinates
template <typename coordinate_type>
void scale(coordinate_type& x, coordinate_type& y) const {
x = scaling_policy<coordinate_type>::round(
(scale_factor_type)x * get(HORIZONTAL));
y = scaling_policy<coordinate_type>::round(
(scale_factor_type)y * get(HORIZONTAL));
}
// invert this scale factor to give the reverse scale factor
anisotropic_scale_factor& invert() {
x(1/x());
y(1/y());
return *this;
}
private:
scale_factor_type scale_[2];
};
// Transformation object, stores and provides services for transformations.
// Consits of axis transformation, scale factor and translation.
// The tranlation is the position of the origin of the new coordinate system of
// in the old system. Coordinates are scaled before they are transformed.
template <typename coordinate_type>
class transformation {
public:
transformation() : atr_(), p_(0, 0) {}
explicit transformation(axis_transformation atr) : atr_(atr), p_(0, 0) {}
explicit transformation(axis_transformation::ATR atr) : atr_(atr), p_(0, 0) {}
transformation(const transformation& tr) : atr_(tr.atr_), p_(tr.p_) {}
template <typename point_type>
explicit transformation(const point_type& p) : atr_(), p_(0, 0) {
set_translation(p);
}
template <typename point_type>
transformation(axis_transformation atr,
const point_type& p) : atr_(atr), p_(0, 0) {
set_translation(p);
}
template <typename point_type>
transformation(axis_transformation atr,
const point_type& referencePt,
const point_type& destinationPt) : atr_(), p_(0, 0) {
transformation<coordinate_type> tmp(referencePt);
transformation<coordinate_type> rotRef(atr);
transformation<coordinate_type> tmpInverse = tmp.inverse();
point_type decon(referencePt);
deconvolve(decon, destinationPt);
transformation<coordinate_type> displacement(decon);
tmp += rotRef;
tmp += tmpInverse;
tmp += displacement;
(*this) = tmp;
}
// equivalence operator
bool operator==(const transformation& tr) const {
return (atr_ == tr.atr_) && (p_ == tr.p_);
}
// inequivalence operator
bool operator!=(const transformation& tr) const {
return !(*this == tr);
}
// ordering
bool operator<(const transformation& tr) const {
return (atr_ < tr.atr_) || ((atr_ == tr.atr_) && (p_ < tr.p_));
}
// concatenation operator
transformation operator+(const transformation& tr) const {
transformation<coordinate_type> retval(*this);
return retval+=tr;
}
// concatenate this with that
const transformation& operator+=(const transformation& tr) {
coordinate_type x, y;
transformation<coordinate_type> inv = inverse();
inv.transform(x, y);
p_.set(HORIZONTAL, p_.get(HORIZONTAL) + x);
p_.set(VERTICAL, p_.get(VERTICAL) + y);
// concatenate axis transforms
atr_ += tr.atr_;
return *this;
}
// get the axis_transformation portion of this
axis_transformation get_axis_transformation() const {
return atr_;
}
// set the axis_transformation portion of this
void set_axis_transformation(const axis_transformation& atr) {
atr_ = atr;
}
// get the translation
template <typename point_type>
void get_translation(point_type& p) const {
assign(p, p_);
}
// set the translation
template <typename point_type>
void set_translation(const point_type& p) {
assign(p_, p);
}
// apply the 2D portion of this transformation to the two coordinates given
void transform(coordinate_type& x, coordinate_type& y) const {
y -= p_.get(VERTICAL);
x -= p_.get(HORIZONTAL);
atr_.transform(x, y);
}
// invert this transformation
transformation& invert() {
coordinate_type x = p_.get(HORIZONTAL), y = p_.get(VERTICAL);
atr_.transform(x, y);
x *= -1;
y *= -1;
p_ = point_data<coordinate_type>(x, y);
atr_.invert();
return *this;
}
// get the inverse of this transformation
transformation inverse() const {
transformation<coordinate_type> ret_val(*this);
return ret_val.invert();
}
void get_directions(direction_2d& horizontal_dir,
direction_2d& vertical_dir) const {
return atr_.get_directions(horizontal_dir, vertical_dir);
}
private:
axis_transformation atr_;
point_data<coordinate_type> p_;
};
} // polygon
} // boost
#endif // BOOST_POLYGON_TRANSFORM_HPP

View file

@ -0,0 +1,157 @@
// Boost.Polygon library voronoi.hpp header file
// Copyright Andrii Sydorchuk 2010-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POLYGON_VORONOI
#define BOOST_POLYGON_VORONOI
#include "isotropy.hpp"
#include "point_concept.hpp"
#include "segment_concept.hpp"
#include "voronoi_builder.hpp"
#include "voronoi_diagram.hpp"
// Public methods to compute Voronoi diagram of a set of points and segments.
// Coordinates of the points and of the endpoints of the segments should belong
// to the 32-bit signed integer range [-2^31, 2^31-1]. To use wider input
// coordinate range voronoi_builder configuration via coordinate type traits
// is required.
// Complexity - O(N*logN), memory usage - O(N), N - number of input objects.
namespace boost {
namespace polygon {
template <typename Point, typename VB>
typename enable_if<
typename gtl_if<
typename is_point_concept<
typename geometry_concept<Point>::type
>::type
>::type,
std::size_t
>::type insert(const Point& point, VB* vb) {
return vb->insert_point(x(point), y(point));
}
template <typename PointIterator, typename VB>
typename enable_if<
typename gtl_if<
typename is_point_concept<
typename geometry_concept<
typename std::iterator_traits<PointIterator>::value_type
>::type
>::type
>::type,
void
>::type insert(const PointIterator first, const PointIterator last, VB* vb) {
for (PointIterator it = first; it != last; ++it) {
insert(*it, vb);
}
}
template <typename Segment, typename VB>
typename enable_if<
typename gtl_if<
typename is_segment_concept<
typename geometry_concept<Segment>::type
>::type
>::type,
std::size_t
>::type insert(const Segment& segment, VB* vb) {
return vb->insert_segment(
x(low(segment)), y(low(segment)),
x(high(segment)), y(high(segment)));
}
template <typename SegmentIterator, typename VB>
typename enable_if<
typename gtl_if<
typename is_segment_concept<
typename geometry_concept<
typename std::iterator_traits<SegmentIterator>::value_type
>::type
>::type
>::type,
void
>::type insert(const SegmentIterator first,
const SegmentIterator last,
VB* vb) {
for (SegmentIterator it = first; it != last; ++it) {
insert(*it, vb);
}
}
template <typename PointIterator, typename VD>
typename enable_if<
typename gtl_if<
typename is_point_concept<
typename geometry_concept<
typename std::iterator_traits<PointIterator>::value_type
>::type
>::type
>::type,
void
>::type construct_voronoi(const PointIterator first,
const PointIterator last,
VD* vd) {
default_voronoi_builder builder;
insert(first, last, &builder);
builder.construct(vd);
}
template <typename SegmentIterator, typename VD>
typename enable_if<
typename gtl_if<
typename is_segment_concept<
typename geometry_concept<
typename std::iterator_traits<SegmentIterator>::value_type
>::type
>::type
>::type,
void
>::type construct_voronoi(const SegmentIterator first,
const SegmentIterator last,
VD* vd) {
default_voronoi_builder builder;
insert(first, last, &builder);
builder.construct(vd);
}
template <typename PointIterator, typename SegmentIterator, typename VD>
typename enable_if<
typename gtl_and<
typename gtl_if<
typename is_point_concept<
typename geometry_concept<
typename std::iterator_traits<PointIterator>::value_type
>::type
>::type
>::type,
typename gtl_if<
typename is_segment_concept<
typename geometry_concept<
typename std::iterator_traits<SegmentIterator>::value_type
>::type
>::type
>::type
>::type,
void
>::type construct_voronoi(const PointIterator p_first,
const PointIterator p_last,
const SegmentIterator s_first,
const SegmentIterator s_last,
VD* vd) {
default_voronoi_builder builder;
insert(p_first, p_last, &builder);
insert(s_first, s_last, &builder);
builder.construct(vd);
}
} // polygon
} // boost
#endif // BOOST_POLYGON_VORONOI

View file

@ -0,0 +1,517 @@
// Boost.Polygon library voronoi_builder.hpp header file
// Copyright Andrii Sydorchuk 2010-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POLYGON_VORONOI_BUILDER
#define BOOST_POLYGON_VORONOI_BUILDER
#include <algorithm>
#include <map>
#include <queue>
#include <utility>
#include <vector>
#include "detail/voronoi_ctypes.hpp"
#include "detail/voronoi_predicates.hpp"
#include "detail/voronoi_structures.hpp"
#include "voronoi_geometry_type.hpp"
namespace boost {
namespace polygon {
// GENERAL INFO:
// The sweepline algorithm implementation to compute Voronoi diagram of
// points and non-intersecting segments (except endpoints).
// Complexity - O(N*logN), memory usage - O(N), where N is the total number
// of input geometries. Input geometries should have integer coordinate type.
//
// IMPLEMENTATION DETAILS:
// Each input point creates one site event. Each input segment creates three
// site events: two for its endpoints and one for the segment itself (this is
// made to simplify output construction). All the site events are constructed
// and sorted at the algorithm initialization step. Priority queue is used to
// dynamically hold circle events. At each step of the algorithm execution the
// leftmost event is retrieved by comparing the current site event and the
// topmost element from the circle event queue. STL map (red-black tree)
// container was chosen to hold state of the beach line. The keys of the map
// correspond to the neighboring sites that form a bisector and values map to
// the corresponding Voronoi edges in the output data structure.
template <typename T,
typename CTT = detail::voronoi_ctype_traits<T>,
typename VP = detail::voronoi_predicates<CTT> >
class voronoi_builder {
public:
typedef typename CTT::int_type int_type;
typedef typename CTT::fpt_type fpt_type;
voronoi_builder() : index_(0) {}
// Each point creates a single site event.
std::size_t insert_point(const int_type& x, const int_type& y) {
site_events_.push_back(site_event_type(x, y));
site_events_.back().initial_index(index_);
site_events_.back().source_category(SOURCE_CATEGORY_SINGLE_POINT);
return index_++;
}
// Each segment creates three site events that correspond to:
// 1) the start point of the segment;
// 2) the end point of the segment;
// 3) the segment itself defined by its start point.
std::size_t insert_segment(
const int_type& x1, const int_type& y1,
const int_type& x2, const int_type& y2) {
// Set up start point site.
point_type p1(x1, y1);
site_events_.push_back(site_event_type(p1));
site_events_.back().initial_index(index_);
site_events_.back().source_category(SOURCE_CATEGORY_SEGMENT_START_POINT);
// Set up end point site.
point_type p2(x2, y2);
site_events_.push_back(site_event_type(p2));
site_events_.back().initial_index(index_);
site_events_.back().source_category(SOURCE_CATEGORY_SEGMENT_END_POINT);
// Set up segment site.
if (point_comparison_(p1, p2)) {
site_events_.push_back(site_event_type(p1, p2));
site_events_.back().source_category(SOURCE_CATEGORY_INITIAL_SEGMENT);
} else {
site_events_.push_back(site_event_type(p2, p1));
site_events_.back().source_category(SOURCE_CATEGORY_REVERSE_SEGMENT);
}
site_events_.back().initial_index(index_);
return index_++;
}
// Run sweepline algorithm and fill output data structure.
template <typename OUTPUT>
void construct(OUTPUT* output) {
// Init structures.
output->_reserve(site_events_.size());
init_sites_queue();
init_beach_line(output);
// The algorithm stops when there are no events to process.
event_comparison_predicate event_comparison;
while (!circle_events_.empty() ||
!(site_event_iterator_ == site_events_.end())) {
if (circle_events_.empty()) {
process_site_event(output);
} else if (site_event_iterator_ == site_events_.end()) {
process_circle_event(output);
} else {
if (event_comparison(*site_event_iterator_,
circle_events_.top().first)) {
process_site_event(output);
} else {
process_circle_event(output);
}
}
while (!circle_events_.empty() &&
!circle_events_.top().first.is_active()) {
circle_events_.pop();
}
}
beach_line_.clear();
// Finish construction.
output->_build();
}
void clear() {
index_ = 0;
site_events_.clear();
}
private:
typedef detail::point_2d<int_type> point_type;
typedef detail::site_event<int_type> site_event_type;
typedef typename std::vector<site_event_type>::const_iterator
site_event_iterator_type;
typedef detail::circle_event<fpt_type> circle_event_type;
typedef typename VP::template point_comparison_predicate<point_type>
point_comparison_predicate;
typedef typename VP::
template event_comparison_predicate<site_event_type, circle_event_type>
event_comparison_predicate;
typedef typename VP::
template circle_formation_predicate<site_event_type, circle_event_type>
circle_formation_predicate_type;
typedef void edge_type;
typedef detail::beach_line_node_key<site_event_type> key_type;
typedef detail::beach_line_node_data<edge_type, circle_event_type>
value_type;
typedef typename VP::template node_comparison_predicate<key_type>
node_comparer_type;
typedef std::map< key_type, value_type, node_comparer_type > beach_line_type;
typedef typename beach_line_type::iterator beach_line_iterator;
typedef std::pair<circle_event_type, beach_line_iterator> event_type;
typedef struct {
bool operator()(const event_type& lhs, const event_type& rhs) const {
return predicate(rhs.first, lhs.first);
}
event_comparison_predicate predicate;
} event_comparison_type;
typedef detail::ordered_queue<event_type, event_comparison_type>
circle_event_queue_type;
typedef std::pair<point_type, beach_line_iterator> end_point_type;
void init_sites_queue() {
// Sort site events.
std::sort(site_events_.begin(), site_events_.end(),
event_comparison_predicate());
// Remove duplicates.
site_events_.erase(std::unique(
site_events_.begin(), site_events_.end()), site_events_.end());
// Index sites.
for (std::size_t cur = 0; cur < site_events_.size(); ++cur) {
site_events_[cur].sorted_index(cur);
}
// Init site iterator.
site_event_iterator_ = site_events_.begin();
}
template <typename OUTPUT>
void init_beach_line(OUTPUT* output) {
if (site_events_.empty())
return;
if (site_events_.size() == 1) {
// Handle single site event case.
output->_process_single_site(site_events_[0]);
++site_event_iterator_;
} else {
int skip = 0;
while (site_event_iterator_ != site_events_.end() &&
VP::is_vertical(site_event_iterator_->point0(),
site_events_.begin()->point0()) &&
VP::is_vertical(*site_event_iterator_)) {
++site_event_iterator_;
++skip;
}
if (skip == 1) {
// Init beach line with the first two sites.
init_beach_line_default(output);
} else {
// Init beach line with collinear vertical sites.
init_beach_line_collinear_sites(output);
}
}
}
// Init beach line with the two first sites.
// The first site is always a point.
template <typename OUTPUT>
void init_beach_line_default(OUTPUT* output) {
// Get the first and the second site event.
site_event_iterator_type it_first = site_events_.begin();
site_event_iterator_type it_second = site_events_.begin();
++it_second;
insert_new_arc(
*it_first, *it_first, *it_second, beach_line_.end(), output);
// The second site was already processed. Move the iterator.
++site_event_iterator_;
}
// Init beach line with collinear sites.
template <typename OUTPUT>
void init_beach_line_collinear_sites(OUTPUT* output) {
site_event_iterator_type it_first = site_events_.begin();
site_event_iterator_type it_second = site_events_.begin();
++it_second;
while (it_second != site_event_iterator_) {
// Create a new beach line node.
key_type new_node(*it_first, *it_second);
// Update the output.
edge_type* edge = output->_insert_new_edge(*it_first, *it_second).first;
// Insert a new bisector into the beach line.
beach_line_.insert(beach_line_.end(),
std::pair<key_type, value_type>(new_node, value_type(edge)));
// Update iterators.
++it_first;
++it_second;
}
}
void deactivate_circle_event(value_type* value) {
if (value->circle_event()) {
value->circle_event()->deactivate();
value->circle_event(NULL);
}
}
template <typename OUTPUT>
void process_site_event(OUTPUT* output) {
// Get next site event to process.
site_event_type site_event = *site_event_iterator_;
// Move site iterator.
site_event_iterator_type last = site_event_iterator_ + 1;
// If a new site is an end point of some segment,
// remove temporary nodes from the beach line data structure.
if (!site_event.is_segment()) {
while (!end_points_.empty() &&
end_points_.top().first == site_event.point0()) {
beach_line_iterator b_it = end_points_.top().second;
end_points_.pop();
beach_line_.erase(b_it);
}
} else {
while (last != site_events_.end() &&
last->is_segment() && last->point0() == site_event.point0())
++last;
}
// Find the node in the binary search tree with left arc
// lying above the new site point.
key_type new_key(*site_event_iterator_);
beach_line_iterator right_it = beach_line_.lower_bound(new_key);
for (; site_event_iterator_ != last; ++site_event_iterator_) {
site_event = *site_event_iterator_;
beach_line_iterator left_it = right_it;
// Do further processing depending on the above node position.
// For any two neighboring nodes the second site of the first node
// is the same as the first site of the second node.
if (right_it == beach_line_.end()) {
// The above arc corresponds to the second arc of the last node.
// Move the iterator to the last node.
--left_it;
// Get the second site of the last node
const site_event_type& site_arc = left_it->first.right_site();
// Insert new nodes into the beach line. Update the output.
right_it = insert_new_arc(
site_arc, site_arc, site_event, right_it, output);
// Add a candidate circle to the circle event queue.
// There could be only one new circle event formed by
// a new bisector and the one on the left.
activate_circle_event(left_it->first.left_site(),
left_it->first.right_site(),
site_event, right_it);
} else if (right_it == beach_line_.begin()) {
// The above arc corresponds to the first site of the first node.
const site_event_type& site_arc = right_it->first.left_site();
// Insert new nodes into the beach line. Update the output.
left_it = insert_new_arc(
site_arc, site_arc, site_event, right_it, output);
// If the site event is a segment, update its direction.
if (site_event.is_segment()) {
site_event.inverse();
}
// Add a candidate circle to the circle event queue.
// There could be only one new circle event formed by
// a new bisector and the one on the right.
activate_circle_event(site_event, right_it->first.left_site(),
right_it->first.right_site(), right_it);
right_it = left_it;
} else {
// The above arc corresponds neither to the first,
// nor to the last site in the beach line.
const site_event_type& site_arc2 = right_it->first.left_site();
const site_event_type& site3 = right_it->first.right_site();
// Remove the candidate circle from the event queue.
deactivate_circle_event(&right_it->second);
--left_it;
const site_event_type& site_arc1 = left_it->first.right_site();
const site_event_type& site1 = left_it->first.left_site();
// Insert new nodes into the beach line. Update the output.
beach_line_iterator new_node_it =
insert_new_arc(site_arc1, site_arc2, site_event, right_it, output);
// Add candidate circles to the circle event queue.
// There could be up to two circle events formed by
// a new bisector and the one on the left or right.
activate_circle_event(site1, site_arc1, site_event, new_node_it);
// If the site event is a segment, update its direction.
if (site_event.is_segment()) {
site_event.inverse();
}
activate_circle_event(site_event, site_arc2, site3, right_it);
right_it = new_node_it;
}
}
}
// In general case circle event is made of the three consecutive sites
// that form two bisectors in the beach line data structure.
// Let circle event sites be A, B, C, two bisectors that define
// circle event are (A, B), (B, C). During circle event processing
// we remove (A, B), (B, C) and insert (A, C). As beach line comparison
// works correctly only if one of the nodes is a new one we remove
// (B, C) bisector and change (A, B) bisector to the (A, C). That's
// why we use const_cast there and take all the responsibility that
// map data structure keeps correct ordering.
template <typename OUTPUT>
void process_circle_event(OUTPUT* output) {
// Get the topmost circle event.
const event_type& e = circle_events_.top();
const circle_event_type& circle_event = e.first;
beach_line_iterator it_first = e.second;
beach_line_iterator it_last = it_first;
// Get the C site.
site_event_type site3 = it_first->first.right_site();
// Get the half-edge corresponding to the second bisector - (B, C).
edge_type* bisector2 = it_first->second.edge();
// Get the half-edge corresponding to the first bisector - (A, B).
--it_first;
edge_type* bisector1 = it_first->second.edge();
// Get the A site.
site_event_type site1 = it_first->first.left_site();
if (!site1.is_segment() && site3.is_segment() &&
site3.point1() == site1.point0()) {
site3.inverse();
}
// Change the (A, B) bisector node to the (A, C) bisector node.
const_cast<key_type&>(it_first->first).right_site(site3);
// Insert the new bisector into the beach line.
it_first->second.edge(output->_insert_new_edge(
site1, site3, circle_event, bisector1, bisector2).first);
// Remove the (B, C) bisector node from the beach line.
beach_line_.erase(it_last);
it_last = it_first;
// Pop the topmost circle event from the event queue.
circle_events_.pop();
// Check new triplets formed by the neighboring arcs
// to the left for potential circle events.
if (it_first != beach_line_.begin()) {
deactivate_circle_event(&it_first->second);
--it_first;
const site_event_type& site_l1 = it_first->first.left_site();
activate_circle_event(site_l1, site1, site3, it_last);
}
// Check the new triplet formed by the neighboring arcs
// to the right for potential circle events.
++it_last;
if (it_last != beach_line_.end()) {
deactivate_circle_event(&it_last->second);
const site_event_type& site_r1 = it_last->first.right_site();
activate_circle_event(site1, site3, site_r1, it_last);
}
}
// Insert new nodes into the beach line. Update the output.
template <typename OUTPUT>
beach_line_iterator insert_new_arc(
const site_event_type& site_arc1, const site_event_type &site_arc2,
const site_event_type& site_event, beach_line_iterator position,
OUTPUT* output) {
// Create two new bisectors with opposite directions.
key_type new_left_node(site_arc1, site_event);
key_type new_right_node(site_event, site_arc2);
// Set correct orientation for the first site of the second node.
if (site_event.is_segment()) {
new_right_node.left_site().inverse();
}
// Update the output.
std::pair<edge_type*, edge_type*> edges =
output->_insert_new_edge(site_arc2, site_event);
position = beach_line_.insert(position,
typename beach_line_type::value_type(
new_right_node, value_type(edges.second)));
if (site_event.is_segment()) {
// Update the beach line with temporary bisector, that will
// disappear after processing site event corresponding to the
// second endpoint of the segment site.
key_type new_node(site_event, site_event);
new_node.right_site().inverse();
position = beach_line_.insert(position,
typename beach_line_type::value_type(new_node, value_type(NULL)));
// Update the data structure that holds temporary bisectors.
end_points_.push(std::make_pair(site_event.point1(), position));
}
position = beach_line_.insert(position,
typename beach_line_type::value_type(
new_left_node, value_type(edges.first)));
return position;
}
// Add a new circle event to the event queue.
// bisector_node corresponds to the (site2, site3) bisector.
void activate_circle_event(const site_event_type& site1,
const site_event_type& site2,
const site_event_type& site3,
beach_line_iterator bisector_node) {
circle_event_type c_event;
// Check if the three input sites create a circle event.
if (circle_formation_predicate_(site1, site2, site3, c_event)) {
// Add the new circle event to the circle events queue.
// Update bisector's circle event iterator to point to the
// new circle event in the circle event queue.
event_type& e = circle_events_.push(
std::pair<circle_event_type, beach_line_iterator>(
c_event, bisector_node));
bisector_node->second.circle_event(&e.first);
}
}
private:
point_comparison_predicate point_comparison_;
struct end_point_comparison {
bool operator() (const end_point_type& end1,
const end_point_type& end2) const {
return point_comparison(end2.first, end1.first);
}
point_comparison_predicate point_comparison;
};
std::vector<site_event_type> site_events_;
site_event_iterator_type site_event_iterator_;
std::priority_queue< end_point_type, std::vector<end_point_type>,
end_point_comparison > end_points_;
circle_event_queue_type circle_events_;
beach_line_type beach_line_;
circle_formation_predicate_type circle_formation_predicate_;
std::size_t index_;
// Disallow copy constructor and operator=
voronoi_builder(const voronoi_builder&);
void operator=(const voronoi_builder&);
};
typedef voronoi_builder<detail::int32> default_voronoi_builder;
} // polygon
} // boost
#endif // BOOST_POLYGON_VORONOI_BUILDER

View file

@ -0,0 +1,620 @@
// Boost.Polygon library voronoi_diagram.hpp header file
// Copyright Andrii Sydorchuk 2010-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POLYGON_VORONOI_DIAGRAM
#define BOOST_POLYGON_VORONOI_DIAGRAM
#include <vector>
#include <utility>
#include "detail/voronoi_ctypes.hpp"
#include "detail/voronoi_structures.hpp"
#include "voronoi_geometry_type.hpp"
namespace boost {
namespace polygon {
// Forward declarations.
template <typename T>
class voronoi_edge;
// Represents Voronoi cell.
// Data members:
// 1) index of the source within the initial input set
// 2) pointer to the incident edge
// 3) mutable color member
// Cell may contain point or segment site inside.
template <typename T>
class voronoi_cell {
public:
typedef T coordinate_type;
typedef std::size_t color_type;
typedef voronoi_edge<coordinate_type> voronoi_edge_type;
typedef std::size_t source_index_type;
typedef SourceCategory source_category_type;
voronoi_cell(source_index_type source_index,
source_category_type source_category) :
source_index_(source_index),
incident_edge_(NULL),
color_(source_category) {}
// Returns true if the cell contains point site, false else.
bool contains_point() const {
source_category_type source_category = this->source_category();
return belongs(source_category, GEOMETRY_CATEGORY_POINT);
}
// Returns true if the cell contains segment site, false else.
bool contains_segment() const {
source_category_type source_category = this->source_category();
return belongs(source_category, GEOMETRY_CATEGORY_SEGMENT);
}
source_index_type source_index() const {
return source_index_;
}
source_category_type source_category() const {
return static_cast<source_category_type>(color_ & SOURCE_CATEGORY_BITMASK);
}
// Degenerate cells don't have any incident edges.
bool is_degenerate() const { return incident_edge_ == NULL; }
voronoi_edge_type* incident_edge() { return incident_edge_; }
const voronoi_edge_type* incident_edge() const { return incident_edge_; }
void incident_edge(voronoi_edge_type* e) { incident_edge_ = e; }
color_type color() const { return color_ >> BITS_SHIFT; }
void color(color_type color) const {
color_ &= BITS_MASK;
color_ |= color << BITS_SHIFT;
}
private:
// 5 color bits are reserved.
enum Bits {
BITS_SHIFT = 0x5,
BITS_MASK = 0x1F
};
source_index_type source_index_;
voronoi_edge_type* incident_edge_;
mutable color_type color_;
};
// Represents Voronoi vertex.
// Data members:
// 1) vertex coordinates
// 2) pointer to the incident edge
// 3) mutable color member
template <typename T>
class voronoi_vertex {
public:
typedef T coordinate_type;
typedef std::size_t color_type;
typedef voronoi_edge<coordinate_type> voronoi_edge_type;
voronoi_vertex(const coordinate_type& x, const coordinate_type& y) :
x_(x),
y_(y),
incident_edge_(NULL),
color_(0) {}
const coordinate_type& x() const { return x_; }
const coordinate_type& y() const { return y_; }
bool is_degenerate() const { return incident_edge_ == NULL; }
voronoi_edge_type* incident_edge() { return incident_edge_; }
const voronoi_edge_type* incident_edge() const { return incident_edge_; }
void incident_edge(voronoi_edge_type* e) { incident_edge_ = e; }
color_type color() const { return color_ >> BITS_SHIFT; }
void color(color_type color) const {
color_ &= BITS_MASK;
color_ |= color << BITS_SHIFT;
}
private:
// 5 color bits are reserved.
enum Bits {
BITS_SHIFT = 0x5,
BITS_MASK = 0x1F
};
coordinate_type x_;
coordinate_type y_;
voronoi_edge_type* incident_edge_;
mutable color_type color_;
};
// Half-edge data structure. Represents Voronoi edge.
// Data members:
// 1) pointer to the corresponding cell
// 2) pointer to the vertex that is the starting
// point of the half-edge
// 3) pointer to the twin edge
// 4) pointer to the CCW next edge
// 5) pointer to the CCW prev edge
// 6) mutable color member
template <typename T>
class voronoi_edge {
public:
typedef T coordinate_type;
typedef voronoi_cell<coordinate_type> voronoi_cell_type;
typedef voronoi_vertex<coordinate_type> voronoi_vertex_type;
typedef voronoi_edge<coordinate_type> voronoi_edge_type;
typedef std::size_t color_type;
voronoi_edge(bool is_linear, bool is_primary) :
cell_(NULL),
vertex_(NULL),
twin_(NULL),
next_(NULL),
prev_(NULL),
color_(0) {
if (is_linear)
color_ |= BIT_IS_LINEAR;
if (is_primary)
color_ |= BIT_IS_PRIMARY;
}
voronoi_cell_type* cell() { return cell_; }
const voronoi_cell_type* cell() const { return cell_; }
void cell(voronoi_cell_type* c) { cell_ = c; }
voronoi_vertex_type* vertex0() { return vertex_; }
const voronoi_vertex_type* vertex0() const { return vertex_; }
void vertex0(voronoi_vertex_type* v) { vertex_ = v; }
voronoi_vertex_type* vertex1() { return twin_->vertex0(); }
const voronoi_vertex_type* vertex1() const { return twin_->vertex0(); }
voronoi_edge_type* twin() { return twin_; }
const voronoi_edge_type* twin() const { return twin_; }
void twin(voronoi_edge_type* e) { twin_ = e; }
voronoi_edge_type* next() { return next_; }
const voronoi_edge_type* next() const { return next_; }
void next(voronoi_edge_type* e) { next_ = e; }
voronoi_edge_type* prev() { return prev_; }
const voronoi_edge_type* prev() const { return prev_; }
void prev(voronoi_edge_type* e) { prev_ = e; }
// Returns a pointer to the rotation next edge
// over the starting point of the half-edge.
voronoi_edge_type* rot_next() { return prev_->twin(); }
const voronoi_edge_type* rot_next() const { return prev_->twin(); }
// Returns a pointer to the rotation prev edge
// over the starting point of the half-edge.
voronoi_edge_type* rot_prev() { return twin_->next(); }
const voronoi_edge_type* rot_prev() const { return twin_->next(); }
// Returns true if the edge is finite (segment, parabolic arc).
// Returns false if the edge is infinite (ray, line).
bool is_finite() const { return vertex0() && vertex1(); }
// Returns true if the edge is infinite (ray, line).
// Returns false if the edge is finite (segment, parabolic arc).
bool is_infinite() const { return !vertex0() || !vertex1(); }
// Returns true if the edge is linear (segment, ray, line).
// Returns false if the edge is curved (parabolic arc).
bool is_linear() const {
return (color_ & BIT_IS_LINEAR) ? true : false;
}
// Returns true if the edge is curved (parabolic arc).
// Returns false if the edge is linear (segment, ray, line).
bool is_curved() const {
return (color_ & BIT_IS_LINEAR) ? false : true;
}
// Returns false if edge goes through the endpoint of the segment.
// Returns true else.
bool is_primary() const {
return (color_ & BIT_IS_PRIMARY) ? true : false;
}
// Returns true if edge goes through the endpoint of the segment.
// Returns false else.
bool is_secondary() const {
return (color_ & BIT_IS_PRIMARY) ? false : true;
}
color_type color() const { return color_ >> BITS_SHIFT; }
void color(color_type color) const {
color_ &= BITS_MASK;
color_ |= color << BITS_SHIFT;
}
private:
// 5 color bits are reserved.
enum Bits {
BIT_IS_LINEAR = 0x1, // linear is opposite to curved
BIT_IS_PRIMARY = 0x2, // primary is opposite to secondary
BITS_SHIFT = 0x5,
BITS_MASK = 0x1F
};
voronoi_cell_type* cell_;
voronoi_vertex_type* vertex_;
voronoi_edge_type* twin_;
voronoi_edge_type* next_;
voronoi_edge_type* prev_;
mutable color_type color_;
};
template <typename T>
struct voronoi_diagram_traits {
typedef T coordinate_type;
typedef voronoi_cell<coordinate_type> cell_type;
typedef voronoi_vertex<coordinate_type> vertex_type;
typedef voronoi_edge<coordinate_type> edge_type;
typedef class {
public:
enum { ULPS = 128 };
bool operator()(const vertex_type& v1, const vertex_type& v2) const {
return (ulp_cmp(v1.x(), v2.x(), ULPS) ==
detail::ulp_comparison<T>::EQUAL) &&
(ulp_cmp(v1.y(), v2.y(), ULPS) ==
detail::ulp_comparison<T>::EQUAL);
}
private:
typename detail::ulp_comparison<T> ulp_cmp;
} vertex_equality_predicate_type;
};
// Voronoi output data structure.
// CCW ordering is used on the faces perimeter and around the vertices.
template <typename T, typename TRAITS = voronoi_diagram_traits<T> >
class voronoi_diagram {
public:
typedef typename TRAITS::coordinate_type coordinate_type;
typedef typename TRAITS::cell_type cell_type;
typedef typename TRAITS::vertex_type vertex_type;
typedef typename TRAITS::edge_type edge_type;
typedef std::vector<cell_type> cell_container_type;
typedef typename cell_container_type::const_iterator const_cell_iterator;
typedef std::vector<vertex_type> vertex_container_type;
typedef typename vertex_container_type::const_iterator const_vertex_iterator;
typedef std::vector<edge_type> edge_container_type;
typedef typename edge_container_type::const_iterator const_edge_iterator;
voronoi_diagram() {}
void clear() {
cells_.clear();
vertices_.clear();
edges_.clear();
}
const cell_container_type& cells() const {
return cells_;
}
const vertex_container_type& vertices() const {
return vertices_;
}
const edge_container_type& edges() const {
return edges_;
}
std::size_t num_cells() const {
return cells_.size();
}
std::size_t num_edges() const {
return edges_.size();
}
std::size_t num_vertices() const {
return vertices_.size();
}
void _reserve(std::size_t num_sites) {
cells_.reserve(num_sites);
vertices_.reserve(num_sites << 1);
edges_.reserve((num_sites << 2) + (num_sites << 1));
}
template <typename CT>
void _process_single_site(const detail::site_event<CT>& site) {
cells_.push_back(cell_type(site.initial_index(), site.source_category()));
}
// Insert a new half-edge into the output data structure.
// Takes as input left and right sites that form a new bisector.
// Returns a pair of pointers to a new half-edges.
template <typename CT>
std::pair<void*, void*> _insert_new_edge(
const detail::site_event<CT>& site1,
const detail::site_event<CT>& site2) {
// Get sites' indexes.
int site_index1 = site1.sorted_index();
int site_index2 = site2.sorted_index();
bool is_linear = is_linear_edge(site1, site2);
bool is_primary = is_primary_edge(site1, site2);
// Create a new half-edge that belongs to the first site.
edges_.push_back(edge_type(is_linear, is_primary));
edge_type& edge1 = edges_.back();
// Create a new half-edge that belongs to the second site.
edges_.push_back(edge_type(is_linear, is_primary));
edge_type& edge2 = edges_.back();
// Add the initial cell during the first edge insertion.
if (cells_.empty()) {
cells_.push_back(cell_type(
site1.initial_index(), site1.source_category()));
}
// The second site represents a new site during site event
// processing. Add a new cell to the cell records.
cells_.push_back(cell_type(
site2.initial_index(), site2.source_category()));
// Set up pointers to cells.
edge1.cell(&cells_[site_index1]);
edge2.cell(&cells_[site_index2]);
// Set up twin pointers.
edge1.twin(&edge2);
edge2.twin(&edge1);
// Return a pointer to the new half-edge.
return std::make_pair(&edge1, &edge2);
}
// Insert a new half-edge into the output data structure with the
// start at the point where two previously added half-edges intersect.
// Takes as input two sites that create a new bisector, circle event
// that corresponds to the intersection point of the two old half-edges,
// pointers to those half-edges. Half-edges' direction goes out of the
// new Voronoi vertex point. Returns a pair of pointers to a new half-edges.
template <typename CT1, typename CT2>
std::pair<void*, void*> _insert_new_edge(
const detail::site_event<CT1>& site1,
const detail::site_event<CT1>& site3,
const detail::circle_event<CT2>& circle,
void* data12, void* data23) {
edge_type* edge12 = static_cast<edge_type*>(data12);
edge_type* edge23 = static_cast<edge_type*>(data23);
// Add a new Voronoi vertex.
vertices_.push_back(vertex_type(circle.x(), circle.y()));
vertex_type& new_vertex = vertices_.back();
// Update vertex pointers of the old edges.
edge12->vertex0(&new_vertex);
edge23->vertex0(&new_vertex);
bool is_linear = is_linear_edge(site1, site3);
bool is_primary = is_primary_edge(site1, site3);
// Add a new half-edge.
edges_.push_back(edge_type(is_linear, is_primary));
edge_type& new_edge1 = edges_.back();
new_edge1.cell(&cells_[site1.sorted_index()]);
// Add a new half-edge.
edges_.push_back(edge_type(is_linear, is_primary));
edge_type& new_edge2 = edges_.back();
new_edge2.cell(&cells_[site3.sorted_index()]);
// Update twin pointers.
new_edge1.twin(&new_edge2);
new_edge2.twin(&new_edge1);
// Update vertex pointer.
new_edge2.vertex0(&new_vertex);
// Update Voronoi prev/next pointers.
edge12->prev(&new_edge1);
new_edge1.next(edge12);
edge12->twin()->next(edge23);
edge23->prev(edge12->twin());
edge23->twin()->next(&new_edge2);
new_edge2.prev(edge23->twin());
// Return a pointer to the new half-edge.
return std::make_pair(&new_edge1, &new_edge2);
}
void _build() {
// Remove degenerate edges.
edge_iterator last_edge = edges_.begin();
for (edge_iterator it = edges_.begin(); it != edges_.end(); it += 2) {
const vertex_type* v1 = it->vertex0();
const vertex_type* v2 = it->vertex1();
if (v1 && v2 && vertex_equality_predicate_(*v1, *v2)) {
remove_edge(&(*it));
} else {
if (it != last_edge) {
edge_type* e1 = &(*last_edge = *it);
edge_type* e2 = &(*(last_edge + 1) = *(it + 1));
e1->twin(e2);
e2->twin(e1);
if (e1->prev()) {
e1->prev()->next(e1);
e2->next()->prev(e2);
}
if (e2->prev()) {
e1->next()->prev(e1);
e2->prev()->next(e2);
}
}
last_edge += 2;
}
}
edges_.erase(last_edge, edges_.end());
// Set up incident edge pointers for cells and vertices.
for (edge_iterator it = edges_.begin(); it != edges_.end(); ++it) {
it->cell()->incident_edge(&(*it));
if (it->vertex0()) {
it->vertex0()->incident_edge(&(*it));
}
}
// Remove degenerate vertices.
vertex_iterator last_vertex = vertices_.begin();
for (vertex_iterator it = vertices_.begin(); it != vertices_.end(); ++it) {
if (it->incident_edge()) {
if (it != last_vertex) {
*last_vertex = *it;
vertex_type* v = &(*last_vertex);
edge_type* e = v->incident_edge();
do {
e->vertex0(v);
e = e->rot_next();
} while (e != v->incident_edge());
}
++last_vertex;
}
}
vertices_.erase(last_vertex, vertices_.end());
// Set up next/prev pointers for infinite edges.
if (vertices_.empty()) {
if (!edges_.empty()) {
// Update prev/next pointers for the line edges.
edge_iterator edge_it = edges_.begin();
edge_type* edge1 = &(*edge_it);
edge1->next(edge1);
edge1->prev(edge1);
++edge_it;
edge1 = &(*edge_it);
++edge_it;
while (edge_it != edges_.end()) {
edge_type* edge2 = &(*edge_it);
++edge_it;
edge1->next(edge2);
edge1->prev(edge2);
edge2->next(edge1);
edge2->prev(edge1);
edge1 = &(*edge_it);
++edge_it;
}
edge1->next(edge1);
edge1->prev(edge1);
}
} else {
// Update prev/next pointers for the ray edges.
for (cell_iterator cell_it = cells_.begin();
cell_it != cells_.end(); ++cell_it) {
if (cell_it->is_degenerate())
continue;
// Move to the previous edge while
// it is possible in the CW direction.
edge_type* left_edge = cell_it->incident_edge();
while (left_edge->prev() != NULL) {
left_edge = left_edge->prev();
// Terminate if this is not a boundary cell.
if (left_edge == cell_it->incident_edge())
break;
}
if (left_edge->prev() != NULL)
continue;
edge_type* right_edge = cell_it->incident_edge();
while (right_edge->next() != NULL)
right_edge = right_edge->next();
left_edge->prev(right_edge);
right_edge->next(left_edge);
}
}
}
private:
typedef typename cell_container_type::iterator cell_iterator;
typedef typename vertex_container_type::iterator vertex_iterator;
typedef typename edge_container_type::iterator edge_iterator;
typedef typename TRAITS::vertex_equality_predicate_type
vertex_equality_predicate_type;
template <typename SEvent>
bool is_primary_edge(const SEvent& site1, const SEvent& site2) const {
bool flag1 = site1.is_segment();
bool flag2 = site2.is_segment();
if (flag1 && !flag2) {
return (site1.point0() != site2.point0()) &&
(site1.point1() != site2.point0());
}
if (!flag1 && flag2) {
return (site2.point0() != site1.point0()) &&
(site2.point1() != site1.point0());
}
return true;
}
template <typename SEvent>
bool is_linear_edge(const SEvent& site1, const SEvent& site2) const {
if (!is_primary_edge(site1, site2)) {
return true;
}
return !(site1.is_segment() ^ site2.is_segment());
}
// Remove degenerate edge.
void remove_edge(edge_type* edge) {
// Update the endpoints of the incident edges to the second vertex.
vertex_type* vertex = edge->vertex0();
edge_type* updated_edge = edge->twin()->rot_next();
while (updated_edge != edge->twin()) {
updated_edge->vertex0(vertex);
updated_edge = updated_edge->rot_next();
}
edge_type* edge1 = edge;
edge_type* edge2 = edge->twin();
edge_type* edge1_rot_prev = edge1->rot_prev();
edge_type* edge1_rot_next = edge1->rot_next();
edge_type* edge2_rot_prev = edge2->rot_prev();
edge_type* edge2_rot_next = edge2->rot_next();
// Update prev/next pointers for the incident edges.
edge1_rot_next->twin()->next(edge2_rot_prev);
edge2_rot_prev->prev(edge1_rot_next->twin());
edge1_rot_prev->prev(edge2_rot_next->twin());
edge2_rot_next->twin()->next(edge1_rot_prev);
}
cell_container_type cells_;
vertex_container_type vertices_;
edge_container_type edges_;
vertex_equality_predicate_type vertex_equality_predicate_;
// Disallow copy constructor and operator=
voronoi_diagram(const voronoi_diagram&);
void operator=(const voronoi_diagram&);
};
} // polygon
} // boost
#endif // BOOST_POLYGON_VORONOI_DIAGRAM

View file

@ -0,0 +1,46 @@
// Boost.Polygon library voronoi_geometry_type.hpp header file
// Copyright Andrii Sydorchuk 2010-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POLYGON_VORONOI_GEOMETRY_TYPE
#define BOOST_POLYGON_VORONOI_GEOMETRY_TYPE
namespace boost {
namespace polygon {
// Represents topology type of the voronoi site.
enum GeometryCategory {
GEOMETRY_CATEGORY_POINT = 0x0,
GEOMETRY_CATEGORY_SEGMENT = 0x1
};
// Represents category of the input source that forms Voronoi cell.
enum SourceCategory {
// Point subtypes.
SOURCE_CATEGORY_SINGLE_POINT = 0x0,
SOURCE_CATEGORY_SEGMENT_START_POINT = 0x1,
SOURCE_CATEGORY_SEGMENT_END_POINT = 0x2,
// Segment subtypes.
SOURCE_CATEGORY_INITIAL_SEGMENT = 0x8,
SOURCE_CATEGORY_REVERSE_SEGMENT = 0x9,
SOURCE_CATEGORY_GEOMETRY_SHIFT = 0x3,
SOURCE_CATEGORY_BITMASK = 0x1F
};
inline bool belongs(
SourceCategory source_category,
GeometryCategory geometry_category) {
return (static_cast<std::size_t>(source_category) >>
SOURCE_CATEGORY_GEOMETRY_SHIFT) ==
static_cast<std::size_t>(geometry_category);
}
} // polygon
} // boost
#endif // BOOST_POLYGON_VORONOI_GEOMETRY_TYPE