File indexing completed on 2024-11-16 09:28:40
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_POLYGON_BOOLEAN_OP_45_HPP
0009 #define BOOST_POLYGON_BOOLEAN_OP_45_HPP
0010 namespace boost { namespace polygon{
0011
0012 template <typename Unit>
0013 struct boolean_op_45 {
0014 typedef point_data<Unit> Point;
0015 typedef typename coordinate_traits<Unit>::manhattan_area_type LongUnit;
0016
0017 class Count2 {
0018 public:
0019 inline Count2()
0020 #ifndef BOOST_POLYGON_MSVC
0021 : counts()
0022 #endif
0023 { counts[0] = counts[1] = 0; }
0024
0025 inline Count2(int count1, int count2)
0026 #ifndef BOOST_POLYGON_MSVC
0027 : counts()
0028 #endif
0029 { counts[0] = count1; counts[1] = count2; }
0030 inline Count2(const Count2& count)
0031 #ifndef BOOST_POLYGON_MSVC
0032 : counts()
0033 #endif
0034 { counts[0] = count.counts[0]; counts[1] = count.counts[1]; }
0035 inline bool operator==(const Count2& count) const { return counts[0] == count.counts[0] && counts[1] == count.counts[1]; }
0036 inline bool operator!=(const Count2& count) const { return !((*this) == count); }
0037 inline Count2& operator=(int count) { counts[0] = counts[1] = count; return *this; }
0038 inline Count2& operator=(const Count2& count) { counts[0] = count.counts[0]; counts[1] = count.counts[1]; return *this; }
0039 inline int& operator[](bool index) { return counts[index]; }
0040 inline int operator[](bool index) const {return counts[index]; }
0041 inline Count2& operator+=(const Count2& count){
0042 counts[0] += count[0];
0043 counts[1] += count[1];
0044 return *this;
0045 }
0046 inline Count2& operator-=(const Count2& count){
0047 counts[0] -= count[0];
0048 counts[1] -= count[1];
0049 return *this;
0050 }
0051 inline Count2 operator+(const Count2& count) const {
0052 return Count2(*this)+=count;
0053 }
0054 inline Count2 operator-(const Count2& count) const {
0055 return Count2(*this)-=count;
0056 }
0057 inline Count2 invert() const {
0058 return Count2(-counts[0], -counts[1]);
0059 }
0060 private:
0061 int counts[2];
0062 };
0063
0064 class Count1 {
0065 public:
0066 inline Count1() : count_(0) { }
0067 inline Count1(int count) : count_(count) { }
0068 inline Count1(const Count1& count) : count_(count.count_) { }
0069 inline bool operator==(const Count1& count) const { return count_ == count.count_; }
0070 inline bool operator!=(const Count1& count) const { return !((*this) == count); }
0071 inline Count1& operator=(int count) { count_ = count; return *this; }
0072 inline Count1& operator=(const Count1& count) { count_ = count.count_; return *this; }
0073 inline Count1& operator+=(const Count1& count){
0074 count_ += count.count_;
0075 return *this;
0076 }
0077 inline Count1& operator-=(const Count1& count){
0078 count_ -= count.count_;
0079 return *this;
0080 }
0081 inline Count1 operator+(const Count1& count) const {
0082 return Count1(*this)+=count;
0083 }
0084 inline Count1 operator-(const Count1& count) const {
0085 return Count1(*this)-=count;
0086 }
0087 inline Count1 invert() const {
0088 return Count1(-count_);
0089 }
0090 int count_;
0091 };
0092
0093
0094
0095
0096
0097
0098 template <typename CountType>
0099 class Scan45ElementT {
0100 public:
0101 Unit x;
0102 Unit y;
0103 int rise;
0104 mutable CountType count;
0105 inline Scan45ElementT() : x(), y(), rise(), count() {}
0106 inline Scan45ElementT(Unit xIn, Unit yIn, int riseIn, CountType countIn = CountType()) :
0107 x(xIn), y(yIn), rise(riseIn), count(countIn) {}
0108 inline Scan45ElementT(const Scan45ElementT& that) :
0109 x(that.x), y(that.y), rise(that.rise), count(that.count) {}
0110 inline Scan45ElementT& operator=(const Scan45ElementT& that) {
0111 x = that.x; y = that.y; rise = that.rise; count = that.count;
0112 return *this;
0113 }
0114 inline Unit evalAtX(Unit xIn) const {
0115 return y + rise * (xIn - x);
0116 }
0117
0118 inline bool cross(Point& crossPoint, const Scan45ElementT& edge, Unit currentX) const {
0119 Unit y1 = evalAtX(currentX);
0120 Unit y2 = edge.evalAtX(currentX);
0121 int rise1 = rise;
0122 int rise2 = edge.rise;
0123 if(rise > edge.rise){
0124 if(y1 > y2) return false;
0125 } else if(rise < edge.rise){
0126 if(y2 > y1) return false;
0127 std::swap(y1, y2);
0128 std::swap(rise1, rise2);
0129 } else { return false; }
0130 if(rise1 == 1) {
0131 if(rise2 == 0) {
0132 crossPoint = Point(currentX + y2 - y1, y2);
0133 } else {
0134
0135 Unit delta = (y2 - y1)/2;
0136 crossPoint = Point(currentX + delta, y1 + delta);
0137 }
0138 } else {
0139
0140 crossPoint = Point(currentX + y2 - y1, y1);
0141 }
0142 return true;
0143 }
0144 };
0145
0146 typedef Scan45ElementT<Count2> Scan45Element;
0147
0148
0149
0150
0151
0152
0153 class lessScan45ElementRise {
0154 public:
0155 typedef Scan45Element first_argument_type;
0156 typedef Scan45Element second_argument_type;
0157 typedef bool result_type;
0158 inline lessScan45ElementRise() {}
0159 inline bool operator () (Scan45Element elm1, Scan45Element elm2) const {
0160 return elm1.rise < elm2.rise;
0161 }
0162 };
0163
0164 template <typename CountType>
0165 class lessScan45Element {
0166 private:
0167 Unit *x_;
0168 int *justBefore_;
0169 public:
0170 inline lessScan45Element() : x_(0), justBefore_(0) {}
0171 inline lessScan45Element(Unit *x, int *justBefore) : x_(x), justBefore_(justBefore) {}
0172 inline lessScan45Element(const lessScan45Element& that) : x_(that.x_), justBefore_(that.justBefore_) {}
0173 inline lessScan45Element& operator=(const lessScan45Element& that) { x_ = that.x_; justBefore_ = that.justBefore_; return *this; }
0174 inline bool operator () (const Scan45ElementT<CountType>& elm1,
0175 const Scan45ElementT<CountType>& elm2) const {
0176 Unit y1 = elm1.evalAtX(*x_);
0177 Unit y2 = elm2.evalAtX(*x_);
0178 if(y1 < y2) return true;
0179 if(y1 == y2) {
0180
0181 if(*justBefore_) {
0182 return elm1.rise > elm2.rise;
0183 } else {
0184 return elm1.rise < elm2.rise;
0185 }
0186 }
0187 return false;
0188 }
0189 };
0190
0191 template <typename CountType>
0192 class Scan45CountT {
0193 public:
0194 inline Scan45CountT() : counts() {}
0195 inline Scan45CountT(CountType count) : counts() { counts[0] = counts[1] = counts[2] = counts[3] = count; }
0196 inline Scan45CountT(const CountType& count1, const CountType& count2, const CountType& count3,
0197 const CountType& count4) : counts() {
0198 counts[0] = count1;
0199 counts[1] = count2;
0200 counts[2] = count3;
0201 counts[3] = count4;
0202 }
0203 inline Scan45CountT(const Scan45CountT& count) : counts() {
0204 (*this) = count;
0205 }
0206 inline bool operator==(const Scan45CountT& count) const {
0207 for(unsigned int i = 0; i < 4; ++i) {
0208 if(counts[i] != count.counts[i]) return false;
0209 }
0210 return true;
0211 }
0212 inline bool operator!=(const Scan45CountT& count) const { return !((*this) == count); }
0213 inline Scan45CountT& operator=(CountType count) {
0214 counts[0] = counts[1] = counts[2] = counts[3] = count; return *this; }
0215 inline Scan45CountT& operator=(const Scan45CountT& count) {
0216 for(unsigned int i = 0; i < 4; ++i) {
0217 counts[i] = count.counts[i];
0218 }
0219 return *this;
0220 }
0221 inline CountType& operator[](int index) { return counts[index]; }
0222 inline CountType operator[](int index) const {return counts[index]; }
0223 inline Scan45CountT& operator+=(const Scan45CountT& count){
0224 for(unsigned int i = 0; i < 4; ++i) {
0225 counts[i] += count.counts[i];
0226 }
0227 return *this;
0228 }
0229 inline Scan45CountT& operator-=(const Scan45CountT& count){
0230 for(unsigned int i = 0; i < 4; ++i) {
0231 counts[i] -= count.counts[i];
0232 }
0233 return *this;
0234 }
0235 inline Scan45CountT operator+(const Scan45CountT& count) const {
0236 return Scan45CountT(*this)+=count;
0237 }
0238 inline Scan45CountT operator-(const Scan45CountT& count) const {
0239 return Scan45CountT(*this)-=count;
0240 }
0241 inline Scan45CountT invert() const {
0242 return Scan45CountT(CountType())-=(*this);
0243 }
0244 inline Scan45CountT& operator+=(const Scan45ElementT<CountType>& element){
0245 counts[element.rise+1] += element.count; return *this;
0246 }
0247 private:
0248 CountType counts[4];
0249 };
0250
0251 typedef Scan45CountT<Count2> Scan45Count;
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267 template <typename ct>
0268 class Vertex45T {
0269 public:
0270 Point pt;
0271 int rise;
0272 ct count;
0273 inline Vertex45T() : pt(), rise(), count() {}
0274 inline Vertex45T(const Point& point, int riseIn, ct countIn) : pt(point), rise(riseIn), count(countIn) {}
0275 inline Vertex45T(const Vertex45T& vertex) : pt(vertex.pt), rise(vertex.rise), count(vertex.count) {}
0276 inline Vertex45T& operator=(const Vertex45T& vertex){
0277 pt = vertex.pt; rise = vertex.rise; count = vertex.count; return *this; }
0278 inline bool operator==(const Vertex45T& vertex) const {
0279 return pt == vertex.pt && rise == vertex.rise && count == vertex.count; }
0280 inline bool operator!=(const Vertex45T& vertex) const { return !((*this) == vertex); }
0281 inline bool operator<(const Vertex45T& vertex) const {
0282 if(pt.x() < vertex.pt.x()) return true;
0283 if(pt.x() == vertex.pt.x()) {
0284 if(pt.y() < vertex.pt.y()) return true;
0285 if(pt.y() == vertex.pt.y()) { return rise < vertex.rise; }
0286 }
0287 return false;
0288 }
0289 inline bool operator>(const Vertex45T& vertex) const { return vertex < (*this); }
0290 inline bool operator<=(const Vertex45T& vertex) const { return !((*this) > vertex); }
0291 inline bool operator>=(const Vertex45T& vertex) const { return !((*this) < vertex); }
0292 inline Unit evalAtX(Unit xIn) const { return pt.y() + rise * (xIn - pt.x()); }
0293 };
0294
0295 typedef Vertex45T<int> Vertex45;
0296
0297
0298
0299
0300
0301
0302
0303 class lessVertex45 {
0304 private:
0305 Unit *x_;
0306 int *justBefore_;
0307 public:
0308 inline lessVertex45() : x_(0), justBefore_() {}
0309
0310 inline lessVertex45(Unit *x, int *justBefore) : x_(x), justBefore_(justBefore) {}
0311
0312 inline lessVertex45(const lessVertex45& that) : x_(that.x_), justBefore_(that.justBefore_) {}
0313
0314 inline lessVertex45& operator=(const lessVertex45& that) { x_ = that.x_; justBefore_ = that.justBefore_; return *this; }
0315
0316 template <typename ct>
0317 inline bool operator () (const Vertex45T<ct>& elm1, const Vertex45T<ct>& elm2) const {
0318 Unit y1 = elm1.evalAtX(*x_);
0319 Unit y2 = elm2.evalAtX(*x_);
0320 if(y1 < y2) return true;
0321 if(y1 == y2) {
0322
0323 if(*justBefore_) {
0324 return elm1.rise > elm2.rise;
0325 } else {
0326 return elm1.rise < elm2.rise;
0327 }
0328 }
0329 return false;
0330 }
0331 };
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341 static inline int classifyEdge45(const Point& prevPt, const Point& nextPt) {
0342 if(prevPt.x() == nextPt.x()) {
0343
0344 return predicated_value(prevPt.y() < nextPt.y(), 6, 2);
0345 }
0346 if(prevPt.y() == nextPt.y()) {
0347
0348 return predicated_value(prevPt.x() < nextPt.x(), 4, 0);
0349 }
0350 if(prevPt.x() < nextPt.x()) {
0351
0352 return predicated_value(prevPt.y() < nextPt.y(), 5, 3);
0353 }
0354
0355
0356 return predicated_value(prevPt.y() < nextPt.y(), 7, 1);
0357 }
0358
0359 template <int op, typename CountType>
0360 static int applyLogic(CountType count1, CountType count2){
0361 bool l1 = applyLogic<op>(count1);
0362 bool l2 = applyLogic<op>(count2);
0363 if(l1 && !l2)
0364 return -1;
0365 if(!l1 && l2)
0366 return 1;
0367 return 0;
0368 }
0369 template <int op>
0370 static bool applyLogic(Count2 count) {
0371 #ifdef BOOST_POLYGON_MSVC
0372 #pragma warning (push)
0373 #pragma warning (disable: 4127)
0374 #endif
0375 if(op == 0) {
0376 return count[0] > 0 || count[1] > 0;
0377 } else if(op == 1) {
0378 return count[0] > 0 && count[1] > 0;
0379 } else if(op == 2) {
0380 return count[0] > 0 && !(count[1] > 0);
0381 } else if(op == 3) {
0382 return (count[0] > 0) ^ (count[1] > 0);
0383 } else
0384 return false;
0385 #ifdef BOOST_POLYGON_MSVC
0386 #pragma warning (pop)
0387 #endif
0388 }
0389
0390 template <int op>
0391 struct boolean_op_45_output_functor {
0392 template <typename cT>
0393 void operator()(cT& output, const Count2& count1, const Count2& count2,
0394 const Point& pt, int rise, direction_1d end) {
0395 int edgeType = applyLogic<op>(count1, count2);
0396 if(edgeType) {
0397 int multiplier = end == LOW ? -1 : 1;
0398
0399 output.insert(output.end(), Vertex45(pt, rise, edgeType * multiplier));
0400
0401 }
0402 }
0403 };
0404
0405 template <int op>
0406 static bool applyLogic(Count1 count) {
0407 #ifdef BOOST_POLYGON_MSVC
0408 #pragma warning (push)
0409 #pragma warning (disable: 4127)
0410 #endif
0411 if(op == 0) {
0412 return count.count_ > 0;
0413 } else if(op == 1) {
0414 return count.count_ > 1;
0415 } else if(op == 3) {
0416 return (count.count_ % 2) != 0;
0417 } else
0418 return false;
0419 #ifdef BOOST_POLYGON_MSVC
0420 #pragma warning (pop)
0421 #endif
0422 }
0423
0424 template <int op>
0425 struct unary_op_45_output_functor {
0426 template <typename cT>
0427 void operator()(cT& output, const Count1& count1, const Count1& count2,
0428 const Point& pt, int rise, direction_1d end) {
0429 int edgeType = applyLogic<op>(count1, count2);
0430 if(edgeType) {
0431 int multiplier = end == LOW ? -1 : 1;
0432
0433 output.insert(output.end(), Vertex45(pt, rise, edgeType * multiplier));
0434
0435 }
0436 }
0437 };
0438
0439 class lessScan45Vertex {
0440 public:
0441 inline lessScan45Vertex() {}
0442 template <typename Scan45Vertex>
0443 inline bool operator () (const Scan45Vertex& v1, const Scan45Vertex& v2) const {
0444 return (v1.first.x() < v2.first.x()) || (v1.first.x() == v2.first.x() && v1.first.y() < v2.first.y());
0445 }
0446 };
0447 template <typename S45V>
0448 static inline void sortScan45Vector(S45V& vec) {
0449 polygon_sort(vec.begin(), vec.end(), lessScan45Vertex());
0450 }
0451
0452 template <typename CountType, typename output_functor>
0453 class Scan45 {
0454 public:
0455 typedef Scan45CountT<CountType> Scan45Count;
0456 typedef std::pair<Point, Scan45Count> Scan45Vertex;
0457
0458
0459 static inline Scan45Element getElement(const Scan45Vertex& vertex, int index) {
0460 return Scan45Element(vertex.first.x(), vertex.first.y(), index - 1, vertex.second[index]);
0461 }
0462
0463 class lessScan45Point {
0464 public:
0465 typedef Point first_argument_type;
0466 typedef Point second_argument_type;
0467 typedef bool result_type;
0468 inline lessScan45Point() {}
0469 inline bool operator () (const Point& v1, const Point& v2) const {
0470 return (v1.x() < v2.x()) || (v1.x() == v2.x() && v1.y() < v2.y());
0471 }
0472 };
0473
0474 typedef std::vector<Scan45Vertex> Scan45Vector;
0475
0476
0477 typedef std::set<Scan45ElementT<CountType>, lessScan45Element<CountType> > Scan45Data;
0478 typedef typename Scan45Data::iterator iterator;
0479 typedef typename Scan45Data::const_iterator const_iterator;
0480 typedef std::set<Point, lessScan45Point> CrossQueue;
0481
0482
0483 Scan45Data scanData_;
0484 CrossQueue crossQueue_;
0485 Scan45Vector crossVector_;
0486 Unit x_;
0487 int justBefore_;
0488 public:
0489 inline Scan45() : scanData_(), crossQueue_(), crossVector_(),
0490 x_((std::numeric_limits<Unit>::min)()), justBefore_(false) {
0491 lessScan45Element<CountType> lessElm(&x_, &justBefore_);
0492 scanData_ = std::set<Scan45ElementT<CountType>, lessScan45Element<CountType> >(lessElm);
0493 }
0494 inline Scan45(const Scan45& that) : scanData_(), crossQueue_(), crossVector_(),
0495 x_((std::numeric_limits<Unit>::min)()), justBefore_(false) {
0496 (*this) = that; }
0497 inline Scan45& operator=(const Scan45& that) {
0498 x_ = that.x_;
0499 justBefore_ = that.justBefore_;
0500 crossQueue_ = that.crossQueue_;
0501 crossVector_ = that.crossVector_;
0502 lessScan45Element<CountType> lessElm(&x_, &justBefore_);
0503 scanData_ = std::set<Scan45ElementT<CountType>, lessScan45Element<CountType> >(lessElm);
0504 for(const_iterator itr = that.scanData_.begin(); itr != that.scanData_.end(); ++itr){
0505 scanData_.insert(scanData_.end(), *itr);
0506 }
0507 return *this;
0508 }
0509
0510
0511
0512 template <class cT, class iT>
0513 void scan(cT& output, iT inputBegin, iT inputEnd) {
0514
0515 while(inputBegin != inputEnd) {
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529 Unit nextX = (*inputBegin).first.x();
0530 if(!crossVector_.empty() && crossVector_[0].first.x() < nextX) nextX = crossVector_[0].first.x();
0531 if(nextX != x_) {
0532
0533
0534
0535
0536 if(!crossQueue_.empty() &&
0537 (*crossQueue_.begin()).x() < nextX) {
0538
0539 nextX = (std::min)(nextX, (*crossQueue_.begin()).x());
0540 }
0541
0542 justBefore_ = true;
0543 x_ = nextX;
0544 advance_(output);
0545 justBefore_ = false;
0546 if(!crossVector_.empty() &&
0547 nextX == (*inputBegin).first.x()) {
0548 inputBegin = mergeCross_(inputBegin, inputEnd);
0549 }
0550 processEvent_(output, crossVector_.begin(), crossVector_.end());
0551 crossVector_.clear();
0552 } else {
0553
0554
0555 inputBegin = processEvent_(output, inputBegin, inputEnd);
0556 }
0557 }
0558
0559 }
0560
0561 private:
0562
0563
0564 template <class cT>
0565 inline void advance_(cT& output) {
0566
0567
0568 std::vector<iterator> eraseVec;
0569 while(!crossQueue_.empty() &&
0570 (*crossQueue_.begin()).x() == x_){
0571
0572
0573 Point crossPoint = *(crossQueue_.begin());
0574
0575
0576
0577
0578
0579
0580 crossQueue_.erase(crossQueue_.begin());
0581 Scan45Vertex vertex(crossPoint, Scan45Count());
0582 iterator lowIter = lookUp_(vertex.first.y());
0583
0584
0585
0586 if(lowIter == scanData_.end() ||
0587 lowIter->evalAtX(x_) != vertex.first.y()) {
0588
0589
0590 continue;
0591 }
0592 CountType countBelow;
0593 iterator searchDownItr = lowIter;
0594 while(searchDownItr != scanData_.begin()
0595 && searchDownItr->evalAtX(x_) == vertex.first.y()) {
0596
0597 --searchDownItr;
0598 countBelow = searchDownItr->count;
0599 }
0600
0601 Scan45Count count(countBelow);
0602 std::size_t numEdges = 0;
0603 iterator eraseItrs[3];
0604 while(lowIter != scanData_.end() &&
0605 lowIter->evalAtX(x_) == vertex.first.y()) {
0606 for(int index = lowIter->rise +1; index >= 0; --index)
0607 count[index] = lowIter->count;
0608
0609 eraseItrs[numEdges] = lowIter;
0610 ++numEdges;
0611 ++lowIter;
0612 }
0613 if(numEdges == 1) {
0614
0615
0616 findCross_(eraseItrs[0]);
0617 continue;
0618 }
0619
0620 CountType currentCount = countBelow;
0621 for(std::size_t i = 0; i < numEdges; ++i) {
0622 output_functor f;
0623 f(output, currentCount, eraseItrs[i]->count, crossPoint, eraseItrs[i]->rise, LOW);
0624 currentCount = eraseItrs[i]->count;
0625 }
0626
0627 for(std::size_t i = 0; i < numEdges; ++i) {
0628 eraseVec.push_back(eraseItrs[i]);
0629 }
0630
0631
0632 vertex.second[2] = count[2] - countBelow;
0633 vertex.second[1] = count[1] - count[2];
0634 vertex.second[0] = count[0] - count[1];
0635
0636
0637
0638
0639 crossVector_.push_back(vertex);
0640 }
0641
0642 std::vector<iterator> searchVec;
0643 for(std::size_t i = 0; i < eraseVec.size(); ++i) {
0644 if(eraseVec[i] != scanData_.begin()) {
0645 iterator searchItr = eraseVec[i];
0646 --searchItr;
0647 if(searchVec.empty() ||
0648 searchVec.back() != searchItr)
0649 searchVec.push_back(searchItr);
0650 }
0651 scanData_.erase(eraseVec[i]);
0652 }
0653 for(std::size_t i = 0; i < searchVec.size(); ++i) {
0654 findCross_(searchVec[i]);
0655 }
0656 }
0657
0658 template <class iT>
0659 inline iT mergeCross_(iT inputBegin, iT inputEnd) {
0660 Scan45Vector vec;
0661 swap(vec, crossVector_);
0662 iT mergeEnd = inputBegin;
0663 std::size_t mergeCount = 0;
0664 while(mergeEnd != inputEnd &&
0665 (*mergeEnd).first.x() == x_) {
0666 ++mergeCount;
0667 ++mergeEnd;
0668 }
0669 crossVector_.reserve((std::max)(vec.capacity(), vec.size() + mergeCount));
0670 for(std::size_t i = 0; i < vec.size(); ++i){
0671 while(inputBegin != mergeEnd &&
0672 (*inputBegin).first.y() < vec[i].first.y()) {
0673 crossVector_.push_back(*inputBegin);
0674 ++inputBegin;
0675 }
0676 crossVector_.push_back(vec[i]);
0677 }
0678 while(inputBegin != mergeEnd){
0679 crossVector_.push_back(*inputBegin);
0680 ++inputBegin;
0681 }
0682 return inputBegin;
0683 }
0684
0685 template <class cT, class iT>
0686 inline iT processEvent_(cT& output, iT inputBegin, iT inputEnd) {
0687
0688 CountType verticalCount = CountType();
0689 Point prevPoint;
0690 iterator prevIter = scanData_.end();
0691 while(inputBegin != inputEnd &&
0692 (*inputBegin).first.x() == x_) {
0693
0694
0695 Scan45Vertex vertex = *inputBegin;
0696
0697
0698 if(verticalCount != CountType() && (prevIter != scanData_.end() &&
0699 prevIter->evalAtX(x_) < vertex.first.y())) {
0700
0701 vertex = Scan45Vertex(Point(x_, prevIter->evalAtX(x_)), Scan45Count());
0702 } else {
0703 ++inputBegin;
0704
0705
0706 while(inputBegin != inputEnd &&
0707 (*inputBegin).first.x() == x_ &&
0708 (*inputBegin).first.y() == vertex.first.y()) {
0709
0710 vertex.second += (*inputBegin).second;
0711 ++inputBegin;
0712 }
0713 }
0714
0715
0716 CountType currentCount = verticalCount;
0717 for(unsigned int i = 0; i < 3; ++i) {
0718 vertex.second[i] = currentCount += vertex.second[i];
0719 }
0720
0721
0722
0723
0724 CountType countBelow;
0725 iterator lowIter = lookUp_(vertex.first.y());
0726 if(lowIter != scanData_.begin()) {
0727
0728 --lowIter;
0729 countBelow = lowIter->count;
0730 ++lowIter;
0731 }
0732
0733
0734 Scan45Count countAt(countBelow - verticalCount);
0735
0736 if(verticalCount != CountType()) {
0737 output_functor f;
0738 f(output, countBelow - verticalCount, countBelow, prevPoint, 2, HIGH);
0739 f(output, countBelow - verticalCount, countBelow, vertex.first, 2, LOW);
0740 }
0741 currentCount = countBelow - verticalCount;
0742 while(lowIter != scanData_.end() &&
0743 lowIter->evalAtX(x_) == vertex.first.y()) {
0744 for(unsigned int i = lowIter->rise + 1; i < 3; ++i) {
0745 countAt[i] = lowIter->count;
0746 }
0747 Point lp(lowIter->x, lowIter->y);
0748 if(lp != vertex.first) {
0749 output_functor f;
0750 f(output, currentCount, lowIter->count, vertex.first, lowIter->rise, LOW);
0751 }
0752 currentCount = lowIter->count;
0753 iterator nextIter = lowIter;
0754 ++nextIter;
0755
0756 scanData_.erase(lowIter);
0757 if(nextIter != scanData_.end())
0758 findCross_(nextIter);
0759 lowIter = nextIter;
0760 }
0761 verticalCount += vertex.second[3];
0762 prevPoint = vertex.first;
0763
0764 prevIter = lowIter;
0765
0766
0767
0768
0769 vertex.second += countAt;
0770
0771
0772
0773 for(int i = 0; i < 3; ++i) {
0774 if(vertex.second[i] != countBelow) {
0775
0776
0777 iterator insertIter = scanData_.insert(scanData_.end(),
0778 Scan45ElementT<CountType>(vertex.first.x(),
0779 vertex.first.y(),
0780 i - 1, vertex.second[i]));
0781 findCross_(insertIter);
0782 output_functor f;
0783 f(output, countBelow, vertex.second[i], vertex.first, i - 1, HIGH);
0784 }
0785 countBelow = vertex.second[i];
0786 }
0787 }
0788
0789 return inputBegin;
0790 }
0791
0792
0793 inline void scheduleCross0_(iterator iter1, iterator iter2) {
0794
0795 Unit y1 = iter1->evalAtX(x_);
0796 Unit y2 = iter2->evalAtX(x_);
0797 LongUnit delta = local_abs(LongUnit(y1) - LongUnit(y2));
0798 if(delta + static_cast<LongUnit>(x_) <= (std::numeric_limits<Unit>::max)())
0799 crossQueue_.insert(crossQueue_.end(), Point(x_ + static_cast<Unit>(delta), y1));
0800
0801 }
0802
0803
0804 inline void scheduleCross1_(iterator iter1, iterator iter2) {
0805
0806 Unit y1 = iter1->evalAtX(x_);
0807 Unit y2 = iter2->evalAtX(x_);
0808
0809
0810 LongUnit delta = y1;
0811 delta -= y2;
0812 Unit UnitMax = (std::numeric_limits<Unit>::max)();
0813 if((delta & 1) == 1) {
0814
0815 if(delta == 1) {
0816
0817
0818 std::string msg = "GTL 45 Boolean error, precision insufficient to represent edge intersection coordinate value.";
0819 throw(msg);
0820 } else {
0821
0822 LongUnit halfDelta2 = (LongUnit)((((LongUnit)y1) - y2)/2);
0823
0824 if(halfDelta2 + x_ <= UnitMax && halfDelta2 + y2 <= UnitMax) {
0825 crossQueue_.insert(crossQueue_.end(), Point(x_+static_cast<Unit>(halfDelta2), y2+static_cast<Unit>(halfDelta2)));
0826 crossQueue_.insert(crossQueue_.end(), Point(x_+static_cast<Unit>(halfDelta2), y2+static_cast<Unit>(halfDelta2)+1));
0827 }
0828 }
0829 } else {
0830 LongUnit halfDelta = (LongUnit)((((LongUnit)y1) - y2)/2);
0831 if(halfDelta + x_ <= UnitMax && halfDelta + y2 <= UnitMax)
0832 crossQueue_.insert(crossQueue_.end(), Point(x_+static_cast<Unit>(halfDelta), y2+static_cast<Unit>(halfDelta)));
0833
0834 }
0835 }
0836
0837 inline void findCross_(iterator iter) {
0838
0839 iterator iteratorBelow = iter;
0840 iterator iteratorAbove = iter;
0841 if(iter != scanData_.begin() && iter->rise < 1) {
0842 --iteratorBelow;
0843 if(iter->rise == 0){
0844 if(iteratorBelow->rise == 1) {
0845 scheduleCross0_(iter, iteratorBelow);
0846 }
0847 } else {
0848
0849 if(iteratorBelow->rise == 1) {
0850 scheduleCross1_(iter, iteratorBelow);
0851 } else if(iteratorBelow->rise == 0) {
0852 scheduleCross0_(iteratorBelow, iter);
0853 }
0854 }
0855 }
0856 ++iteratorAbove;
0857 if(iteratorAbove != scanData_.end() && iter->rise > -1) {
0858 if(iter->rise == 0) {
0859 if(iteratorAbove->rise == -1) {
0860 scheduleCross0_(iter, iteratorAbove);
0861 }
0862 } else {
0863
0864 if(iteratorAbove->rise == -1) {
0865 scheduleCross1_(iteratorAbove, iter);
0866 } else if(iteratorAbove->rise == 0) {
0867 scheduleCross0_(iteratorAbove, iter);
0868 }
0869 }
0870 }
0871
0872 }
0873
0874 inline iterator lookUp_(Unit y){
0875
0876 return scanData_.lower_bound(Scan45ElementT<CountType>(x_, y, -1+2*justBefore_));
0877 }
0878 };
0879
0880
0881
0882
0883
0884
0885
0886
0887
0888
0889 template <typename streamtype>
0890 static inline bool testScan45Data(streamtype& stdcout) {
0891 Unit x = 0;
0892 int justBefore = false;
0893 lessScan45Element<Count2> lessElm(&x, &justBefore);
0894 std::set<Scan45ElementT<Count2>, lessScan45Element<Count2> > testData(lessElm);
0895
0896 typedef std::set<Scan45ElementT<Count2>, lessScan45Element<Count2> > Scan45Data;
0897 typename Scan45Data::iterator itr10 = testData.insert(testData.end(), Scan45Element(0, 10, 1));
0898 typename Scan45Data::iterator itr20 = testData.insert(testData.end(), Scan45Element(0, 20, 1));
0899 typename Scan45Data::iterator itr30 = testData.insert(testData.end(), Scan45Element(0, 30, -1));
0900 typename Scan45Data::iterator itr40 = testData.insert(testData.end(), Scan45Element(0, 40, -1));
0901 typename Scan45Data::iterator itrA = testData.lower_bound(Scan45Element(0, 29, -1));
0902 typename Scan45Data::iterator itr1 = testData.lower_bound(Scan45Element(0, 10, -1));
0903 x = 4;
0904
0905 typename Scan45Data::iterator itrB = testData.lower_bound(Scan45Element(4, 29, -1));
0906 typename Scan45Data::iterator itr2 = testData.lower_bound(Scan45Element(4, 14, -1));
0907 if(itr1 != itr2) stdcout << "test1 failed\n";
0908 if(itrA == itrB) stdcout << "test2 failed\n";
0909
0910 testData.erase(itr20);
0911 testData.erase(itr30);
0912 x = 5;
0913 itr20 = testData.insert(testData.end(), Scan45Element(0, 20, 1));
0914 itr30 = testData.insert(testData.end(), Scan45Element(0, 30, -1));
0915
0916 typename Scan45Data::iterator itr = testData.begin();
0917 if(itr != itr10) stdcout << "test3 failed\n";
0918 ++itr;
0919 if(itr != itr30) stdcout << "test4 failed\n";
0920 ++itr;
0921 if(itr != itr20) stdcout << "test5 failed\n";
0922 ++itr;
0923 if(itr != itr40) stdcout << "test6 failed\n";
0924 stdcout << "done testing Scan45Data\n";
0925 return true;
0926 }
0927
0928 template <typename stream_type>
0929 static inline bool testScan45Rect(stream_type& stdcout) {
0930 stdcout << "testing Scan45Rect\n";
0931 Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
0932 std::vector<Vertex45 > result;
0933 typedef std::pair<Point, Scan45Count> Scan45Vertex;
0934 std::vector<Scan45Vertex> vertices;
0935
0936 Count2 count(1, 0);
0937 Count2 ncount(-1, 0);
0938 vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
0939 vertices.push_back(Scan45Vertex(Point(0,10), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
0940 vertices.push_back(Scan45Vertex(Point(10,0), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
0941 vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
0942 stdcout << "scanning\n";
0943 scan45.scan(result, vertices.begin(), vertices.end());
0944 stdcout << "done scanning\n";
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954 std::vector<Vertex45> reference;
0955 reference.push_back(Vertex45(Point(0, 0), 0, 1));
0956 reference.push_back(Vertex45(Point(0, 0), 2, 1));
0957 reference.push_back(Vertex45(Point(0, 10), 2, -1));
0958 reference.push_back(Vertex45(Point(0, 10), 0, -1));
0959 reference.push_back(Vertex45(Point(10, 0), 0, -1));
0960 reference.push_back(Vertex45(Point(10, 0), 2, -1));
0961 reference.push_back(Vertex45(Point(10, 10), 2, 1));
0962 reference.push_back(Vertex45(Point(10, 10), 0, 1));
0963 if(result != reference) {
0964 stdcout << "result size == " << result.size() << "\n";
0965 for(std::size_t i = 0; i < result.size(); ++i) {
0966
0967 }
0968 stdcout << "reference size == " << reference.size() << "\n";
0969 for(std::size_t i = 0; i < reference.size(); ++i) {
0970
0971 }
0972 return false;
0973 }
0974 stdcout << "done testing Scan45Rect\n";
0975 return true;
0976 }
0977
0978 template <typename stream_type>
0979 static inline bool testScan45P1(stream_type& stdcout) {
0980 stdcout << "testing Scan45P1\n";
0981 Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
0982 std::vector<Vertex45 > result;
0983 typedef std::pair<Point, Scan45Count> Scan45Vertex;
0984 std::vector<Scan45Vertex> vertices;
0985
0986 Count2 count(1, 0);
0987 Count2 ncount(-1, 0);
0988 vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
0989 vertices.push_back(Scan45Vertex(Point(0,10), Scan45Count(Count2(0, 0), Count2(0, 0), ncount, ncount)));
0990 vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), Count2(0, 0), ncount, ncount)));
0991 vertices.push_back(Scan45Vertex(Point(10,20), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
0992 stdcout << "scanning\n";
0993 scan45.scan(result, vertices.begin(), vertices.end());
0994 stdcout << "done scanning\n";
0995
0996
0997
0998
0999
1000
1001
1002
1003
1004 std::vector<Vertex45> reference;
1005 reference.push_back(Vertex45(Point(0, 0), 1, 1));
1006 reference.push_back(Vertex45(Point(0, 0), 2, 1));
1007 reference.push_back(Vertex45(Point(0, 10), 2, -1));
1008 reference.push_back(Vertex45(Point(0, 10), 1, -1));
1009 reference.push_back(Vertex45(Point(10, 10), 1, -1));
1010 reference.push_back(Vertex45(Point(10, 10), 2, -1));
1011 reference.push_back(Vertex45(Point(10, 20), 2, 1));
1012 reference.push_back(Vertex45(Point(10, 20), 1, 1));
1013 if(result != reference) {
1014 stdcout << "result size == " << result.size() << "\n";
1015 for(std::size_t i = 0; i < result.size(); ++i) {
1016
1017 }
1018 stdcout << "reference size == " << reference.size() << "\n";
1019 for(std::size_t i = 0; i < reference.size(); ++i) {
1020
1021 }
1022 return false;
1023 }
1024 stdcout << "done testing Scan45P1\n";
1025 return true;
1026 }
1027
1028 template <typename stream_type>
1029 static inline bool testScan45P2(stream_type& stdcout) {
1030 stdcout << "testing Scan45P2\n";
1031 Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
1032 std::vector<Vertex45 > result;
1033 typedef std::pair<Point, Scan45Count> Scan45Vertex;
1034 std::vector<Scan45Vertex> vertices;
1035
1036 Count2 count(1, 0);
1037 Count2 ncount(-1, 0);
1038 vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
1039 vertices.push_back(Scan45Vertex(Point(10,0), Scan45Count(Count2(0, 0), ncount, count, Count2(0, 0))));
1040 vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), ncount, count, Count2(0, 0))));
1041 vertices.push_back(Scan45Vertex(Point(20,10), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
1042 stdcout << "scanning\n";
1043 scan45.scan(result, vertices.begin(), vertices.end());
1044 stdcout << "done scanning\n";
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054 std::vector<Vertex45> reference;
1055 reference.push_back(Vertex45(Point(0, 0), 0, 1));
1056 reference.push_back(Vertex45(Point(0, 0), 1, -1));
1057 reference.push_back(Vertex45(Point(10, 0), 0, -1));
1058 reference.push_back(Vertex45(Point(10, 0), 1, 1));
1059 reference.push_back(Vertex45(Point(10, 10), 1, 1));
1060 reference.push_back(Vertex45(Point(10, 10), 0, -1));
1061 reference.push_back(Vertex45(Point(20, 10), 1, -1));
1062 reference.push_back(Vertex45(Point(20, 10), 0, 1));
1063 if(result != reference) {
1064 stdcout << "result size == " << result.size() << "\n";
1065 for(std::size_t i = 0; i < result.size(); ++i) {
1066
1067 }
1068 stdcout << "reference size == " << reference.size() << "\n";
1069 for(std::size_t i = 0; i < reference.size(); ++i) {
1070
1071 }
1072 return false;
1073 }
1074 stdcout << "done testing Scan45P2\n";
1075 return true;
1076 }
1077
1078 template <typename streamtype>
1079 static inline bool testScan45And(streamtype& stdcout) {
1080 stdcout << "testing Scan45And\n";
1081 Scan45<Count2, boolean_op_45_output_functor<1> > scan45;
1082 std::vector<Vertex45 > result;
1083 typedef std::pair<Point, Scan45Count> Scan45Vertex;
1084 std::vector<Scan45Vertex> vertices;
1085
1086 Count2 count(1, 0);
1087 Count2 ncount(-1, 0);
1088 vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
1089 vertices.push_back(Scan45Vertex(Point(0,10), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
1090 vertices.push_back(Scan45Vertex(Point(10,0), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
1091 vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
1092 count = Count2(0, 1);
1093 ncount = count.invert();
1094 vertices.push_back(Scan45Vertex(Point(2,2), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
1095 vertices.push_back(Scan45Vertex(Point(2,12), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
1096 vertices.push_back(Scan45Vertex(Point(12,2), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
1097 vertices.push_back(Scan45Vertex(Point(12,12), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
1098 sortScan45Vector(vertices);
1099 stdcout << "scanning\n";
1100 scan45.scan(result, vertices.begin(), vertices.end());
1101 stdcout << "done scanning\n";
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111 std::vector<Vertex45> reference;
1112 reference.push_back(Vertex45(Point(2, 2), 0, 1));
1113 reference.push_back(Vertex45(Point(2, 2), 2, 1));
1114 reference.push_back(Vertex45(Point(2, 10), 2, -1));
1115 reference.push_back(Vertex45(Point(2, 10), 0, -1));
1116 reference.push_back(Vertex45(Point(10, 2), 0, -1));
1117 reference.push_back(Vertex45(Point(10, 2), 2, -1));
1118 reference.push_back(Vertex45(Point(10, 10), 2, 1));
1119 reference.push_back(Vertex45(Point(10, 10), 0, 1));
1120 if(result != reference) {
1121 stdcout << "result size == " << result.size() << "\n";
1122 for(std::size_t i = 0; i < result.size(); ++i) {
1123
1124 }
1125 stdcout << "reference size == " << reference.size() << "\n";
1126 for(std::size_t i = 0; i < reference.size(); ++i) {
1127
1128 }
1129 return false;
1130 }
1131 stdcout << "done testing Scan45And\n";
1132 return true;
1133 }
1134
1135 template <typename stream_type>
1136 static inline bool testScan45Star1(stream_type& stdcout) {
1137 stdcout << "testing Scan45Star1\n";
1138 Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
1139 std::vector<Vertex45 > result;
1140 typedef std::pair<Point, Scan45Count> Scan45Vertex;
1141 std::vector<Scan45Vertex> vertices;
1142
1143 Count2 count(1, 0);
1144 Count2 ncount(-1, 0);
1145 vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0))));
1146 vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount)));
1147 vertices.push_back(Scan45Vertex(Point(8,16), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
1148 count = Count2(0, 1);
1149 ncount = count.invert();
1150 vertices.push_back(Scan45Vertex(Point(12,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0))));
1151 vertices.push_back(Scan45Vertex(Point(4,0), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
1152 vertices.push_back(Scan45Vertex(Point(4,16), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount)));
1153 sortScan45Vector(vertices);
1154 stdcout << "scanning\n";
1155 scan45.scan(result, vertices.begin(), vertices.end());
1156 stdcout << "done scanning\n";
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182 if(result.size() != 24) {
1183
1184
1185 return false;
1186 }
1187 stdcout << "done testing Scan45Star1\n";
1188 return true;
1189 }
1190
1191 template <typename stream_type>
1192 static inline bool testScan45Star2(stream_type& stdcout) {
1193 stdcout << "testing Scan45Star2\n";
1194 Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
1195 std::vector<Vertex45 > result;
1196 typedef std::pair<Point, Scan45Count> Scan45Vertex;
1197 std::vector<Scan45Vertex> vertices;
1198
1199 Count2 count(1, 0);
1200 Count2 ncount(-1, 0);
1201 vertices.push_back(Scan45Vertex(Point(0,4), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
1202 vertices.push_back(Scan45Vertex(Point(16,4), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
1203 vertices.push_back(Scan45Vertex(Point(8,12), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
1204 count = Count2(0, 1);
1205 ncount = count.invert();
1206 vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
1207 vertices.push_back(Scan45Vertex(Point(16,8), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
1208 vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
1209 sortScan45Vector(vertices);
1210 stdcout << "scanning\n";
1211 scan45.scan(result, vertices.begin(), vertices.end());
1212 stdcout << "done scanning\n";
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238 if(result.size() != 24) {
1239
1240
1241 return false;
1242 }
1243 stdcout << "done testing Scan45Star2\n";
1244 return true;
1245 }
1246
1247 template <typename stream_type>
1248 static inline bool testScan45Star3(stream_type& stdcout) {
1249 stdcout << "testing Scan45Star3\n";
1250 Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
1251 std::vector<Vertex45 > result;
1252 typedef std::pair<Point, Scan45Count> Scan45Vertex;
1253 std::vector<Scan45Vertex> vertices;
1254
1255 Count2 count(1, 0);
1256 Count2 ncount(-1, 0);
1257 vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0))));
1258 vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount)));
1259 vertices.push_back(Scan45Vertex(Point(8,16), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
1260
1261 vertices.push_back(Scan45Vertex(Point(6,0), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
1262 vertices.push_back(Scan45Vertex(Point(6,14), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
1263 vertices.push_back(Scan45Vertex(Point(12,0), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
1264 vertices.push_back(Scan45Vertex(Point(12,14), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
1265 count = Count2(0, 1);
1266 ncount = count.invert();
1267 vertices.push_back(Scan45Vertex(Point(12,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0))));
1268 vertices.push_back(Scan45Vertex(Point(4,0), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
1269 vertices.push_back(Scan45Vertex(Point(4,16), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount)));
1270 sortScan45Vector(vertices);
1271 stdcout << "scanning\n";
1272 scan45.scan(result, vertices.begin(), vertices.end());
1273 stdcout << "done scanning\n";
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303 if(result.size() != 28) {
1304
1305
1306 return false;
1307 }
1308
1309 stdcout << "done testing Scan45Star3\n";
1310 return true;
1311 }
1312
1313
1314 template <typename stream_type>
1315 static inline bool testScan45Star4(stream_type& stdcout) {
1316 stdcout << "testing Scan45Star4\n";
1317 Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
1318 std::vector<Vertex45 > result;
1319 typedef std::pair<Point, Scan45Count> Scan45Vertex;
1320 std::vector<Scan45Vertex> vertices;
1321
1322 Count2 count(1, 0);
1323 Count2 ncount(-1, 0);
1324 vertices.push_back(Scan45Vertex(Point(0,4), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
1325 vertices.push_back(Scan45Vertex(Point(16,4), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
1326 vertices.push_back(Scan45Vertex(Point(8,12), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
1327
1328 vertices.push_back(Scan45Vertex(Point(0,6), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
1329 vertices.push_back(Scan45Vertex(Point(0,12), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
1330 vertices.push_back(Scan45Vertex(Point(16,6), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
1331 vertices.push_back(Scan45Vertex(Point(16,12), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
1332 count = Count2(0, 1);
1333 ncount = count.invert();
1334 vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
1335 vertices.push_back(Scan45Vertex(Point(16,8), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
1336 vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
1337 sortScan45Vector(vertices);
1338 stdcout << "scanning\n";
1339 scan45.scan(result, vertices.begin(), vertices.end());
1340 stdcout << "done scanning\n";
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370 if(result.size() != 28) {
1371
1372
1373 return false;
1374 }
1375
1376 stdcout << "done testing Scan45Star4\n";
1377 return true;
1378 }
1379
1380 template <typename stream_type>
1381 static inline bool testScan45(stream_type& stdcout) {
1382 if(!testScan45Rect(stdcout)) return false;
1383 if(!testScan45P1(stdcout)) return false;
1384 if(!testScan45P2(stdcout)) return false;
1385 if(!testScan45And(stdcout)) return false;
1386 if(!testScan45Star1(stdcout)) return false;
1387 if(!testScan45Star2(stdcout)) return false;
1388 if(!testScan45Star3(stdcout)) return false;
1389 if(!testScan45Star4(stdcout)) return false;
1390 return true;
1391 }
1392
1393 };
1394
1395 }
1396
1397 }
1398 #endif