Added boost header
This commit is contained in:
448
test/external/boost/polygon/detail/boolean_op.hpp
vendored
Normal file
448
test/external/boost/polygon/detail/boolean_op.hpp
vendored
Normal 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
|
||||
1394
test/external/boost/polygon/detail/boolean_op_45.hpp
vendored
Normal file
1394
test/external/boost/polygon/detail/boolean_op_45.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
69
test/external/boost/polygon/detail/iterator_compact_to_points.hpp
vendored
Normal file
69
test/external/boost/polygon/detail/iterator_compact_to_points.hpp
vendored
Normal 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_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
|
||||
|
||||
315
test/external/boost/polygon/detail/iterator_geometry_to_set.hpp
vendored
Normal file
315
test/external/boost/polygon/detail/iterator_geometry_to_set.hpp
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
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
|
||||
|
||||
60
test/external/boost/polygon/detail/iterator_points_to_compact.hpp
vendored
Normal file
60
test/external/boost/polygon/detail/iterator_points_to_compact.hpp
vendored
Normal 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
|
||||
|
||||
278
test/external/boost/polygon/detail/max_cover.hpp
vendored
Normal file
278
test/external/boost/polygon/detail/max_cover.hpp
vendored
Normal 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));
|
||||
}
|
||||
gtlsort(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
|
||||
125
test/external/boost/polygon/detail/minkowski.hpp
vendored
Normal file
125
test/external/boost/polygon/detail/minkowski.hpp
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}}
|
||||
2255
test/external/boost/polygon/detail/polygon_45_formation.hpp
vendored
Normal file
2255
test/external/boost/polygon/detail/polygon_45_formation.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
378
test/external/boost/polygon/detail/polygon_45_set_view.hpp
vendored
Normal file
378
test/external/boost/polygon/detail/polygon_45_set_view.hpp
vendored
Normal file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
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 (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 (default: 4127)
|
||||
#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 (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 (default: 4127)
|
||||
#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);
|
||||
// gtlsort(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 (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 (default: 4127)
|
||||
#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
|
||||
|
||||
236
test/external/boost/polygon/detail/polygon_45_touch.hpp
vendored
Normal file
236
test/external/boost/polygon/detail/polygon_45_touch.hpp
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
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 = 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) {
|
||||
|
||||
gtlsort(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
|
||||
491
test/external/boost/polygon/detail/polygon_90_set_view.hpp
vendored
Normal file
491
test/external/boost/polygon/detail/polygon_90_set_view.hpp
vendored
Normal file
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
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);
|
||||
// gtlsort(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
|
||||
|
||||
418
test/external/boost/polygon/detail/polygon_90_touch.hpp
vendored
Normal file
418
test/external/boost/polygon/detail/polygon_90_touch.hpp
vendored
Normal 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
|
||||
2932
test/external/boost/polygon/detail/polygon_arbitrary_formation.hpp
vendored
Normal file
2932
test/external/boost/polygon/detail/polygon_arbitrary_formation.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1807
test/external/boost/polygon/detail/polygon_formation.hpp
vendored
Normal file
1807
test/external/boost/polygon/detail/polygon_formation.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
213
test/external/boost/polygon/detail/polygon_set_view.hpp
vendored
Normal file
213
test/external/boost/polygon/detail/polygon_set_view.hpp
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
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 (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 (default: 4127)
|
||||
#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_) {}
|
||||
|
||||
template <typename ltype, typename rtype, int op_type>
|
||||
struct geometry_concept<polygon_set_view<ltype, rtype, op_type> > { typedef polygon_set_concept type; };
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
116
test/external/boost/polygon/detail/polygon_simplify.hpp
vendored
Normal file
116
test/external/boost/polygon/detail/polygon_simplify.hpp
vendored
Normal 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
|
||||
67
test/external/boost/polygon/detail/polygon_sort_adaptor.hpp
vendored
Normal file
67
test/external/boost/polygon/detail/polygon_sort_adaptor.hpp
vendored
Normal 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 gtlsort_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 gtlsort_adaptor default implementation that calls std::sort
|
||||
template<typename T>
|
||||
struct gtlsort_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 gtlsort(iter_type _b_, iter_type _e_)
|
||||
{
|
||||
gtlsort_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 gtlsort(iter_type _b_, iter_type _e_, const pred_type& _pred_)
|
||||
{
|
||||
gtlsort_adaptor<typename dummy_to_delay_instantiation<iter_type>::unit_type>::sort(_b_, _e_, _pred_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace polygon
|
||||
} // namespace boost
|
||||
#endif
|
||||
588
test/external/boost/polygon/detail/property_merge.hpp
vendored
Normal file
588
test/external/boost/polygon/detail/property_merge.hpp
vendored
Normal 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
|
||||
gtlsort(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
|
||||
gtlsort(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
|
||||
160
test/external/boost/polygon/detail/property_merge_45.hpp
vendored
Normal file
160
test/external/boost/polygon/detail/property_merge_45.hpp
vendored
Normal 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) {
|
||||
|
||||
gtlsort(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
|
||||
267
test/external/boost/polygon/detail/rectangle_formation.hpp
vendored
Normal file
267
test/external/boost/polygon/detail/rectangle_formation.hpp
vendored
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
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
|
||||
|
||||
2855
test/external/boost/polygon/detail/scan_arbitrary.hpp
vendored
Normal file
2855
test/external/boost/polygon/detail/scan_arbitrary.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
553
test/external/boost/polygon/detail/transform_detail.hpp
vendored
Normal file
553
test/external/boost/polygon/detail/transform_detail.hpp
vendored
Normal file
@@ -0,0 +1,553 @@
|
||||
/*
|
||||
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_TRANSFORM_DETAIL_HPP
|
||||
#define BOOST_POLYGON_TRANSFORM_DETAIL_HPP
|
||||
|
||||
namespace boost { namespace polygon{
|
||||
// inline std::ostream& operator<< (std::ostream& o, const axis_transformation& r) {
|
||||
// o << r.atr_;
|
||||
// return o;
|
||||
// }
|
||||
|
||||
// inline std::istream& operator>> (std::istream& i, axis_transformation& r) {
|
||||
// int tmp;
|
||||
// i >> tmp;
|
||||
// r = axis_transformation((axis_transformation::ATR)tmp);
|
||||
// return i;
|
||||
// }
|
||||
|
||||
// template <typename scale_factor_type>
|
||||
// inline std::ostream& operator<< (std::ostream& o, const anisotropic_scale_factor<scale_factor_type>& sc) {
|
||||
// o << sc.scale_[0] << BOOST_POLYGON_SEP << sc.scale_[1] << GTL_SEP << sc.scale_[2];
|
||||
// return o;
|
||||
// }
|
||||
|
||||
// template <typename scale_factor_type>
|
||||
// inline std::istream& operator>> (std::istream& i, anisotropic_scale_factor<scale_factor_type>& sc) {
|
||||
// i >> sc.scale_[0] >> sc.scale_[1] >> sc.scale_[2];
|
||||
// return i;
|
||||
// }
|
||||
|
||||
// template <typename coordinate_type>
|
||||
// inline std::ostream& operator<< (std::ostream& o, const transformation& tr) {
|
||||
// o << tr.atr_ << BOOST_POLYGON_SEP << tr.p_;
|
||||
// return o;
|
||||
// }
|
||||
|
||||
// template <typename coordinate_type>
|
||||
// inline std::istream& operator>> (std::istream& i, transformation& tr) {
|
||||
// i >> tr.atr_ >> tr.p_;
|
||||
// return i;
|
||||
// }
|
||||
|
||||
|
||||
inline axis_transformation::axis_transformation(const orientation_3d& orient) : atr_(NULL_TRANSFORM) {
|
||||
const ATR tmp[3] = {
|
||||
UP_EAST_NORTH, //sort by x, then z, then y
|
||||
EAST_UP_NORTH, //sort by y, then z, then x
|
||||
EAST_NORTH_UP //sort by z, then y, then x
|
||||
};
|
||||
atr_ = tmp[orient.to_int()];
|
||||
}
|
||||
|
||||
inline axis_transformation::axis_transformation(const orientation_2d& orient) : atr_(NULL_TRANSFORM) {
|
||||
const ATR tmp[3] = {
|
||||
NORTH_EAST_UP, //sort by z, then x, then y
|
||||
EAST_NORTH_UP //sort by z, then y, then x
|
||||
};
|
||||
atr_ = tmp[orient.to_int()];
|
||||
}
|
||||
|
||||
inline axis_transformation::axis_transformation(const direction_3d& dir) : atr_(NULL_TRANSFORM) {
|
||||
const ATR tmp[6] = {
|
||||
DOWN_EAST_NORTH, //sort by -x, then z, then y
|
||||
UP_EAST_NORTH, //sort by x, then z, then y
|
||||
EAST_DOWN_NORTH, //sort by -y, then z, then x
|
||||
EAST_UP_NORTH, //sort by y, then z, then x
|
||||
EAST_NORTH_DOWN, //sort by -z, then y, then x
|
||||
EAST_NORTH_UP //sort by z, then y, then x
|
||||
};
|
||||
atr_ = tmp[dir.to_int()];
|
||||
}
|
||||
|
||||
inline axis_transformation::axis_transformation(const direction_2d& dir) : atr_(NULL_TRANSFORM) {
|
||||
const ATR tmp[4] = {
|
||||
SOUTH_EAST_UP, //sort by z, then x, then y
|
||||
NORTH_EAST_UP, //sort by z, then x, then y
|
||||
EAST_SOUTH_UP, //sort by z, then y, then x
|
||||
EAST_NORTH_UP //sort by z, then y, then x
|
||||
};
|
||||
atr_ = tmp[dir.to_int()];
|
||||
}
|
||||
|
||||
inline axis_transformation& axis_transformation::operator=(const axis_transformation& a) {
|
||||
atr_ = a.atr_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline axis_transformation& axis_transformation::operator=(const ATR& atr) {
|
||||
atr_ = atr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool axis_transformation::operator==(const axis_transformation& a) const {
|
||||
return atr_ == a.atr_;
|
||||
}
|
||||
|
||||
inline bool axis_transformation::operator!=(const axis_transformation& a) const {
|
||||
return !(*this == a);
|
||||
}
|
||||
|
||||
inline bool axis_transformation::operator<(const axis_transformation& a) const {
|
||||
return atr_ < a.atr_;
|
||||
}
|
||||
|
||||
inline axis_transformation& axis_transformation::operator+=(const axis_transformation& a){
|
||||
bool abit5 = (a.atr_ & 32) != 0;
|
||||
bool abit4 = (a.atr_ & 16) != 0;
|
||||
bool abit3 = (a.atr_ & 8) != 0;
|
||||
bool abit2 = (a.atr_ & 4) != 0;
|
||||
bool abit1 = (a.atr_ & 2) != 0;
|
||||
bool abit0 = (a.atr_ & 1) != 0;
|
||||
bool bit5 = (atr_ & 32) != 0;
|
||||
bool bit4 = (atr_ & 16) != 0;
|
||||
bool bit3 = (atr_ & 8) != 0;
|
||||
bool bit2 = (atr_ & 4) != 0;
|
||||
bool bit1 = (atr_ & 2) != 0;
|
||||
bool bit0 = (atr_ & 1) != 0;
|
||||
int indexes[2][3] = {
|
||||
{
|
||||
((int)((bit5 & bit2) | (bit4 & !bit2)) << 1) +
|
||||
(int)(bit2 & !bit5),
|
||||
((int)((bit4 & bit2) | (bit5 & !bit2)) << 1) +
|
||||
(int)(!bit5 & !bit2),
|
||||
((int)(!bit4 & !bit5) << 1) +
|
||||
(int)(bit5)
|
||||
},
|
||||
{
|
||||
((int)((abit5 & abit2) | (abit4 & !abit2)) << 1) +
|
||||
(int)(abit2 & !abit5),
|
||||
((int)((abit4 & abit2) | (abit5 & !abit2)) << 1) +
|
||||
(int)(!abit5 & !abit2),
|
||||
((int)(!abit4 & !abit5) << 1) +
|
||||
(int)(abit5)
|
||||
}
|
||||
};
|
||||
int zero_bits[2][3] = {
|
||||
{bit0, bit1, bit3},
|
||||
{abit0, abit1, abit3}
|
||||
};
|
||||
int nbit3 = zero_bits[0][2] ^ zero_bits[1][indexes[0][2]];
|
||||
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]];
|
||||
indexes[0][2] = indexes[1][indexes[0][2]];
|
||||
int nbit5 = (indexes[0][2] == 1);
|
||||
int nbit4 = (indexes[0][2] == 0);
|
||||
int nbit2 = (!(nbit5 | nbit4) & (bool)(indexes[0][0] & 1)) | //swap xy
|
||||
(nbit5 & ((indexes[0][0] & 2) >> 1)) | //z->y x->z
|
||||
(nbit4 & ((indexes[0][1] & 2) >> 1)); //z->x y->z
|
||||
atr_ = (ATR)((nbit5 << 5) +
|
||||
(nbit4 << 4) +
|
||||
(nbit3 << 3) +
|
||||
(nbit2 << 2) +
|
||||
(nbit1 << 1) + nbit0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline axis_transformation 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
|
||||
inline void axis_transformation::populate_axis_array(INDIVIDUAL_AXIS axis_array[]) const {
|
||||
bool bit5 = (atr_ & 32) != 0;
|
||||
bool bit4 = (atr_ & 16) != 0;
|
||||
bool bit3 = (atr_ & 8) != 0;
|
||||
bool bit2 = (atr_ & 4) != 0;
|
||||
bool bit1 = (atr_ & 2) != 0;
|
||||
bool bit0 = (atr_ & 1) != 0;
|
||||
axis_array[2] =
|
||||
(INDIVIDUAL_AXIS)((((int)(!bit4 & !bit5)) << 2) +
|
||||
((int)(bit5) << 1) +
|
||||
bit3);
|
||||
axis_array[1] =
|
||||
(INDIVIDUAL_AXIS)((((int)((bit4 & bit2) | (bit5 & !bit2))) << 2)+
|
||||
((int)(!bit5 & !bit2) << 1) +
|
||||
bit1);
|
||||
axis_array[0] =
|
||||
(INDIVIDUAL_AXIS)((((int)((bit5 & bit2) | (bit4 & !bit2))) << 2) +
|
||||
((int)(bit2 & !bit5) << 1) +
|
||||
bit0);
|
||||
}
|
||||
|
||||
// combine_axis_arrays concatenates this_array and that_array overwriting
|
||||
// the result into this_array
|
||||
inline void
|
||||
axis_transformation::combine_axis_arrays (INDIVIDUAL_AXIS this_array[],
|
||||
const INDIVIDUAL_AXIS that_array[]){
|
||||
int indexes[3] = {this_array[0] >> 1,
|
||||
this_array[1] >> 1,
|
||||
this_array[2] >> 1};
|
||||
int zero_bits[2][3] = {
|
||||
{this_array[0] & 1, this_array[1] & 1, this_array[2] & 1},
|
||||
{that_array[0] & 1, that_array[1] & 1, that_array[2] & 1}
|
||||
};
|
||||
this_array[0] = that_array[indexes[0]];
|
||||
this_array[0] = (INDIVIDUAL_AXIS)((int)this_array[0] & (int)((int)PZ+(int)PY));
|
||||
this_array[0] = (INDIVIDUAL_AXIS)((int)this_array[0] |
|
||||
((int)zero_bits[0][0] ^
|
||||
(int)zero_bits[1][indexes[0]]));
|
||||
this_array[1] = that_array[indexes[1]];
|
||||
this_array[1] = (INDIVIDUAL_AXIS)((int)this_array[1] & (int)((int)PZ+(int)PY));
|
||||
this_array[1] = (INDIVIDUAL_AXIS)((int)this_array[1] |
|
||||
((int)zero_bits[0][1] ^
|
||||
(int)zero_bits[1][indexes[1]]));
|
||||
this_array[2] = that_array[indexes[2]];
|
||||
this_array[2] = (INDIVIDUAL_AXIS)((int)this_array[2] & (int)((int)PZ+(int)PY));
|
||||
this_array[2] = (INDIVIDUAL_AXIS)((int)this_array[2] |
|
||||
((int)zero_bits[0][2] ^
|
||||
(int)zero_bits[1][indexes[2]]));
|
||||
}
|
||||
|
||||
// write_back_axis_array converts an array of three INDIVIDUAL_AXIS values
|
||||
// to the ATR enum value and sets 'this' to that value
|
||||
inline void axis_transformation::write_back_axis_array(const INDIVIDUAL_AXIS this_array[]) {
|
||||
int bit5 = ((int)this_array[2] & 2) != 0;
|
||||
int bit4 = !((((int)this_array[2] & 4) != 0) | (((int)this_array[2] & 2) != 0));
|
||||
int bit3 = ((int)this_array[2] & 1) != 0;
|
||||
//bit 2 is the tricky bit
|
||||
int bit2 = ((!(bit5 | bit4)) & (((int)this_array[0] & 2) != 0)) | //swap xy
|
||||
(bit5 & (((int)this_array[0] & 4) >> 2)) | //z->y x->z
|
||||
(bit4 & (((int)this_array[1] & 4) >> 2)); //z->x y->z
|
||||
int bit1 = ((int)this_array[1] & 1);
|
||||
int bit0 = ((int)this_array[0] & 1);
|
||||
atr_ = ATR((bit5 << 5) +
|
||||
(bit4 << 4) +
|
||||
(bit3 << 3) +
|
||||
(bit2 << 2) +
|
||||
(bit1 << 1) + bit0);
|
||||
}
|
||||
|
||||
// behavior is deterministic but undefined in the case where illegal
|
||||
// combinations of directions are passed in.
|
||||
inline axis_transformation&
|
||||
axis_transformation::set_directions(const direction_2d& horizontalDir,
|
||||
const direction_2d& verticalDir){
|
||||
int bit2 = (static_cast<orientation_2d>(horizontalDir).to_int()) != 0;
|
||||
int bit1 = !(verticalDir.to_int() & 1);
|
||||
int bit0 = !(horizontalDir.to_int() & 1);
|
||||
atr_ = ATR((bit2 << 2) + (bit1 << 1) + bit0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// behavior is deterministic but undefined in the case where illegal
|
||||
// combinations of directions are passed in.
|
||||
inline axis_transformation& axis_transformation::set_directions(const direction_3d& horizontalDir,
|
||||
const direction_3d& verticalDir,
|
||||
const direction_3d& proximalDir){
|
||||
int this_array[3] = {horizontalDir.to_int(),
|
||||
verticalDir.to_int(),
|
||||
proximalDir.to_int()};
|
||||
int bit5 = (this_array[2] & 2) != 0;
|
||||
int bit4 = !(((this_array[2] & 4) != 0) | ((this_array[2] & 2) != 0));
|
||||
int bit3 = !((this_array[2] & 1) != 0);
|
||||
//bit 2 is the tricky bit
|
||||
int bit2 = (!(bit5 | bit4) & ((this_array[0] & 2) != 0 )) | //swap xy
|
||||
(bit5 & ((this_array[0] & 4) >> 2)) | //z->y x->z
|
||||
(bit4 & ((this_array[1] & 4) >> 2)); //z->x y->z
|
||||
int bit1 = !(this_array[1] & 1);
|
||||
int bit0 = !(this_array[0] & 1);
|
||||
atr_ = ATR((bit5 << 5) +
|
||||
(bit4 << 4) +
|
||||
(bit3 << 3) +
|
||||
(bit2 << 2) +
|
||||
(bit1 << 1) + bit0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename coordinate_type_2>
|
||||
inline void axis_transformation::transform(coordinate_type_2& x, coordinate_type_2& 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);
|
||||
}
|
||||
|
||||
template <typename coordinate_type_2>
|
||||
inline void axis_transformation::transform(coordinate_type_2& x, coordinate_type_2& y, coordinate_type_2& z) const {
|
||||
int bit5 = (atr_ & 32) != 0;
|
||||
int bit4 = (atr_ & 16) != 0;
|
||||
int bit3 = (atr_ & 8) != 0;
|
||||
int bit2 = (atr_ & 4) != 0;
|
||||
int bit1 = (atr_ & 2) != 0;
|
||||
int bit0 = (atr_ & 1) != 0;
|
||||
x *= -((bit0 << 1) - 1);
|
||||
y *= -((bit1 << 1) - 1);
|
||||
z *= -((bit3 << 1) - 1);
|
||||
predicated_swap(bit2 != 0, x, y);
|
||||
predicated_swap(bit5 != 0, y, z);
|
||||
predicated_swap(bit4 != 0, x, z);
|
||||
}
|
||||
|
||||
inline axis_transformation& axis_transformation::invert_2d() {
|
||||
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;
|
||||
}
|
||||
|
||||
inline axis_transformation axis_transformation::inverse_2d() const {
|
||||
axis_transformation retval(*this);
|
||||
return retval.invert_2d();
|
||||
}
|
||||
|
||||
inline axis_transformation& axis_transformation::invert() {
|
||||
int bit5 = ((atr_ & 32) != 0);
|
||||
int bit4 = ((atr_ & 16) != 0);
|
||||
int bit3 = ((atr_ & 8) != 0);
|
||||
int bit2 = ((atr_ & 4) != 0);
|
||||
int bit1 = ((atr_ & 2) != 0);
|
||||
int bit0 = ((atr_ & 1) != 0);
|
||||
predicated_swap(bit2 != 0, bit4, bit5);
|
||||
predicated_swap(bit4 != 0, bit0, bit3);
|
||||
predicated_swap(bit5 != 0, bit1, bit3);
|
||||
predicated_swap(bit2 != 0, bit0, bit1);
|
||||
atr_ = (ATR)((bit5 << 5) +
|
||||
(bit4 << 4) +
|
||||
(bit3 << 3) +
|
||||
(bit2 << 2) +
|
||||
(bit1 << 1) + bit0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline axis_transformation axis_transformation::inverse() const {
|
||||
axis_transformation retval(*this);
|
||||
return retval.invert();
|
||||
}
|
||||
|
||||
template <typename scale_factor_type>
|
||||
inline scale_factor_type anisotropic_scale_factor<scale_factor_type>::get(orientation_3d orient) const {
|
||||
return scale_[orient.to_int()];
|
||||
}
|
||||
|
||||
template <typename scale_factor_type>
|
||||
inline void anisotropic_scale_factor<scale_factor_type>::set(orientation_3d orient, scale_factor_type value) {
|
||||
scale_[orient.to_int()] = value;
|
||||
}
|
||||
|
||||
template <typename scale_factor_type>
|
||||
inline scale_factor_type anisotropic_scale_factor<scale_factor_type>::x() const { return scale_[HORIZONTAL]; }
|
||||
template <typename scale_factor_type>
|
||||
inline scale_factor_type anisotropic_scale_factor<scale_factor_type>::y() const { return scale_[VERTICAL]; }
|
||||
template <typename scale_factor_type>
|
||||
inline scale_factor_type anisotropic_scale_factor<scale_factor_type>::z() const { return scale_[PROXIMAL]; }
|
||||
template <typename scale_factor_type>
|
||||
inline void anisotropic_scale_factor<scale_factor_type>::x(scale_factor_type value) { scale_[HORIZONTAL] = value; }
|
||||
template <typename scale_factor_type>
|
||||
inline void anisotropic_scale_factor<scale_factor_type>::y(scale_factor_type value) { scale_[VERTICAL] = value; }
|
||||
template <typename scale_factor_type>
|
||||
inline void anisotropic_scale_factor<scale_factor_type>::z(scale_factor_type value) { scale_[PROXIMAL] = value; }
|
||||
|
||||
//concatenation operator (convolve scale factors)
|
||||
template <typename scale_factor_type>
|
||||
inline anisotropic_scale_factor<scale_factor_type> anisotropic_scale_factor<scale_factor_type>::operator+(const anisotropic_scale_factor<scale_factor_type>& s) const {
|
||||
anisotropic_scale_factor<scale_factor_type> retval(*this);
|
||||
return retval+=s;
|
||||
}
|
||||
|
||||
//concatenate this with that
|
||||
template <typename scale_factor_type>
|
||||
inline const anisotropic_scale_factor<scale_factor_type>& anisotropic_scale_factor<scale_factor_type>::operator+=(const anisotropic_scale_factor<scale_factor_type>& s){
|
||||
scale_[0] *= s.scale_[0];
|
||||
scale_[1] *= s.scale_[1];
|
||||
scale_[2] *= s.scale_[2];
|
||||
return *this;
|
||||
}
|
||||
|
||||
//transform
|
||||
template <typename scale_factor_type>
|
||||
inline anisotropic_scale_factor<scale_factor_type>& anisotropic_scale_factor<scale_factor_type>::transform(axis_transformation atr){
|
||||
direction_3d dirs[3];
|
||||
atr.get_directions(dirs[0],dirs[1],dirs[2]);
|
||||
scale_factor_type tmp[3] = {scale_[0], scale_[1], scale_[2]};
|
||||
for(int i = 0; i < 3; ++i){
|
||||
scale_[orientation_3d(dirs[i]).to_int()] = tmp[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename scale_factor_type>
|
||||
template <typename coordinate_type_2>
|
||||
inline void anisotropic_scale_factor<scale_factor_type>::scale(coordinate_type_2& x, coordinate_type_2& y) const {
|
||||
x = scaling_policy<coordinate_type_2>::round((scale_factor_type)x * get(HORIZONTAL));
|
||||
y = scaling_policy<coordinate_type_2>::round((scale_factor_type)y * get(HORIZONTAL));
|
||||
}
|
||||
|
||||
template <typename scale_factor_type>
|
||||
template <typename coordinate_type_2>
|
||||
inline void anisotropic_scale_factor<scale_factor_type>::scale(coordinate_type_2& x, coordinate_type_2& y, coordinate_type_2& z) const {
|
||||
scale(x, y);
|
||||
z = scaling_policy<coordinate_type_2>::round((scale_factor_type)z * get(HORIZONTAL));
|
||||
}
|
||||
|
||||
template <typename scale_factor_type>
|
||||
inline anisotropic_scale_factor<scale_factor_type>& anisotropic_scale_factor<scale_factor_type>::invert() {
|
||||
x(1/x());
|
||||
y(1/y());
|
||||
z(1/z());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <typename coordinate_type>
|
||||
inline transformation<coordinate_type>::transformation() : atr_(), p_(0, 0, 0) {;}
|
||||
|
||||
template <typename coordinate_type>
|
||||
inline transformation<coordinate_type>::transformation(axis_transformation atr) : atr_(atr), p_(0, 0, 0){;}
|
||||
|
||||
template <typename coordinate_type>
|
||||
inline transformation<coordinate_type>::transformation(axis_transformation::ATR atr) : atr_(atr), p_(0, 0, 0){;}
|
||||
|
||||
template <typename coordinate_type>
|
||||
template <typename point_type>
|
||||
inline transformation<coordinate_type>::transformation(const point_type& p) : atr_(), p_(0, 0, 0) {
|
||||
set_translation(p);
|
||||
}
|
||||
|
||||
template <typename coordinate_type>
|
||||
template <typename point_type>
|
||||
inline transformation<coordinate_type>::transformation(axis_transformation atr, const point_type& p) :
|
||||
atr_(atr), p_(0, 0, 0) {
|
||||
set_translation(p);
|
||||
}
|
||||
|
||||
template <typename coordinate_type>
|
||||
template <typename point_type>
|
||||
inline transformation<coordinate_type>::transformation(axis_transformation atr, const point_type& referencePt, const point_type& destinationPt) : atr_(), p_(0, 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;
|
||||
}
|
||||
|
||||
template <typename coordinate_type>
|
||||
inline transformation<coordinate_type>::transformation(const transformation<coordinate_type>& tr) :
|
||||
atr_(tr.atr_), p_(tr.p_) {;}
|
||||
|
||||
template <typename coordinate_type>
|
||||
inline bool transformation<coordinate_type>::operator==(const transformation<coordinate_type>& tr) const {
|
||||
return atr_ == tr.atr_ && p_ == tr.p_;
|
||||
}
|
||||
|
||||
template <typename coordinate_type>
|
||||
inline bool transformation<coordinate_type>::operator!=(const transformation<coordinate_type>& tr) const {
|
||||
return !(*this == tr);
|
||||
}
|
||||
|
||||
template <typename coordinate_type>
|
||||
inline bool transformation<coordinate_type>::operator<(const transformation<coordinate_type>& tr) const {
|
||||
return atr_ < tr.atr_ || atr_ == tr.atr_ && p_ < tr.p_;
|
||||
}
|
||||
|
||||
template <typename coordinate_type>
|
||||
inline transformation<coordinate_type> transformation<coordinate_type>::operator+(const transformation<coordinate_type>& tr) const {
|
||||
transformation<coordinate_type> retval(*this);
|
||||
return retval+=tr;
|
||||
}
|
||||
|
||||
template <typename coordinate_type>
|
||||
inline const transformation<coordinate_type>& transformation<coordinate_type>::operator+=(const transformation<coordinate_type>& tr){
|
||||
//apply the inverse transformation of this to the translation point of that
|
||||
//and convolve it with this translation point
|
||||
coordinate_type x, y, z;
|
||||
transformation<coordinate_type> inv = inverse();
|
||||
inv.transform(x, y, z);
|
||||
p_.set(HORIZONTAL, p_.get(HORIZONTAL) + x);
|
||||
p_.set(VERTICAL, p_.get(VERTICAL) + y);
|
||||
p_.set(PROXIMAL, p_.get(PROXIMAL) + z);
|
||||
//concatenate axis transforms
|
||||
atr_ += tr.atr_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename coordinate_type>
|
||||
inline void transformation<coordinate_type>::set_axis_transformation(const axis_transformation& atr) {
|
||||
atr_ = atr;
|
||||
}
|
||||
|
||||
template <typename coordinate_type>
|
||||
template <typename point_type>
|
||||
inline void transformation<coordinate_type>::get_translation(point_type& p) const {
|
||||
assign(p, p_);
|
||||
}
|
||||
|
||||
template <typename coordinate_type>
|
||||
template <typename point_type>
|
||||
inline void transformation<coordinate_type>::set_translation(const point_type& p) {
|
||||
assign(p_, p);
|
||||
}
|
||||
|
||||
template <typename coordinate_type>
|
||||
inline void transformation<coordinate_type>::transform(coordinate_type& x, coordinate_type& y) const {
|
||||
//subtract each component of new origin point
|
||||
y -= p_.get(VERTICAL);
|
||||
x -= p_.get(HORIZONTAL);
|
||||
atr_.transform(x, y);
|
||||
}
|
||||
|
||||
template <typename coordinate_type>
|
||||
inline void transformation<coordinate_type>::transform(coordinate_type& x, coordinate_type& y, coordinate_type& z) const {
|
||||
//subtract each component of new origin point
|
||||
z -= p_.get(PROXIMAL);
|
||||
y -= p_.get(VERTICAL);
|
||||
x -= p_.get(HORIZONTAL);
|
||||
atr_.transform(x,y,z);
|
||||
}
|
||||
|
||||
// sets the axis_transform portion to its inverse
|
||||
// transforms the tranlastion portion by that inverse axis_transform
|
||||
// multiplies the translation portion by -1 to reverse it
|
||||
template <typename coordinate_type>
|
||||
inline transformation<coordinate_type>& transformation<coordinate_type>::invert() {
|
||||
coordinate_type x = p_.get(HORIZONTAL), y = p_.get(VERTICAL), z = p_.get(PROXIMAL);
|
||||
atr_.transform(x, y, z);
|
||||
x *= -1;
|
||||
y *= -1;
|
||||
z *= -1;
|
||||
p_ = point_3d_data<coordinate_type>(x, y, z);
|
||||
atr_.invert();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename coordinate_type>
|
||||
inline transformation<coordinate_type> transformation<coordinate_type>::inverse() const {
|
||||
transformation<coordinate_type> retval(*this);
|
||||
return retval.invert();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user