]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/polygon/detail/polygon_45_formation.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / polygon / detail / polygon_45_formation.hpp
1 /*
2 Copyright 2008 Intel Corporation
3
4 Use, modification and distribution are subject to the Boost Software License,
5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 http://www.boost.org/LICENSE_1_0.txt).
7 */
8 #ifndef BOOST_POLYGON_POLYGON_45_FORMATION_HPP
9 #define BOOST_POLYGON_POLYGON_45_FORMATION_HPP
10 namespace boost { namespace polygon{
11
12 template <typename T, typename T2>
13 struct PolyLineByConcept {};
14
15 template <typename T>
16 class PolyLine45PolygonData;
17 template <typename T>
18 class PolyLine45HoleData;
19
20 //polygon45formation algorithm
21 template <typename Unit>
22 struct polygon_45_formation : public boolean_op_45<Unit> {
23 typedef point_data<Unit> Point;
24 typedef polygon_45_data<Unit> Polygon45;
25 typedef polygon_45_with_holes_data<Unit> Polygon45WithHoles;
26 typedef typename boolean_op_45<Unit>::Vertex45 Vertex45;
27 typedef typename boolean_op_45<Unit>::lessVertex45 lessVertex45;
28 typedef typename boolean_op_45<Unit>::Count2 Count2;
29 typedef typename boolean_op_45<Unit>::Scan45Count Scan45Count;
30 typedef std::pair<Point, Scan45Count> Scan45Vertex;
31 typedef typename boolean_op_45<Unit>::template
32 Scan45<Count2, typename boolean_op_45<Unit>::template boolean_op_45_output_functor<0> > Scan45;
33
34 class PolyLine45 {
35 public:
36 typedef typename std::list<Point>::const_iterator iterator;
37
38 // default constructor of point does not initialize x and y
39 inline PolyLine45() : points() {} //do nothing default constructor
40
41 // initialize a polygon from x,y values, it is assumed that the first is an x
42 // and that the input is a well behaved polygon
43 template<class iT>
44 inline PolyLine45& set(iT inputBegin, iT inputEnd) {
45 points.clear(); //just in case there was some old data there
46 while(inputBegin != inputEnd) {
47 points.insert(points.end(), *inputBegin);
48 ++inputBegin;
49 }
50 return *this;
51 }
52
53 // copy constructor (since we have dynamic memory)
54 inline PolyLine45(const PolyLine45& that) : points(that.points) {}
55
56 // assignment operator (since we have dynamic memory do a deep copy)
57 inline PolyLine45& operator=(const PolyLine45& that) {
58 points = that.points;
59 return *this;
60 }
61
62 // get begin iterator, returns a pointer to a const Unit
63 inline iterator begin() const { return points.begin(); }
64
65 // get end iterator, returns a pointer to a const Unit
66 inline iterator end() const { return points.end(); }
67
68 inline std::size_t size() const { return points.size(); }
69
70 //public data member
71 std::list<Point> points;
72 };
73
74 class ActiveTail45 {
75 private:
76 //data
77 PolyLine45* tailp_;
78 ActiveTail45 *otherTailp_;
79 std::list<ActiveTail45*> holesList_;
80 bool head_;
81 public:
82
83 /**
84 * @brief iterator over coordinates of the figure
85 */
86 typedef typename PolyLine45::iterator iterator;
87
88 /**
89 * @brief iterator over holes contained within the figure
90 */
91 typedef typename std::list<ActiveTail45*>::const_iterator iteratorHoles;
92
93 //default constructor
94 inline ActiveTail45() : tailp_(0), otherTailp_(0), holesList_(), head_(0) {}
95
96 //constructor
97 inline ActiveTail45(const Vertex45& vertex, ActiveTail45* otherTailp = 0) :
98 tailp_(0), otherTailp_(0), holesList_(), head_(0) {
99 tailp_ = new PolyLine45;
100 tailp_->points.push_back(vertex.pt);
101 bool headArray[4] = {false, true, true, true};
102 bool inverted = vertex.count == -1;
103 head_ = headArray[vertex.rise+1] ^ inverted;
104 otherTailp_ = otherTailp;
105 }
106
107 inline ActiveTail45(Point point, ActiveTail45* otherTailp, bool head = true) :
108 tailp_(0), otherTailp_(0), holesList_(), head_(0) {
109 tailp_ = new PolyLine45;
110 tailp_->points.push_back(point);
111 head_ = head;
112 otherTailp_ = otherTailp;
113
114 }
115 inline ActiveTail45(ActiveTail45* otherTailp) :
116 tailp_(0), otherTailp_(0), holesList_(), head_(0) {
117 tailp_ = otherTailp->tailp_;
118 otherTailp_ = otherTailp;
119 }
120
121 //copy constructor
122 inline ActiveTail45(const ActiveTail45& that) :
123 tailp_(0), otherTailp_(0), holesList_(), head_(0) { (*this) = that; }
124
125 //destructor
126 inline ~ActiveTail45() {
127 destroyContents();
128 }
129
130 //assignment operator
131 inline ActiveTail45& operator=(const ActiveTail45& that) {
132 tailp_ = new PolyLine45(*(that.tailp_));
133 head_ = that.head_;
134 otherTailp_ = that.otherTailp_;
135 holesList_ = that.holesList_;
136 return *this;
137 }
138
139 //equivalence operator
140 inline bool operator==(const ActiveTail45& b) const {
141 return tailp_ == b.tailp_ && head_ == b.head_;
142 }
143
144 /**
145 * @brief get the pointer to the polyline that this is an active tail of
146 */
147 inline PolyLine45* getTail() const { return tailp_; }
148
149 /**
150 * @brief get the pointer to the polyline at the other end of the chain
151 */
152 inline PolyLine45* getOtherTail() const { return otherTailp_->tailp_; }
153
154 /**
155 * @brief get the pointer to the activetail at the other end of the chain
156 */
157 inline ActiveTail45* getOtherActiveTail() const { return otherTailp_; }
158
159 /**
160 * @brief test if another active tail is the other end of the chain
161 */
162 inline bool isOtherTail(const ActiveTail45& b) const { return &b == otherTailp_; }
163
164 /**
165 * @brief update this end of chain pointer to new polyline
166 */
167 inline ActiveTail45& updateTail(PolyLine45* newTail) { tailp_ = newTail; return *this; }
168
169 inline bool join(ActiveTail45* tail) {
170 if(tail == otherTailp_) {
171 //std::cout << "joining to other tail!\n";
172 return false;
173 }
174 if(tail->head_ == head_) {
175 //std::cout << "joining head to head!\n";
176 return false;
177 }
178 if(!tailp_) {
179 //std::cout << "joining empty tail!\n";
180 return false;
181 }
182 if(!(otherTailp_->head_)) {
183 otherTailp_->copyHoles(*tail);
184 otherTailp_->copyHoles(*this);
185 } else {
186 tail->otherTailp_->copyHoles(*this);
187 tail->otherTailp_->copyHoles(*tail);
188 }
189 PolyLine45* tail1 = tailp_;
190 PolyLine45* tail2 = tail->tailp_;
191 if(head_) std::swap(tail1, tail2);
192 tail1->points.splice(tail1->points.end(), tail2->points);
193 delete tail2;
194 otherTailp_->tailp_ = tail1;
195 tail->otherTailp_->tailp_ = tail1;
196 otherTailp_->otherTailp_ = tail->otherTailp_;
197 tail->otherTailp_->otherTailp_ = otherTailp_;
198 tailp_ = 0;
199 tail->tailp_ = 0;
200 tail->otherTailp_ = 0;
201 otherTailp_ = 0;
202 return true;
203 }
204
205 /**
206 * @brief associate a hole to this active tail by the specified policy
207 */
208 inline ActiveTail45* addHole(ActiveTail45* hole) {
209 holesList_.push_back(hole);
210 copyHoles(*hole);
211 copyHoles(*(hole->otherTailp_));
212 return this;
213 }
214
215 /**
216 * @brief get the list of holes
217 */
218 inline const std::list<ActiveTail45*>& getHoles() const { return holesList_; }
219
220 /**
221 * @brief copy holes from that to this
222 */
223 inline void copyHoles(ActiveTail45& that) { holesList_.splice(holesList_.end(), that.holesList_); }
224
225 /**
226 * @brief find out if solid to right
227 */
228 inline bool solidToRight() const { return !head_; }
229 inline bool solidToLeft() const { return head_; }
230
231 /**
232 * @brief get vertex
233 */
234 inline Point getPoint() const {
235 if(head_) return tailp_->points.front();
236 return tailp_->points.back();
237 }
238
239 /**
240 * @brief add a coordinate to the polygon at this active tail end, properly handle degenerate edges by removing redundant coordinate
241 */
242 inline void pushPoint(Point point) {
243 if(head_) {
244 //if(tailp_->points.size() < 2) {
245 // tailp_->points.push_front(point);
246 // return;
247 //}
248 typename std::list<Point>::iterator iter = tailp_->points.begin();
249 if(iter == tailp_->points.end()) {
250 tailp_->points.push_front(point);
251 return;
252 }
253 Unit firstY = (*iter).y();
254 Unit firstX = (*iter).x();
255 ++iter;
256 if(iter == tailp_->points.end()) {
257 tailp_->points.push_front(point);
258 return;
259 }
260 if((iter->y() == point.y() && firstY == point.y()) ||
261 (iter->x() == point.x() && firstX == point.x())){
262 --iter;
263 *iter = point;
264 } else {
265 tailp_->points.push_front(point);
266 }
267 return;
268 }
269 //if(tailp_->points.size() < 2) {
270 // tailp_->points.push_back(point);
271 // return;
272 //}
273 typename std::list<Point>::reverse_iterator iter = tailp_->points.rbegin();
274 if(iter == tailp_->points.rend()) {
275 tailp_->points.push_back(point);
276 return;
277 }
278 Unit firstY = (*iter).y();
279 Unit firstX = (*iter).x();
280 ++iter;
281 if(iter == tailp_->points.rend()) {
282 tailp_->points.push_back(point);
283 return;
284 }
285 if((iter->y() == point.y() && firstY == point.y()) ||
286 (iter->x() == point.x() && firstX == point.x())){
287 --iter;
288 *iter = point;
289 } else {
290 tailp_->points.push_back(point);
291 }
292 }
293
294 /**
295 * @brief joins the two chains that the two active tail tails are ends of
296 * checks for closure of figure and writes out polygons appropriately
297 * returns a handle to a hole if one is closed
298 */
299
300 template <class cT>
301 static inline ActiveTail45* joinChains(Point point, ActiveTail45* at1, ActiveTail45* at2, bool solid,
302 cT& output) {
303 if(at1->otherTailp_ == at2) {
304 //if(at2->otherTailp_ != at1) std::cout << "half closed error\n";
305 //we are closing a figure
306 at1->pushPoint(point);
307 at2->pushPoint(point);
308 if(solid) {
309 //we are closing a solid figure, write to output
310 //std::cout << "test1\n";
311 at1->copyHoles(*(at1->otherTailp_));
312 //std::cout << "test2\n";
313 //Polygon45WithHolesImpl<PolyLine45PolygonData> poly(polyData);
314 //std::cout << poly << "\n";
315 //std::cout << "test3\n";
316 typedef typename cT::value_type pType;
317 output.push_back(pType());
318 typedef typename geometry_concept<pType>::type cType;
319 typename PolyLineByConcept<Unit, cType>::type polyData(at1);
320 assign(output.back(), polyData);
321 //std::cout << "test4\n";
322 //std::cout << "delete " << at1->otherTailp_ << "\n";
323 //at1->print();
324 //at1->otherTailp_->print();
325 delete at1->otherTailp_;
326 //at1->print();
327 //at1->otherTailp_->print();
328 //std::cout << "test5\n";
329 //std::cout << "delete " << at1 << "\n";
330 delete at1;
331 //std::cout << "test6\n";
332 return 0;
333 } else {
334 //we are closing a hole, return the tail end active tail of the figure
335 return at1;
336 }
337 }
338 //we are not closing a figure
339 at1->pushPoint(point);
340 at1->join(at2);
341 delete at1;
342 delete at2;
343 return 0;
344 }
345
346 inline void destroyContents() {
347 if(otherTailp_) {
348 //std::cout << "delete p " << tailp_ << "\n";
349 if(tailp_) delete tailp_;
350 tailp_ = 0;
351 otherTailp_->otherTailp_ = 0;
352 otherTailp_->tailp_ = 0;
353 otherTailp_ = 0;
354 }
355 for(typename std::list<ActiveTail45*>::iterator itr = holesList_.begin(); itr != holesList_.end(); ++itr) {
356 //std::cout << "delete p " << (*itr) << "\n";
357 if(*itr) {
358 if((*itr)->otherTailp_) {
359 delete (*itr)->otherTailp_;
360 (*itr)->otherTailp_ = 0;
361 }
362 delete (*itr);
363 }
364 (*itr) = 0;
365 }
366 holesList_.clear();
367 }
368
369 // inline void print() {
370 // std::cout << this << " " << tailp_ << " " << otherTailp_ << " " << holesList_.size() << " " << head_ << "\n";
371 // }
372
373 static inline std::pair<ActiveTail45*, ActiveTail45*> createActiveTail45sAsPair(Point point, bool solid,
374 ActiveTail45* phole, bool fractureHoles) {
375 ActiveTail45* at1 = 0;
376 ActiveTail45* at2 = 0;
377 if(phole && fractureHoles) {
378 //std::cout << "adding hole\n";
379 at1 = phole;
380 //assert solid == false, we should be creating a corner with solid below and to the left if there was a hole
381 at2 = at1->getOtherActiveTail();
382 at2->pushPoint(point);
383 at1->pushPoint(point);
384 } else {
385 at1 = new ActiveTail45(point, at2, solid);
386 at2 = new ActiveTail45(at1);
387 at1->otherTailp_ = at2;
388 at2->head_ = !solid;
389 if(phole)
390 at2->addHole(phole); //assert fractureHoles == false
391 }
392 return std::pair<ActiveTail45*, ActiveTail45*>(at1, at2);
393 }
394
395 };
396
397 template <typename ct>
398 class Vertex45CountT {
399 public:
400 typedef ct count_type;
401 inline Vertex45CountT()
402 #ifndef BOOST_POLYGON_MSVC
403 : counts()
404 #endif
405 { counts[0] = counts[1] = counts[2] = counts[3] = 0; }
406 //inline Vertex45CountT(ct count) { counts[0] = counts[1] = counts[2] = counts[3] = count; }
407 inline Vertex45CountT(const ct& count1, const ct& count2, const ct& count3,
408 const ct& count4)
409 #ifndef BOOST_POLYGON_MSVC
410 : counts()
411 #endif
412 {
413 counts[0] = count1;
414 counts[1] = count2;
415 counts[2] = count3;
416 counts[3] = count4;
417 }
418 inline Vertex45CountT(const Vertex45& vertex)
419 #ifndef BOOST_POLYGON_MSVC
420 : counts()
421 #endif
422 {
423 counts[0] = counts[1] = counts[2] = counts[3] = 0;
424 (*this) += vertex;
425 }
426 inline Vertex45CountT(const Vertex45CountT& count)
427 #ifndef BOOST_POLYGON_MSVC
428 : counts()
429 #endif
430 {
431 (*this) = count;
432 }
433 inline bool operator==(const Vertex45CountT& count) const {
434 for(unsigned int i = 0; i < 4; ++i) {
435 if(counts[i] != count.counts[i]) return false;
436 }
437 return true;
438 }
439 inline bool operator!=(const Vertex45CountT& count) const { return !((*this) == count); }
440 inline Vertex45CountT& operator=(ct count) {
441 counts[0] = counts[1] = counts[2] = counts[3] = count; return *this; }
442 inline Vertex45CountT& operator=(const Vertex45CountT& count) {
443 for(unsigned int i = 0; i < 4; ++i) {
444 counts[i] = count.counts[i];
445 }
446 return *this;
447 }
448 inline ct& operator[](int index) { return counts[index]; }
449 inline ct operator[](int index) const {return counts[index]; }
450 inline Vertex45CountT& operator+=(const Vertex45CountT& count){
451 for(unsigned int i = 0; i < 4; ++i) {
452 counts[i] += count.counts[i];
453 }
454 return *this;
455 }
456 inline Vertex45CountT& operator-=(const Vertex45CountT& count){
457 for(unsigned int i = 0; i < 4; ++i) {
458 counts[i] -= count.counts[i];
459 }
460 return *this;
461 }
462 inline Vertex45CountT operator+(const Vertex45CountT& count) const {
463 return Vertex45CountT(*this)+=count;
464 }
465 inline Vertex45CountT operator-(const Vertex45CountT& count) const {
466 return Vertex45CountT(*this)-=count;
467 }
468 inline Vertex45CountT invert() const {
469 return Vertex45CountT()-=(*this);
470 }
471 inline Vertex45CountT& operator+=(const Vertex45& element){
472 counts[element.rise+1] += element.count; return *this;
473 }
474 inline bool is_45() const {
475 return counts[0] != 0 || counts[2] != 0;
476 }
477 private:
478 ct counts[4];
479 };
480
481 typedef Vertex45CountT<int> Vertex45Count;
482
483 // inline std::ostream& operator<< (std::ostream& o, const Vertex45Count& c) {
484 // o << c[0] << ", " << c[1] << ", ";
485 // o << c[2] << ", " << c[3];
486 // return o;
487 // }
488
489 template <typename ct>
490 class Vertex45CompactT {
491 public:
492 Point pt;
493 ct count;
494 typedef typename boolean_op_45<Unit>::template Vertex45T<typename ct::count_type> Vertex45T;
495 inline Vertex45CompactT() : pt(), count() {}
496 inline Vertex45CompactT(const Point& point, int riseIn, int countIn) : pt(point), count() {
497 count[riseIn+1] = countIn;
498 }
499 template <typename ct2>
500 inline Vertex45CompactT(const typename boolean_op_45<Unit>::template Vertex45T<ct2>& vertex) : pt(vertex.pt), count() {
501 count[vertex.rise+1] = vertex.count;
502 }
503 inline Vertex45CompactT(const Vertex45CompactT& vertex) : pt(vertex.pt), count(vertex.count) {}
504 inline Vertex45CompactT& operator=(const Vertex45CompactT& vertex){
505 pt = vertex.pt; count = vertex.count; return *this; }
506 inline bool operator==(const Vertex45CompactT& vertex) const {
507 return pt == vertex.pt && count == vertex.count; }
508 inline bool operator!=(const Vertex45CompactT& vertex) const { return !((*this) == vertex); }
509 inline bool operator<(const Vertex45CompactT& vertex) const {
510 if(pt.x() < vertex.pt.x()) return true;
511 if(pt.x() == vertex.pt.x()) {
512 return pt.y() < vertex.pt.y();
513 }
514 return false;
515 }
516 inline bool operator>(const Vertex45CompactT& vertex) const { return vertex < (*this); }
517 inline bool operator<=(const Vertex45CompactT& vertex) const { return !((*this) > vertex); }
518 inline bool operator>=(const Vertex45CompactT& vertex) const { return !((*this) < vertex); }
519 inline bool haveVertex45(int index) const { return count[index]; }
520 inline Vertex45T operator[](int index) const {
521 return Vertex45T(pt, index-1, count[index]); }
522 };
523
524 typedef Vertex45CompactT<Vertex45Count> Vertex45Compact;
525
526 // inline std::ostream& operator<< (std::ostream& o, const Vertex45Compact& c) {
527 // o << c.pt << ", " << c.count;
528 // return o;
529 // }
530
531 class Polygon45Formation {
532 private:
533 //definitions
534 typedef std::map<Vertex45, ActiveTail45*, lessVertex45> Polygon45FormationData;
535 typedef typename Polygon45FormationData::iterator iterator;
536 typedef typename Polygon45FormationData::const_iterator const_iterator;
537
538 //data
539 Polygon45FormationData scanData_;
540 Unit x_;
541 int justBefore_;
542 int fractureHoles_;
543 public:
544 inline Polygon45Formation() : scanData_(), x_((std::numeric_limits<Unit>::min)()), justBefore_(false), fractureHoles_(0) {
545 lessVertex45 lessElm(&x_, &justBefore_);
546 scanData_ = Polygon45FormationData(lessElm);
547 }
548 inline Polygon45Formation(bool fractureHoles) : scanData_(), x_((std::numeric_limits<Unit>::min)()), justBefore_(false), fractureHoles_(fractureHoles) {
549 lessVertex45 lessElm(&x_, &justBefore_);
550 scanData_ = Polygon45FormationData(lessElm);
551 }
552 inline Polygon45Formation(const Polygon45Formation& that) :
553 scanData_(), x_((std::numeric_limits<Unit>::min)()), justBefore_(false), fractureHoles_(0) { (*this) = that; }
554 inline Polygon45Formation& operator=(const Polygon45Formation& that) {
555 x_ = that.x_;
556 justBefore_ = that.justBefore_;
557 fractureHoles_ = that.fractureHoles_;
558 lessVertex45 lessElm(&x_, &justBefore_);
559 scanData_ = Polygon45FormationData(lessElm);
560 for(const_iterator itr = that.scanData_.begin(); itr != that.scanData_.end(); ++itr){
561 scanData_.insert(scanData_.end(), *itr);
562 }
563 return *this;
564 }
565
566 //cT is an output container of Polygon45 or Polygon45WithHoles
567 //iT is an iterator over Vertex45 elements
568 //inputBegin - inputEnd is a range of sorted iT that represents
569 //one or more scanline stops worth of data
570 template <class cT, class iT>
571 void scan(cT& output, iT inputBegin, iT inputEnd) {
572 //std::cout << "1\n";
573 while(inputBegin != inputEnd) {
574 //std::cout << "2\n";
575 x_ = (*inputBegin).pt.x();
576 //std::cout << "SCAN FORMATION " << x_ << "\n";
577 //std::cout << "x_ = " << x_ << "\n";
578 //std::cout << "scan line size: " << scanData_.size() << "\n";
579 inputBegin = processEvent_(output, inputBegin, inputEnd);
580 }
581 }
582
583 private:
584 //functions
585 template <class cT, class cT2>
586 inline std::pair<int, ActiveTail45*> processPoint_(cT& output, cT2& elements, Point point,
587 Vertex45Count& counts, ActiveTail45** tails, Vertex45Count& incoming) {
588 //std::cout << point << "\n";
589 //std::cout << counts[0] << " ";
590 //std::cout << counts[1] << " ";
591 //std::cout << counts[2] << " ";
592 //std::cout << counts[3] << "\n";
593 //std::cout << incoming[0] << " ";
594 //std::cout << incoming[1] << " ";
595 //std::cout << incoming[2] << " ";
596 //std::cout << incoming[3] << "\n";
597 //join any closing solid corners
598 ActiveTail45* returnValue = 0;
599 int returnCount = 0;
600 for(int i = 0; i < 3; ++i) {
601 //std::cout << i << "\n";
602 if(counts[i] == -1) {
603 //std::cout << "fixed i\n";
604 for(int j = i + 1; j < 4; ++j) {
605 //std::cout << j << "\n";
606 if(counts[j]) {
607 if(counts[j] == 1) {
608 //std::cout << "case1: " << i << " " << j << "\n";
609 //if a figure is closed it will be written out by this function to output
610 ActiveTail45::joinChains(point, tails[i], tails[j], true, output);
611 counts[i] = 0;
612 counts[j] = 0;
613 tails[i] = 0;
614 tails[j] = 0;
615 }
616 break;
617 }
618 }
619 }
620 }
621 //find any pairs of incoming edges that need to create pair for leading solid
622 //std::cout << "checking case2\n";
623 for(int i = 0; i < 3; ++i) {
624 //std::cout << i << "\n";
625 if(incoming[i] == 1) {
626 //std::cout << "fixed i\n";
627 for(int j = i + 1; j < 4; ++j) {
628 //std::cout << j << "\n";
629 if(incoming[j]) {
630 if(incoming[j] == -1) {
631 //std::cout << "case2: " << i << " " << j << "\n";
632 //std::cout << "creating active tail pair\n";
633 std::pair<ActiveTail45*, ActiveTail45*> tailPair =
634 ActiveTail45::createActiveTail45sAsPair(point, true, 0, fractureHoles_ != 0);
635 //tailPair.first->print();
636 //tailPair.second->print();
637 if(j == 3) {
638 //vertical active tail becomes return value
639 returnValue = tailPair.first;
640 returnCount = 1;
641 } else {
642 Vertex45 vertex(point, i -1, incoming[i]);
643 //std::cout << "new element " << j-1 << " " << -1 << "\n";
644 elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, -1), tailPair.first));
645 }
646 //std::cout << "new element " << i-1 << " " << 1 << "\n";
647 elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, i -1, 1), tailPair.second));
648 incoming[i] = 0;
649 incoming[j] = 0;
650 }
651 break;
652 }
653 }
654 }
655 }
656
657 //find any active tail that needs to pass through to an incoming edge
658 //we expect to find no more than two pass through
659
660 //find pass through with solid on top
661 //std::cout << "checking case 3\n";
662 for(int i = 0; i < 4; ++i) {
663 //std::cout << i << "\n";
664 if(counts[i] != 0) {
665 if(counts[i] == 1) {
666 //std::cout << "fixed i\n";
667 for(int j = 3; j >= 0; --j) {
668 if(incoming[j] != 0) {
669 if(incoming[j] == 1) {
670 //std::cout << "case3: " << i << " " << j << "\n";
671 //tails[i]->print();
672 //pass through solid on top
673 tails[i]->pushPoint(point);
674 //std::cout << "after push\n";
675 if(j == 3) {
676 returnValue = tails[i];
677 returnCount = -1;
678 } else {
679 elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, incoming[j]), tails[i]));
680 }
681 tails[i] = 0;
682 counts[i] = 0;
683 incoming[j] = 0;
684 }
685 break;
686 }
687 }
688 }
689 break;
690 }
691 }
692 //std::cout << "checking case 4\n";
693 //find pass through with solid on bottom
694 for(int i = 3; i >= 0; --i) {
695 if(counts[i] != 0) {
696 if(counts[i] == -1) {
697 for(int j = 0; j < 4; ++j) {
698 if(incoming[j] != 0) {
699 if(incoming[j] == -1) {
700 //std::cout << "case4: " << i << " " << j << "\n";
701 //pass through solid on bottom
702 tails[i]->pushPoint(point);
703 if(j == 3) {
704 returnValue = tails[i];
705 returnCount = 1;
706 } else {
707 //std::cout << "new element " << j-1 << " " << incoming[j] << "\n";
708 elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, incoming[j]), tails[i]));
709 }
710 tails[i] = 0;
711 counts[i] = 0;
712 incoming[j] = 0;
713 }
714 break;
715 }
716 }
717 }
718 break;
719 }
720 }
721
722 //find the end of a hole or the beginning of a hole
723
724 //find end of a hole
725 for(int i = 0; i < 3; ++i) {
726 if(counts[i] != 0) {
727 for(int j = i+1; j < 4; ++j) {
728 if(counts[j] != 0) {
729 //std::cout << "case5: " << i << " " << j << "\n";
730 //we are ending a hole and may potentially close a figure and have to handle the hole
731 returnValue = ActiveTail45::joinChains(point, tails[i], tails[j], false, output);
732 tails[i] = 0;
733 tails[j] = 0;
734 counts[i] = 0;
735 counts[j] = 0;
736 break;
737 }
738 }
739 break;
740 }
741 }
742 //find beginning of a hole
743 for(int i = 0; i < 3; ++i) {
744 if(incoming[i] != 0) {
745 for(int j = i+1; j < 4; ++j) {
746 if(incoming[j] != 0) {
747 //std::cout << "case6: " << i << " " << j << "\n";
748 //we are beginning a empty space
749 ActiveTail45* holep = 0;
750 if(counts[3] == 0) holep = tails[3];
751 std::pair<ActiveTail45*, ActiveTail45*> tailPair =
752 ActiveTail45::createActiveTail45sAsPair(point, false, holep, fractureHoles_ != 0);
753 if(j == 3) {
754 returnValue = tailPair.first;
755 returnCount = -1;
756 } else {
757 //std::cout << "new element " << j-1 << " " << incoming[j] << "\n";
758 elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, incoming[j]), tailPair.first));
759 }
760 //std::cout << "new element " << i-1 << " " << incoming[i] << "\n";
761 elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, i -1, incoming[i]), tailPair.second));
762 incoming[i] = 0;
763 incoming[j] = 0;
764 break;
765 }
766 }
767 break;
768 }
769 }
770 //assert that tails, counts and incoming are all null
771 return std::pair<int, ActiveTail45*>(returnCount, returnValue);
772 }
773
774 template <class cT, class iT>
775 inline iT processEvent_(cT& output, iT inputBegin, iT inputEnd) {
776 //std::cout << "processEvent_\n";
777 justBefore_ = true;
778 //collect up all elements from the tree that are at the y
779 //values of events in the input queue
780 //create vector of new elements to add into tree
781 ActiveTail45* verticalTail = 0;
782 int verticalCount = 0;
783 iT currentIter = inputBegin;
784 std::vector<iterator> elementIters;
785 std::vector<std::pair<Vertex45, ActiveTail45*> > elements;
786 while(currentIter != inputEnd && currentIter->pt.x() == x_) {
787 //std::cout << "loop\n";
788 Unit currentY = (*currentIter).pt.y();
789 iterator iter = lookUp_(currentY);
790 //int counts[4] = {0, 0, 0, 0};
791 Vertex45Count counts;
792 ActiveTail45* tails[4] = {0, 0, 0, verticalTail};
793 //std::cout << "finding elements in tree\n";
794 while(iter != scanData_.end() &&
795 iter->first.evalAtX(x_) == currentY) {
796 //std::cout << "loop2\n";
797 elementIters.push_back(iter);
798 int index = iter->first.rise + 1;
799 //std::cout << index << " " << iter->first.count << "\n";
800 counts[index] = iter->first.count;
801 tails[index] = iter->second;
802 ++iter;
803 }
804 //int incoming[4] = {0, 0, 0, 0};
805 Vertex45Count incoming;
806 //std::cout << "aggregating\n";
807 do {
808 //std::cout << "loop3\n";
809 Vertex45Compact currentVertex(*currentIter);
810 incoming += currentVertex.count;
811 ++currentIter;
812 } while(currentIter != inputEnd && currentIter->pt.y() == currentY &&
813 currentIter->pt.x() == x_);
814 //now counts and tails have the data from the left and
815 //incoming has the data from the right at this point
816 //cancel out any end points
817 //std::cout << counts[0] << " ";
818 //std::cout << counts[1] << " ";
819 //std::cout << counts[2] << " ";
820 //std::cout << counts[3] << "\n";
821 //std::cout << incoming[0] << " ";
822 //std::cout << incoming[1] << " ";
823 //std::cout << incoming[2] << " ";
824 //std::cout << incoming[3] << "\n";
825 if(verticalTail) {
826 counts[3] = -verticalCount;
827 }
828 incoming[3] *= -1;
829 for(unsigned int i = 0; i < 4; ++i) incoming[i] += counts[i];
830 //std::cout << "calling processPoint_\n";
831 std::pair<int, ActiveTail45*> result = processPoint_(output, elements, Point(x_, currentY), counts, tails, incoming);
832 verticalCount = result.first;
833 verticalTail = result.second;
834 //if(verticalTail) std::cout << "have vertical tail\n";
835 //std::cout << "verticalCount: " << verticalCount << "\n";
836 if(verticalTail && !verticalCount) {
837 //we got a hole out of the point we just processed
838 //iter is still at the next y element above the current y value in the tree
839 //std::cout << "checking whether ot handle hole\n";
840 if(currentIter == inputEnd ||
841 currentIter->pt.x() != x_ ||
842 currentIter->pt.y() >= iter->first.evalAtX(x_)) {
843 //std::cout << "handle hole here\n";
844 if(fractureHoles_) {
845 //std::cout << "fracture hole here\n";
846 //we need to handle the hole now and not at the next input vertex
847 ActiveTail45* at = iter->second;
848 Point point(x_, iter->first.evalAtX(x_));
849 verticalTail->getOtherActiveTail()->pushPoint(point);
850 iter->second = verticalTail->getOtherActiveTail();
851 at->pushPoint(point);
852 verticalTail->join(at);
853 delete at;
854 delete verticalTail;
855 verticalTail = 0;
856 } else {
857 //std::cout << "push hole onto list\n";
858 iter->second->addHole(verticalTail);
859 verticalTail = 0;
860 }
861 }
862 }
863 }
864 //std::cout << "erasing\n";
865 //erase all elements from the tree
866 for(typename std::vector<iterator>::iterator iter = elementIters.begin();
867 iter != elementIters.end(); ++iter) {
868 //std::cout << "erasing loop\n";
869 scanData_.erase(*iter);
870 }
871 //switch comparison tie breaking policy
872 justBefore_ = false;
873 //add new elements into tree
874 //std::cout << "inserting\n";
875 for(typename std::vector<std::pair<Vertex45, ActiveTail45*> >::iterator iter = elements.begin();
876 iter != elements.end(); ++iter) {
877 //std::cout << "inserting loop\n";
878 scanData_.insert(scanData_.end(), *iter);
879 }
880 //std::cout << "end processEvent\n";
881 return currentIter;
882 }
883
884 inline iterator lookUp_(Unit y){
885 //if just before then we need to look from 1 not -1
886 return scanData_.lower_bound(Vertex45(Point(x_, y), -1+2*justBefore_, 0));
887 }
888
889 };
890
891 template <typename stream_type>
892 static inline bool testPolygon45FormationRect(stream_type& stdcout) {
893 stdcout << "testing polygon formation\n";
894 Polygon45Formation pf(true);
895 std::vector<Polygon45> polys;
896 std::vector<Vertex45> data;
897 data.push_back(Vertex45(Point(0, 0), 0, 1));
898 data.push_back(Vertex45(Point(0, 0), 2, 1));
899 data.push_back(Vertex45(Point(0, 10), 2, -1));
900 data.push_back(Vertex45(Point(0, 10), 0, -1));
901 data.push_back(Vertex45(Point(10, 0), 0, -1));
902 data.push_back(Vertex45(Point(10, 0), 2, -1));
903 data.push_back(Vertex45(Point(10, 10), 2, 1));
904 data.push_back(Vertex45(Point(10, 10), 0, 1));
905 polygon_sort(data.begin(), data.end());
906 pf.scan(polys, data.begin(), data.end());
907 stdcout << "result size: " << polys.size() << "\n";
908 for(std::size_t i = 0; i < polys.size(); ++i) {
909 stdcout << polys[i] << "\n";
910 }
911 stdcout << "done testing polygon formation\n";
912 return true;
913 }
914
915 template <typename stream_type>
916 static inline bool testPolygon45FormationP1(stream_type& stdcout) {
917 stdcout << "testing polygon formation\n";
918 Polygon45Formation pf(true);
919 std::vector<Polygon45> polys;
920 std::vector<Vertex45> data;
921 data.push_back(Vertex45(Point(0, 0), 1, 1));
922 data.push_back(Vertex45(Point(0, 0), 2, 1));
923 data.push_back(Vertex45(Point(0, 10), 2, -1));
924 data.push_back(Vertex45(Point(0, 10), 1, -1));
925 data.push_back(Vertex45(Point(10, 10), 1, -1));
926 data.push_back(Vertex45(Point(10, 10), 2, -1));
927 data.push_back(Vertex45(Point(10, 20), 2, 1));
928 data.push_back(Vertex45(Point(10, 20), 1, 1));
929 polygon_sort(data.begin(), data.end());
930 pf.scan(polys, data.begin(), data.end());
931 stdcout << "result size: " << polys.size() << "\n";
932 for(std::size_t i = 0; i < polys.size(); ++i) {
933 stdcout << polys[i] << "\n";
934 }
935 stdcout << "done testing polygon formation\n";
936 return true;
937 }
938 //polygon45set class
939
940 template <typename stream_type>
941 static inline bool testPolygon45FormationP2(stream_type& stdcout) {
942 stdcout << "testing polygon formation\n";
943 Polygon45Formation pf(true);
944 std::vector<Polygon45> polys;
945 std::vector<Vertex45> data;
946 data.push_back(Vertex45(Point(0, 0), 0, 1));
947 data.push_back(Vertex45(Point(0, 0), 1, -1));
948 data.push_back(Vertex45(Point(10, 0), 0, -1));
949 data.push_back(Vertex45(Point(10, 0), 1, 1));
950 data.push_back(Vertex45(Point(10, 10), 1, 1));
951 data.push_back(Vertex45(Point(10, 10), 0, -1));
952 data.push_back(Vertex45(Point(20, 10), 1, -1));
953 data.push_back(Vertex45(Point(20, 10), 0, 1));
954 polygon_sort(data.begin(), data.end());
955 pf.scan(polys, data.begin(), data.end());
956 stdcout << "result size: " << polys.size() << "\n";
957 for(std::size_t i = 0; i < polys.size(); ++i) {
958 stdcout << polys[i] << "\n";
959 }
960 stdcout << "done testing polygon formation\n";
961 return true;
962 }
963 //polygon45set class
964
965 template <typename stream_type>
966 static inline bool testPolygon45FormationStar1(stream_type& stdcout) {
967 stdcout << "testing polygon formation\n";
968 Polygon45Formation pf(true);
969 std::vector<Polygon45> polys;
970 std::vector<Vertex45> data;
971 // result == 0 8 -1 1
972 data.push_back(Vertex45(Point(0, 8), -1, 1));
973 // result == 0 8 1 -1
974 data.push_back(Vertex45(Point(0, 8), 1, -1));
975 // result == 4 0 1 1
976 data.push_back(Vertex45(Point(4, 0), 1, 1));
977 // result == 4 0 2 1
978 data.push_back(Vertex45(Point(4, 0), 2, 1));
979 // result == 4 4 2 -1
980 data.push_back(Vertex45(Point(4, 4), 2, -1));
981 // result == 4 4 -1 -1
982 data.push_back(Vertex45(Point(4, 4), -1, -1));
983 // result == 4 12 1 1
984 data.push_back(Vertex45(Point(4, 12), 1, 1));
985 // result == 4 12 2 1
986 data.push_back(Vertex45(Point(4, 12), 2, 1));
987 // result == 4 16 2 -1
988 data.push_back(Vertex45(Point(4, 16), 2, 1));
989 // result == 4 16 -1 -1
990 data.push_back(Vertex45(Point(4, 16), -1, -1));
991 // result == 6 2 1 -1
992 data.push_back(Vertex45(Point(6, 2), 1, -1));
993 // result == 6 14 -1 1
994 data.push_back(Vertex45(Point(6, 14), -1, 1));
995 // result == 6 2 -1 1
996 data.push_back(Vertex45(Point(6, 2), -1, 1));
997 // result == 6 14 1 -1
998 data.push_back(Vertex45(Point(6, 14), 1, -1));
999 // result == 8 0 -1 -1
1000 data.push_back(Vertex45(Point(8, 0), -1, -1));
1001 // result == 8 0 2 -1
1002 data.push_back(Vertex45(Point(8, 0), 2, -1));
1003 // result == 8 4 2 1
1004 data.push_back(Vertex45(Point(8, 4), 2, 1));
1005 // result == 8 4 1 1
1006 data.push_back(Vertex45(Point(8, 4), 1, 1));
1007 // result == 8 12 -1 -1
1008 data.push_back(Vertex45(Point(8, 12), -1, -1));
1009 // result == 8 12 2 -1
1010 data.push_back(Vertex45(Point(8, 12), 2, -1));
1011 // result == 8 16 2 1
1012 data.push_back(Vertex45(Point(8, 16), 2, 1));
1013 // result == 8 16 1 1
1014 data.push_back(Vertex45(Point(8, 16), 1, 1));
1015 // result == 12 8 1 -1
1016 data.push_back(Vertex45(Point(12, 8), 1, -1));
1017 // result == 12 8 -1 1
1018 data.push_back(Vertex45(Point(12, 8), -1, 1));
1019 polygon_sort(data.begin(), data.end());
1020 pf.scan(polys, data.begin(), data.end());
1021 stdcout << "result size: " << polys.size() << "\n";
1022 for(std::size_t i = 0; i < polys.size(); ++i) {
1023 stdcout << polys[i] << "\n";
1024 }
1025 stdcout << "done testing polygon formation\n";
1026 return true;
1027 }
1028
1029 template <typename stream_type>
1030 static inline bool testPolygon45FormationStar2(stream_type& stdcout) {
1031 stdcout << "testing polygon formation\n";
1032 Polygon45Formation pf(true);
1033 std::vector<Polygon45> polys;
1034 Scan45 scan45;
1035 std::vector<Vertex45 > result;
1036 std::vector<Scan45Vertex> vertices;
1037 //is a Rectnagle(0, 0, 10, 10);
1038 Count2 count(1, 0);
1039 Count2 ncount(-1, 0);
1040 vertices.push_back(Scan45Vertex(Point(0,4), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
1041 vertices.push_back(Scan45Vertex(Point(16,4), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
1042 vertices.push_back(Scan45Vertex(Point(8,12), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
1043 count = Count2(0, 1);
1044 ncount = count.invert();
1045 vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
1046 vertices.push_back(Scan45Vertex(Point(16,8), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
1047 vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
1048 sortScan45Vector(vertices);
1049 stdcout << "scanning\n";
1050 scan45.scan(result, vertices.begin(), vertices.end());
1051
1052 polygon_sort(result.begin(), result.end());
1053 pf.scan(polys, result.begin(), result.end());
1054 stdcout << "result size: " << polys.size() << "\n";
1055 for(std::size_t i = 0; i < polys.size(); ++i) {
1056 stdcout << polys[i] << "\n";
1057 }
1058 stdcout << "done testing polygon formation\n";
1059 return true;
1060 }
1061
1062 template <typename stream_type>
1063 static inline bool testPolygon45FormationStarHole1(stream_type& stdcout) {
1064 stdcout << "testing polygon formation\n";
1065 Polygon45Formation pf(true);
1066 std::vector<Polygon45> polys;
1067 std::vector<Vertex45> data;
1068 // result == 0 8 -1 1
1069 data.push_back(Vertex45(Point(0, 8), -1, 1));
1070 // result == 0 8 1 -1
1071 data.push_back(Vertex45(Point(0, 8), 1, -1));
1072 // result == 4 0 1 1
1073 data.push_back(Vertex45(Point(4, 0), 1, 1));
1074 // result == 4 0 2 1
1075 data.push_back(Vertex45(Point(4, 0), 2, 1));
1076 // result == 4 4 2 -1
1077 data.push_back(Vertex45(Point(4, 4), 2, -1));
1078 // result == 4 4 -1 -1
1079 data.push_back(Vertex45(Point(4, 4), -1, -1));
1080 // result == 4 12 1 1
1081 data.push_back(Vertex45(Point(4, 12), 1, 1));
1082 // result == 4 12 2 1
1083 data.push_back(Vertex45(Point(4, 12), 2, 1));
1084 // result == 4 16 2 -1
1085 data.push_back(Vertex45(Point(4, 16), 2, 1));
1086 // result == 4 16 -1 -1
1087 data.push_back(Vertex45(Point(4, 16), -1, -1));
1088 // result == 6 2 1 -1
1089 data.push_back(Vertex45(Point(6, 2), 1, -1));
1090 // result == 6 14 -1 1
1091 data.push_back(Vertex45(Point(6, 14), -1, 1));
1092 // result == 6 2 -1 1
1093 data.push_back(Vertex45(Point(6, 2), -1, 1));
1094 // result == 6 14 1 -1
1095 data.push_back(Vertex45(Point(6, 14), 1, -1));
1096 // result == 8 0 -1 -1
1097 data.push_back(Vertex45(Point(8, 0), -1, -1));
1098 // result == 8 0 2 -1
1099 data.push_back(Vertex45(Point(8, 0), 2, -1));
1100 // result == 8 4 2 1
1101 data.push_back(Vertex45(Point(8, 4), 2, 1));
1102 // result == 8 4 1 1
1103 data.push_back(Vertex45(Point(8, 4), 1, 1));
1104 // result == 8 12 -1 -1
1105 data.push_back(Vertex45(Point(8, 12), -1, -1));
1106 // result == 8 12 2 -1
1107 data.push_back(Vertex45(Point(8, 12), 2, -1));
1108 // result == 8 16 2 1
1109 data.push_back(Vertex45(Point(8, 16), 2, 1));
1110 // result == 8 16 1 1
1111 data.push_back(Vertex45(Point(8, 16), 1, 1));
1112 // result == 12 8 1 -1
1113 data.push_back(Vertex45(Point(12, 8), 1, -1));
1114 // result == 12 8 -1 1
1115 data.push_back(Vertex45(Point(12, 8), -1, 1));
1116
1117 data.push_back(Vertex45(Point(6, 4), 1, -1));
1118 data.push_back(Vertex45(Point(6, 4), 2, -1));
1119 data.push_back(Vertex45(Point(6, 8), -1, 1));
1120 data.push_back(Vertex45(Point(6, 8), 2, 1));
1121 data.push_back(Vertex45(Point(8, 6), -1, -1));
1122 data.push_back(Vertex45(Point(8, 6), 1, 1));
1123
1124 polygon_sort(data.begin(), data.end());
1125 pf.scan(polys, data.begin(), data.end());
1126 stdcout << "result size: " << polys.size() << "\n";
1127 for(std::size_t i = 0; i < polys.size(); ++i) {
1128 stdcout << polys[i] << "\n";
1129 }
1130 stdcout << "done testing polygon formation\n";
1131 return true;
1132 }
1133
1134 template <typename stream_type>
1135 static inline bool testPolygon45FormationStarHole2(stream_type& stdcout) {
1136 stdcout << "testing polygon formation\n";
1137 Polygon45Formation pf(false);
1138 std::vector<Polygon45WithHoles> polys;
1139 std::vector<Vertex45> data;
1140 // result == 0 8 -1 1
1141 data.push_back(Vertex45(Point(0, 8), -1, 1));
1142 // result == 0 8 1 -1
1143 data.push_back(Vertex45(Point(0, 8), 1, -1));
1144 // result == 4 0 1 1
1145 data.push_back(Vertex45(Point(4, 0), 1, 1));
1146 // result == 4 0 2 1
1147 data.push_back(Vertex45(Point(4, 0), 2, 1));
1148 // result == 4 4 2 -1
1149 data.push_back(Vertex45(Point(4, 4), 2, -1));
1150 // result == 4 4 -1 -1
1151 data.push_back(Vertex45(Point(4, 4), -1, -1));
1152 // result == 4 12 1 1
1153 data.push_back(Vertex45(Point(4, 12), 1, 1));
1154 // result == 4 12 2 1
1155 data.push_back(Vertex45(Point(4, 12), 2, 1));
1156 // result == 4 16 2 -1
1157 data.push_back(Vertex45(Point(4, 16), 2, 1));
1158 // result == 4 16 -1 -1
1159 data.push_back(Vertex45(Point(4, 16), -1, -1));
1160 // result == 6 2 1 -1
1161 data.push_back(Vertex45(Point(6, 2), 1, -1));
1162 // result == 6 14 -1 1
1163 data.push_back(Vertex45(Point(6, 14), -1, 1));
1164 // result == 6 2 -1 1
1165 data.push_back(Vertex45(Point(6, 2), -1, 1));
1166 // result == 6 14 1 -1
1167 data.push_back(Vertex45(Point(6, 14), 1, -1));
1168 // result == 8 0 -1 -1
1169 data.push_back(Vertex45(Point(8, 0), -1, -1));
1170 // result == 8 0 2 -1
1171 data.push_back(Vertex45(Point(8, 0), 2, -1));
1172 // result == 8 4 2 1
1173 data.push_back(Vertex45(Point(8, 4), 2, 1));
1174 // result == 8 4 1 1
1175 data.push_back(Vertex45(Point(8, 4), 1, 1));
1176 // result == 8 12 -1 -1
1177 data.push_back(Vertex45(Point(8, 12), -1, -1));
1178 // result == 8 12 2 -1
1179 data.push_back(Vertex45(Point(8, 12), 2, -1));
1180 // result == 8 16 2 1
1181 data.push_back(Vertex45(Point(8, 16), 2, 1));
1182 // result == 8 16 1 1
1183 data.push_back(Vertex45(Point(8, 16), 1, 1));
1184 // result == 12 8 1 -1
1185 data.push_back(Vertex45(Point(12, 8), 1, -1));
1186 // result == 12 8 -1 1
1187 data.push_back(Vertex45(Point(12, 8), -1, 1));
1188
1189 data.push_back(Vertex45(Point(6, 4), 1, -1));
1190 data.push_back(Vertex45(Point(6, 4), 2, -1));
1191 data.push_back(Vertex45(Point(6, 12), -1, 1));
1192 data.push_back(Vertex45(Point(6, 12), 2, 1));
1193 data.push_back(Vertex45(Point(10, 8), -1, -1));
1194 data.push_back(Vertex45(Point(10, 8), 1, 1));
1195
1196 polygon_sort(data.begin(), data.end());
1197 pf.scan(polys, data.begin(), data.end());
1198 stdcout << "result size: " << polys.size() << "\n";
1199 for(std::size_t i = 0; i < polys.size(); ++i) {
1200 stdcout << polys[i] << "\n";
1201 }
1202 stdcout << "done testing polygon formation\n";
1203 return true;
1204 }
1205
1206 template <typename stream_type>
1207 static inline bool testPolygon45Formation(stream_type& stdcout) {
1208 stdcout << "testing polygon formation\n";
1209 Polygon45Formation pf(false);
1210 std::vector<Polygon45WithHoles> polys;
1211 std::vector<Vertex45> data;
1212
1213 data.push_back(Vertex45(Point(0, 0), 0, 1));
1214 data.push_back(Vertex45(Point(0, 0), 2, 1));
1215 data.push_back(Vertex45(Point(0, 100), 2, -1));
1216 data.push_back(Vertex45(Point(0, 100), 0, -1));
1217 data.push_back(Vertex45(Point(100, 0), 0, -1));
1218 data.push_back(Vertex45(Point(100, 0), 2, -1));
1219 data.push_back(Vertex45(Point(100, 100), 2, 1));
1220 data.push_back(Vertex45(Point(100, 100), 0, 1));
1221
1222 data.push_back(Vertex45(Point(2, 2), 0, -1));
1223 data.push_back(Vertex45(Point(2, 2), 2, -1));
1224 data.push_back(Vertex45(Point(2, 10), 2, 1));
1225 data.push_back(Vertex45(Point(2, 10), 0, 1));
1226 data.push_back(Vertex45(Point(10, 2), 0, 1));
1227 data.push_back(Vertex45(Point(10, 2), 2, 1));
1228 data.push_back(Vertex45(Point(10, 10), 2, -1));
1229 data.push_back(Vertex45(Point(10, 10), 0, -1));
1230
1231 data.push_back(Vertex45(Point(2, 12), 0, -1));
1232 data.push_back(Vertex45(Point(2, 12), 2, -1));
1233 data.push_back(Vertex45(Point(2, 22), 2, 1));
1234 data.push_back(Vertex45(Point(2, 22), 0, 1));
1235 data.push_back(Vertex45(Point(10, 12), 0, 1));
1236 data.push_back(Vertex45(Point(10, 12), 2, 1));
1237 data.push_back(Vertex45(Point(10, 22), 2, -1));
1238 data.push_back(Vertex45(Point(10, 22), 0, -1));
1239
1240 polygon_sort(data.begin(), data.end());
1241 pf.scan(polys, data.begin(), data.end());
1242 stdcout << "result size: " << polys.size() << "\n";
1243 for(std::size_t i = 0; i < polys.size(); ++i) {
1244 stdcout << polys[i] << "\n";
1245 }
1246 stdcout << "done testing polygon formation\n";
1247 return true;
1248 }
1249
1250
1251 class Polygon45Tiling {
1252 private:
1253 //definitions
1254 typedef std::map<Vertex45, ActiveTail45*, lessVertex45> Polygon45FormationData;
1255 typedef typename Polygon45FormationData::iterator iterator;
1256 typedef typename Polygon45FormationData::const_iterator const_iterator;
1257
1258 //data
1259 Polygon45FormationData scanData_;
1260 Unit x_;
1261 int justBefore_;
1262 public:
1263 inline Polygon45Tiling() : scanData_(), x_((std::numeric_limits<Unit>::min)()), justBefore_(false) {
1264 lessVertex45 lessElm(&x_, &justBefore_);
1265 scanData_ = Polygon45FormationData(lessElm);
1266 }
1267 inline Polygon45Tiling(const Polygon45Tiling& that) :
1268 scanData_(), x_((std::numeric_limits<Unit>::min)()), justBefore_(false) { (*this) = that; }
1269 inline Polygon45Tiling& operator=(const Polygon45Tiling& that) {
1270 x_ = that.x_;
1271 justBefore_ = that.justBefore_;
1272 lessVertex45 lessElm(&x_, &justBefore_);
1273 scanData_ = Polygon45FormationData(lessElm);
1274 for(const_iterator itr = that.scanData_.begin(); itr != that.scanData_.end(); ++itr){
1275 scanData_.insert(scanData_.end(), *itr);
1276 }
1277 return *this;
1278 }
1279
1280 //cT is an output container of Polygon45 or Polygon45WithHoles
1281 //iT is an iterator over Vertex45 elements
1282 //inputBegin - inputEnd is a range of sorted iT that represents
1283 //one or more scanline stops worth of data
1284 template <class cT, class iT>
1285 void scan(cT& output, iT inputBegin, iT inputEnd) {
1286 //std::cout << "1\n";
1287 while(inputBegin != inputEnd) {
1288 //std::cout << "2\n";
1289 x_ = (*inputBegin).pt.x();
1290 //std::cout << "SCAN FORMATION " << x_ << "\n";
1291 //std::cout << "x_ = " << x_ << "\n";
1292 //std::cout << "scan line size: " << scanData_.size() << "\n";
1293 inputBegin = processEvent_(output, inputBegin, inputEnd);
1294 }
1295 }
1296
1297 private:
1298 //functions
1299
1300 inline void getVerticalPair_(std::pair<ActiveTail45*, ActiveTail45*>& verticalPair,
1301 iterator previter) {
1302 ActiveTail45* iterTail = (*previter).second;
1303 Point prevPoint(x_, previter->first.evalAtX(x_));
1304 iterTail->pushPoint(prevPoint);
1305 std::pair<ActiveTail45*, ActiveTail45*> tailPair =
1306 ActiveTail45::createActiveTail45sAsPair(prevPoint, true, 0, false);
1307 verticalPair.first = iterTail;
1308 verticalPair.second = tailPair.first;
1309 (*previter).second = tailPair.second;
1310 }
1311
1312 template <class cT, class cT2>
1313 inline std::pair<int, ActiveTail45*> processPoint_(cT& output, cT2& elements,
1314 std::pair<ActiveTail45*, ActiveTail45*>& verticalPair,
1315 iterator previter, Point point,
1316 Vertex45Count& counts, ActiveTail45** tails, Vertex45Count& incoming) {
1317 //std::cout << point << "\n";
1318 //std::cout << counts[0] << " ";
1319 //std::cout << counts[1] << " ";
1320 //std::cout << counts[2] << " ";
1321 //std::cout << counts[3] << "\n";
1322 //std::cout << incoming[0] << " ";
1323 //std::cout << incoming[1] << " ";
1324 //std::cout << incoming[2] << " ";
1325 //std::cout << incoming[3] << "\n";
1326 //join any closing solid corners
1327 ActiveTail45* returnValue = 0;
1328 std::pair<ActiveTail45*, ActiveTail45*> verticalPairOut;
1329 verticalPairOut.first = 0;
1330 verticalPairOut.second = 0;
1331 int returnCount = 0;
1332 for(int i = 0; i < 3; ++i) {
1333 //std::cout << i << "\n";
1334 if(counts[i] == -1) {
1335 //std::cout << "fixed i\n";
1336 for(int j = i + 1; j < 4; ++j) {
1337 //std::cout << j << "\n";
1338 if(counts[j]) {
1339 if(counts[j] == 1) {
1340 //std::cout << "case1: " << i << " " << j << "\n";
1341 //if a figure is closed it will be written out by this function to output
1342 ActiveTail45::joinChains(point, tails[i], tails[j], true, output);
1343 counts[i] = 0;
1344 counts[j] = 0;
1345 tails[i] = 0;
1346 tails[j] = 0;
1347 }
1348 break;
1349 }
1350 }
1351 }
1352 }
1353 //find any pairs of incoming edges that need to create pair for leading solid
1354 //std::cout << "checking case2\n";
1355 for(int i = 0; i < 3; ++i) {
1356 //std::cout << i << "\n";
1357 if(incoming[i] == 1) {
1358 //std::cout << "fixed i\n";
1359 for(int j = i + 1; j < 4; ++j) {
1360 //std::cout << j << "\n";
1361 if(incoming[j]) {
1362 if(incoming[j] == -1) {
1363 //std::cout << "case2: " << i << " " << j << "\n";
1364 //std::cout << "creating active tail pair\n";
1365 std::pair<ActiveTail45*, ActiveTail45*> tailPair =
1366 ActiveTail45::createActiveTail45sAsPair(point, true, 0, false);
1367 //tailPair.first->print();
1368 //tailPair.second->print();
1369 if(j == 3) {
1370 //vertical active tail becomes return value
1371 returnValue = tailPair.first;
1372 returnCount = 1;
1373 } else {
1374 Vertex45 vertex(point, i -1, incoming[i]);
1375 //std::cout << "new element " << j-1 << " " << -1 << "\n";
1376 elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, -1), tailPair.first));
1377 }
1378 //std::cout << "new element " << i-1 << " " << 1 << "\n";
1379 elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, i -1, 1), tailPair.second));
1380 incoming[i] = 0;
1381 incoming[j] = 0;
1382 }
1383 break;
1384 }
1385 }
1386 }
1387 }
1388
1389 //find any active tail that needs to pass through to an incoming edge
1390 //we expect to find no more than two pass through
1391
1392 //find pass through with solid on top
1393 //std::cout << "checking case 3\n";
1394 for(int i = 0; i < 4; ++i) {
1395 //std::cout << i << "\n";
1396 if(counts[i] != 0) {
1397 if(counts[i] == 1) {
1398 //std::cout << "fixed i\n";
1399 for(int j = 3; j >= 0; --j) {
1400 if(incoming[j] != 0) {
1401 if(incoming[j] == 1) {
1402 //std::cout << "case3: " << i << " " << j << "\n";
1403 //tails[i]->print();
1404 //pass through solid on top
1405 if(i != 3)
1406 tails[i]->pushPoint(point);
1407 //std::cout << "after push\n";
1408 if(j == 3) {
1409 returnValue = tails[i];
1410 returnCount = -1;
1411 } else {
1412 verticalPairOut.first = tails[i];
1413 std::pair<ActiveTail45*, ActiveTail45*> tailPair =
1414 ActiveTail45::createActiveTail45sAsPair(point, true, 0, false);
1415 verticalPairOut.second = tailPair.first;
1416 elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, incoming[j]),
1417 tailPair.second));
1418 }
1419 tails[i] = 0;
1420 counts[i] = 0;
1421 incoming[j] = 0;
1422 }
1423 break;
1424 }
1425 }
1426 }
1427 break;
1428 }
1429 }
1430 //std::cout << "checking case 4\n";
1431 //find pass through with solid on bottom
1432 for(int i = 3; i >= 0; --i) {
1433 if(counts[i] != 0) {
1434 if(counts[i] == -1) {
1435 for(int j = 0; j < 4; ++j) {
1436 if(incoming[j] != 0) {
1437 if(incoming[j] == -1) {
1438 //std::cout << "case4: " << i << " " << j << "\n";
1439 //pass through solid on bottom
1440 if(i == 3) {
1441 //std::cout << "new element " << j-1 << " " << incoming[j] << "\n";
1442 if(j == 3) {
1443 returnValue = tails[i];
1444 returnCount = 1;
1445 } else {
1446 tails[i]->pushPoint(point);
1447 elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, incoming[j]), tails[i]));
1448 }
1449 } else if(j == 3) {
1450 if(verticalPair.first == 0) {
1451 getVerticalPair_(verticalPair, previter);
1452 }
1453 ActiveTail45::joinChains(point, tails[i], verticalPair.first, true, output);
1454 returnValue = verticalPair.second;
1455 returnCount = 1;
1456 } else {
1457 if(verticalPair.first == 0) {
1458 getVerticalPair_(verticalPair, previter);
1459 }
1460 ActiveTail45::joinChains(point, tails[i], verticalPair.first, true, output);
1461 verticalPair.second->pushPoint(point);
1462 elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, incoming[j]),
1463 verticalPair.second));
1464 }
1465 tails[i] = 0;
1466 counts[i] = 0;
1467 incoming[j] = 0;
1468 }
1469 break;
1470 }
1471 }
1472 }
1473 break;
1474 }
1475 }
1476
1477 //find the end of a hole or the beginning of a hole
1478
1479 //find end of a hole
1480 for(int i = 0; i < 3; ++i) {
1481 if(counts[i] != 0) {
1482 for(int j = i+1; j < 4; ++j) {
1483 if(counts[j] != 0) {
1484 //std::cout << "case5: " << i << " " << j << "\n";
1485 //we are ending a hole and may potentially close a figure and have to handle the hole
1486 tails[i]->pushPoint(point);
1487 verticalPairOut.first = tails[i];
1488 if(j == 3) {
1489 verticalPairOut.second = tails[j];
1490 } else {
1491 if(verticalPair.first == 0) {
1492 getVerticalPair_(verticalPair, previter);
1493 }
1494 ActiveTail45::joinChains(point, tails[j], verticalPair.first, true, output);
1495 verticalPairOut.second = verticalPair.second;
1496 }
1497 tails[i] = 0;
1498 tails[j] = 0;
1499 counts[i] = 0;
1500 counts[j] = 0;
1501 break;
1502 }
1503 }
1504 break;
1505 }
1506 }
1507 //find beginning of a hole
1508 for(int i = 0; i < 3; ++i) {
1509 if(incoming[i] != 0) {
1510 for(int j = i+1; j < 4; ++j) {
1511 if(incoming[j] != 0) {
1512 //std::cout << "case6: " << i << " " << j << "\n";
1513 //we are beginning a empty space
1514 if(verticalPair.first == 0) {
1515 getVerticalPair_(verticalPair, previter);
1516 }
1517 verticalPair.second->pushPoint(point);
1518 if(j == 3) {
1519 returnValue = verticalPair.first;
1520 returnCount = -1;
1521 } else {
1522 std::pair<ActiveTail45*, ActiveTail45*> tailPair =
1523 ActiveTail45::createActiveTail45sAsPair(point, true, 0, false);
1524 //std::cout << "new element " << j-1 << " " << incoming[j] << "\n";
1525 elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, incoming[j]), tailPair.second));
1526 verticalPairOut.second = tailPair.first;
1527 verticalPairOut.first = verticalPair.first;
1528 }
1529 //std::cout << "new element " << i-1 << " " << incoming[i] << "\n";
1530 elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, i -1, incoming[i]), verticalPair.second));
1531 incoming[i] = 0;
1532 incoming[j] = 0;
1533 break;
1534 }
1535 }
1536 break;
1537 }
1538 }
1539 verticalPair = verticalPairOut;
1540 //assert that verticalPair is either both null, or neither null
1541 //assert that returnValue is null if verticalPair is not null
1542 //assert that tails, counts and incoming are all null
1543 return std::pair<int, ActiveTail45*>(returnCount, returnValue);
1544 }
1545
1546 template <class cT, class iT>
1547 inline iT processEvent_(cT& output, iT inputBegin, iT inputEnd) {
1548 //std::cout << "processEvent_\n";
1549 justBefore_ = true;
1550 //collect up all elements from the tree that are at the y
1551 //values of events in the input queue
1552 //create vector of new elements to add into tree
1553 ActiveTail45* verticalTail = 0;
1554 std::pair<ActiveTail45*, ActiveTail45*> verticalPair;
1555 verticalPair.first = 0;
1556 verticalPair.second = 0;
1557 int verticalCount = 0;
1558 iT currentIter = inputBegin;
1559 std::vector<iterator> elementIters;
1560 std::vector<std::pair<Vertex45, ActiveTail45*> > elements;
1561 while(currentIter != inputEnd && currentIter->pt.x() == x_) {
1562 //std::cout << "loop\n";
1563 Unit currentY = (*currentIter).pt.y();
1564 iterator iter = lookUp_(currentY);
1565 //int counts[4] = {0, 0, 0, 0};
1566 Vertex45Count counts;
1567 ActiveTail45* tails[4] = {0, 0, 0, verticalTail};
1568 //std::cout << "finding elements in tree\n";
1569 iterator previter = iter;
1570 if(previter != scanData_.end() &&
1571 previter->first.evalAtX(x_) >= currentY &&
1572 previter != scanData_.begin())
1573 --previter;
1574 while(iter != scanData_.end() &&
1575 iter->first.evalAtX(x_) == currentY) {
1576 //std::cout << "loop2\n";
1577 elementIters.push_back(iter);
1578 int index = iter->first.rise + 1;
1579 //std::cout << index << " " << iter->first.count << "\n";
1580 counts[index] = iter->first.count;
1581 tails[index] = iter->second;
1582 ++iter;
1583 }
1584 //int incoming[4] = {0, 0, 0, 0};
1585 Vertex45Count incoming;
1586 //std::cout << "aggregating\n";
1587 do {
1588 //std::cout << "loop3\n";
1589 Vertex45Compact currentVertex(*currentIter);
1590 incoming += currentVertex.count;
1591 ++currentIter;
1592 } while(currentIter != inputEnd && currentIter->pt.y() == currentY &&
1593 currentIter->pt.x() == x_);
1594 //now counts and tails have the data from the left and
1595 //incoming has the data from the right at this point
1596 //cancel out any end points
1597 //std::cout << counts[0] << " ";
1598 //std::cout << counts[1] << " ";
1599 //std::cout << counts[2] << " ";
1600 //std::cout << counts[3] << "\n";
1601 //std::cout << incoming[0] << " ";
1602 //std::cout << incoming[1] << " ";
1603 //std::cout << incoming[2] << " ";
1604 //std::cout << incoming[3] << "\n";
1605 if(verticalTail) {
1606 counts[3] = -verticalCount;
1607 }
1608 incoming[3] *= -1;
1609 for(unsigned int i = 0; i < 4; ++i) incoming[i] += counts[i];
1610 //std::cout << "calling processPoint_\n";
1611 std::pair<int, ActiveTail45*> result = processPoint_(output, elements, verticalPair, previter,
1612 Point(x_, currentY), counts, tails, incoming);
1613 verticalCount = result.first;
1614 verticalTail = result.second;
1615 if(verticalPair.first != 0 && iter != scanData_.end() &&
1616 (currentIter == inputEnd || currentIter->pt.x() != x_ ||
1617 currentIter->pt.y() > (*iter).first.evalAtX(x_))) {
1618 //splice vertical pair into edge above
1619 ActiveTail45* tailabove = (*iter).second;
1620 Point point(x_, (*iter).first.evalAtX(x_));
1621 verticalPair.second->pushPoint(point);
1622 ActiveTail45::joinChains(point, tailabove, verticalPair.first, true, output);
1623 (*iter).second = verticalPair.second;
1624 verticalPair.first = 0;
1625 verticalPair.second = 0;
1626 }
1627 }
1628 //std::cout << "erasing\n";
1629 //erase all elements from the tree
1630 for(typename std::vector<iterator>::iterator iter = elementIters.begin();
1631 iter != elementIters.end(); ++iter) {
1632 //std::cout << "erasing loop\n";
1633 scanData_.erase(*iter);
1634 }
1635 //switch comparison tie breaking policy
1636 justBefore_ = false;
1637 //add new elements into tree
1638 //std::cout << "inserting\n";
1639 for(typename std::vector<std::pair<Vertex45, ActiveTail45*> >::iterator iter = elements.begin();
1640 iter != elements.end(); ++iter) {
1641 //std::cout << "inserting loop\n";
1642 scanData_.insert(scanData_.end(), *iter);
1643 }
1644 //std::cout << "end processEvent\n";
1645 return currentIter;
1646 }
1647
1648 inline iterator lookUp_(Unit y){
1649 //if just before then we need to look from 1 not -1
1650 return scanData_.lower_bound(Vertex45(Point(x_, y), -1+2*justBefore_, 0));
1651 }
1652
1653 };
1654
1655 template <typename stream_type>
1656 static inline bool testPolygon45TilingRect(stream_type& stdcout) {
1657 stdcout << "testing polygon tiling\n";
1658 Polygon45Tiling pf;
1659 std::vector<Polygon45> polys;
1660 std::vector<Vertex45> data;
1661 data.push_back(Vertex45(Point(0, 0), 0, 1));
1662 data.push_back(Vertex45(Point(0, 0), 2, 1));
1663 data.push_back(Vertex45(Point(0, 10), 2, -1));
1664 data.push_back(Vertex45(Point(0, 10), 0, -1));
1665 data.push_back(Vertex45(Point(10, 0), 0, -1));
1666 data.push_back(Vertex45(Point(10, 0), 2, -1));
1667 data.push_back(Vertex45(Point(10, 10), 2, 1));
1668 data.push_back(Vertex45(Point(10, 10), 0, 1));
1669 polygon_sort(data.begin(), data.end());
1670 pf.scan(polys, data.begin(), data.end());
1671 stdcout << "result size: " << polys.size() << "\n";
1672 for(std::size_t i = 0; i < polys.size(); ++i) {
1673 stdcout << polys[i] << "\n";
1674 }
1675 stdcout << "done testing polygon tiling\n";
1676 return true;
1677 }
1678
1679 template <typename stream_type>
1680 static inline bool testPolygon45TilingP1(stream_type& stdcout) {
1681 stdcout << "testing polygon tiling\n";
1682 Polygon45Tiling pf;
1683 std::vector<Polygon45> polys;
1684 std::vector<Vertex45> data;
1685 data.push_back(Vertex45(Point(0, 0), 1, 1));
1686 data.push_back(Vertex45(Point(0, 0), 2, 1));
1687 data.push_back(Vertex45(Point(0, 10), 2, -1));
1688 data.push_back(Vertex45(Point(0, 10), 1, -1));
1689 data.push_back(Vertex45(Point(10, 10), 1, -1));
1690 data.push_back(Vertex45(Point(10, 10), 2, -1));
1691 data.push_back(Vertex45(Point(10, 20), 2, 1));
1692 data.push_back(Vertex45(Point(10, 20), 1, 1));
1693 polygon_sort(data.begin(), data.end());
1694 pf.scan(polys, data.begin(), data.end());
1695 stdcout << "result size: " << polys.size() << "\n";
1696 for(std::size_t i = 0; i < polys.size(); ++i) {
1697 stdcout << polys[i] << "\n";
1698 }
1699 stdcout << "done testing polygon tiling\n";
1700 return true;
1701 }
1702
1703 template <typename stream_type>
1704 static inline bool testPolygon45TilingP2(stream_type& stdcout) {
1705 stdcout << "testing polygon tiling\n";
1706 Polygon45Tiling pf;
1707 std::vector<Polygon45> polys;
1708 std::vector<Vertex45> data;
1709 data.push_back(Vertex45(Point(0, 0), 0, 1));
1710 data.push_back(Vertex45(Point(0, 0), 1, -1));
1711 data.push_back(Vertex45(Point(10, 0), 0, -1));
1712 data.push_back(Vertex45(Point(10, 0), 1, 1));
1713 data.push_back(Vertex45(Point(10, 10), 1, 1));
1714 data.push_back(Vertex45(Point(10, 10), 0, -1));
1715 data.push_back(Vertex45(Point(20, 10), 1, -1));
1716 data.push_back(Vertex45(Point(20, 10), 0, 1));
1717 polygon_sort(data.begin(), data.end());
1718 pf.scan(polys, data.begin(), data.end());
1719 stdcout << "result size: " << polys.size() << "\n";
1720 for(std::size_t i = 0; i < polys.size(); ++i) {
1721 stdcout << polys[i] << "\n";
1722 }
1723 stdcout << "done testing polygon tiling\n";
1724 return true;
1725 }
1726
1727 template <typename stream_type>
1728 static inline bool testPolygon45TilingP3(stream_type& stdcout) {
1729 stdcout << "testing polygon tiling\n";
1730 Polygon45Tiling pf;
1731 std::vector<Polygon45> polys;
1732 std::vector<Vertex45> data;
1733 data.push_back(Vertex45(Point(0, 0), 0, 1));
1734 data.push_back(Vertex45(Point(0, 0), 2, 1));
1735 data.push_back(Vertex45(Point(0, 10), 2, -1));
1736 data.push_back(Vertex45(Point(0, 10), 0, -1));
1737 data.push_back(Vertex45(Point(20, 0), 0, -1));
1738 data.push_back(Vertex45(Point(20, 0), 2, -1));
1739 data.push_back(Vertex45(Point(10, 10), 1, -1));
1740 data.push_back(Vertex45(Point(10, 10), 0, 1));
1741 data.push_back(Vertex45(Point(20, 20), 1, 1));
1742 data.push_back(Vertex45(Point(20, 20), 2, 1));
1743 polygon_sort(data.begin(), data.end());
1744 pf.scan(polys, data.begin(), data.end());
1745 stdcout << "result size: " << polys.size() << "\n";
1746 for(std::size_t i = 0; i < polys.size(); ++i) {
1747 stdcout << polys[i] << "\n";
1748 }
1749 stdcout << "done testing polygon tiling\n";
1750 return true;
1751 }
1752
1753 template <typename stream_type>
1754 static inline bool testPolygon45TilingP4(stream_type& stdcout) {
1755 stdcout << "testing polygon tiling p4\n";
1756 Polygon45Tiling pf;
1757 std::vector<Polygon45> polys;
1758 std::vector<Vertex45> data;
1759 data.push_back(Vertex45(Point(0, 0), 0, 1));
1760 data.push_back(Vertex45(Point(0, 0), 2, 1));
1761 data.push_back(Vertex45(Point(0, 10), 2, -1));
1762 data.push_back(Vertex45(Point(0, 10), 0, -1));
1763 data.push_back(Vertex45(Point(10, 0), -1, 1));
1764 data.push_back(Vertex45(Point(10, 0), 0, -1));
1765 data.push_back(Vertex45(Point(20, 10), 2, 1));
1766 data.push_back(Vertex45(Point(20, 10), 0, 1));
1767 data.push_back(Vertex45(Point(20, -10), -1, -1));
1768 data.push_back(Vertex45(Point(20, -10), 2, -1));
1769 polygon_sort(data.begin(), data.end());
1770 pf.scan(polys, data.begin(), data.end());
1771 stdcout << "result size: " << polys.size() << "\n";
1772 for(std::size_t i = 0; i < polys.size(); ++i) {
1773 stdcout << polys[i] << "\n";
1774 }
1775 stdcout << "done testing polygon tiling\n";
1776 return true;
1777 }
1778
1779 template <typename stream_type>
1780 static inline bool testPolygon45TilingP5(stream_type& stdcout) {
1781 stdcout << "testing polygon tiling P5\n";
1782 Polygon45Tiling pf;
1783 std::vector<Polygon45> polys;
1784 std::vector<Vertex45> data;
1785 data.push_back(Vertex45(Point(0, 0), 0, 1));
1786 data.push_back(Vertex45(Point(0, 0), 2, 1));
1787 data.push_back(Vertex45(Point(0, 10), 2, -1));
1788 data.push_back(Vertex45(Point(0, 10), 0, -1));
1789 data.push_back(Vertex45(Point(10, 0), 0, -1));
1790 data.push_back(Vertex45(Point(10, 0), 2, -1));
1791 data.push_back(Vertex45(Point(10, 10), 2, 1));
1792 data.push_back(Vertex45(Point(10, 10), 0, 1));
1793
1794 data.push_back(Vertex45(Point(1, 1), 0, -1));
1795 data.push_back(Vertex45(Point(1, 1), 1, 1));
1796 data.push_back(Vertex45(Point(2, 1), 0, 1));
1797 data.push_back(Vertex45(Point(2, 1), 1, -1));
1798 data.push_back(Vertex45(Point(2, 2), 1, -1));
1799 data.push_back(Vertex45(Point(2, 2), 0, 1));
1800 data.push_back(Vertex45(Point(3, 2), 1, 1));
1801 data.push_back(Vertex45(Point(3, 2), 0, -1));
1802 polygon_sort(data.begin(), data.end());
1803 pf.scan(polys, data.begin(), data.end());
1804 stdcout << "result size: " << polys.size() << "\n";
1805 for(std::size_t i = 0; i < polys.size(); ++i) {
1806 stdcout << polys[i] << "\n";
1807 }
1808 stdcout << "done testing polygon tiling\n";
1809 return true;
1810 }
1811
1812 template <typename stream_type>
1813 static inline bool testPolygon45TilingP6(stream_type& stdcout) {
1814 stdcout << "testing polygon tiling P6\n";
1815 Polygon45Tiling pf;
1816 std::vector<Polygon45> polys;
1817 std::vector<Vertex45> data;
1818 data.push_back(Vertex45(Point(0, 0), 0, 1));
1819 data.push_back(Vertex45(Point(0, 0), 2, 1));
1820 data.push_back(Vertex45(Point(0, 10), 2, -1));
1821 data.push_back(Vertex45(Point(0, 10), 0, -1));
1822 data.push_back(Vertex45(Point(10, 0), 0, -1));
1823 data.push_back(Vertex45(Point(10, 0), 2, -1));
1824 data.push_back(Vertex45(Point(10, 10), 2, 1));
1825 data.push_back(Vertex45(Point(10, 10), 0, 1));
1826
1827 data.push_back(Vertex45(Point(1, 1), 0, -1));
1828 data.push_back(Vertex45(Point(1, 1), 2, -1));
1829 data.push_back(Vertex45(Point(1, 2), 2, 1));
1830 data.push_back(Vertex45(Point(1, 2), 0, 1));
1831 data.push_back(Vertex45(Point(2, 1), 0, 1));
1832 data.push_back(Vertex45(Point(2, 1), 2, 1));
1833 data.push_back(Vertex45(Point(2, 2), 2, -1));
1834 data.push_back(Vertex45(Point(2, 2), 0, -1));
1835
1836 polygon_sort(data.begin(), data.end());
1837 pf.scan(polys, data.begin(), data.end());
1838 stdcout << "result size: " << polys.size() << "\n";
1839 for(std::size_t i = 0; i < polys.size(); ++i) {
1840 stdcout << polys[i] << "\n";
1841 }
1842 stdcout << "done testing polygon tiling\n";
1843 return true;
1844 }
1845
1846 template <typename stream_type>
1847 static inline bool testPolygon45TilingStar1(stream_type& stdcout) {
1848 stdcout << "testing polygon tiling star1\n";
1849 Polygon45Tiling pf;
1850 std::vector<Polygon45> polys;
1851 std::vector<Vertex45> data;
1852 // result == 0 8 -1 1
1853 data.push_back(Vertex45(Point(0, 8), -1, 1));
1854 // result == 0 8 1 -1
1855 data.push_back(Vertex45(Point(0, 8), 1, -1));
1856 // result == 4 0 1 1
1857 data.push_back(Vertex45(Point(4, 0), 1, 1));
1858 // result == 4 0 2 1
1859 data.push_back(Vertex45(Point(4, 0), 2, 1));
1860 // result == 4 4 2 -1
1861 data.push_back(Vertex45(Point(4, 4), 2, -1));
1862 // result == 4 4 -1 -1
1863 data.push_back(Vertex45(Point(4, 4), -1, -1));
1864 // result == 4 12 1 1
1865 data.push_back(Vertex45(Point(4, 12), 1, 1));
1866 // result == 4 12 2 1
1867 data.push_back(Vertex45(Point(4, 12), 2, 1));
1868 // result == 4 16 2 -1
1869 data.push_back(Vertex45(Point(4, 16), 2, 1));
1870 // result == 4 16 -1 -1
1871 data.push_back(Vertex45(Point(4, 16), -1, -1));
1872 // result == 6 2 1 -1
1873 data.push_back(Vertex45(Point(6, 2), 1, -1));
1874 // result == 6 14 -1 1
1875 data.push_back(Vertex45(Point(6, 14), -1, 1));
1876 // result == 6 2 -1 1
1877 data.push_back(Vertex45(Point(6, 2), -1, 1));
1878 // result == 6 14 1 -1
1879 data.push_back(Vertex45(Point(6, 14), 1, -1));
1880 // result == 8 0 -1 -1
1881 data.push_back(Vertex45(Point(8, 0), -1, -1));
1882 // result == 8 0 2 -1
1883 data.push_back(Vertex45(Point(8, 0), 2, -1));
1884 // result == 8 4 2 1
1885 data.push_back(Vertex45(Point(8, 4), 2, 1));
1886 // result == 8 4 1 1
1887 data.push_back(Vertex45(Point(8, 4), 1, 1));
1888 // result == 8 12 -1 -1
1889 data.push_back(Vertex45(Point(8, 12), -1, -1));
1890 // result == 8 12 2 -1
1891 data.push_back(Vertex45(Point(8, 12), 2, -1));
1892 // result == 8 16 2 1
1893 data.push_back(Vertex45(Point(8, 16), 2, 1));
1894 // result == 8 16 1 1
1895 data.push_back(Vertex45(Point(8, 16), 1, 1));
1896 // result == 12 8 1 -1
1897 data.push_back(Vertex45(Point(12, 8), 1, -1));
1898 // result == 12 8 -1 1
1899 data.push_back(Vertex45(Point(12, 8), -1, 1));
1900 polygon_sort(data.begin(), data.end());
1901 pf.scan(polys, data.begin(), data.end());
1902 stdcout << "result size: " << polys.size() << "\n";
1903 for(std::size_t i = 0; i < polys.size(); ++i) {
1904 stdcout << polys[i] << "\n";
1905 }
1906 stdcout << "done testing polygon tiling\n";
1907 return true;
1908 }
1909
1910 template <typename stream_type>
1911 static inline bool testPolygon45TilingStar2(stream_type& stdcout) {
1912 stdcout << "testing polygon tiling\n";
1913 Polygon45Tiling pf;
1914 std::vector<Polygon45> polys;
1915
1916 Scan45 scan45;
1917 std::vector<Vertex45 > result;
1918 std::vector<Scan45Vertex> vertices;
1919 //is a Rectnagle(0, 0, 10, 10);
1920 Count2 count(1, 0);
1921 Count2 ncount(-1, 0);
1922 vertices.push_back(Scan45Vertex(Point(0,4), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
1923 vertices.push_back(Scan45Vertex(Point(16,4), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
1924 vertices.push_back(Scan45Vertex(Point(8,12), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
1925 count = Count2(0, 1);
1926 ncount = count.invert();
1927 vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
1928 vertices.push_back(Scan45Vertex(Point(16,8), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
1929 vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
1930 sortScan45Vector(vertices);
1931 stdcout << "scanning\n";
1932 scan45.scan(result, vertices.begin(), vertices.end());
1933
1934 polygon_sort(result.begin(), result.end());
1935 pf.scan(polys, result.begin(), result.end());
1936 stdcout << "result size: " << polys.size() << "\n";
1937 for(std::size_t i = 0; i < polys.size(); ++i) {
1938 stdcout << polys[i] << "\n";
1939 }
1940 stdcout << "done testing polygon tiling\n";
1941 return true;
1942 }
1943
1944 template <typename stream_type>
1945 static inline bool testPolygon45TilingStarHole1(stream_type& stdcout) {
1946 stdcout << "testing polygon tiling star hole 1\n";
1947 Polygon45Tiling pf;
1948 std::vector<Polygon45> polys;
1949 std::vector<Vertex45> data;
1950 // result == 0 8 -1 1
1951 data.push_back(Vertex45(Point(0, 8), -1, 1));
1952 // result == 0 8 1 -1
1953 data.push_back(Vertex45(Point(0, 8), 1, -1));
1954 // result == 4 0 1 1
1955 data.push_back(Vertex45(Point(4, 0), 1, 1));
1956 // result == 4 0 2 1
1957 data.push_back(Vertex45(Point(4, 0), 2, 1));
1958 // result == 4 4 2 -1
1959 data.push_back(Vertex45(Point(4, 4), 2, -1));
1960 // result == 4 4 -1 -1
1961 data.push_back(Vertex45(Point(4, 4), -1, -1));
1962 // result == 4 12 1 1
1963 data.push_back(Vertex45(Point(4, 12), 1, 1));
1964 // result == 4 12 2 1
1965 data.push_back(Vertex45(Point(4, 12), 2, 1));
1966 // result == 4 16 2 -1
1967 data.push_back(Vertex45(Point(4, 16), 2, 1));
1968 // result == 4 16 -1 -1
1969 data.push_back(Vertex45(Point(4, 16), -1, -1));
1970 // result == 6 2 1 -1
1971 data.push_back(Vertex45(Point(6, 2), 1, -1));
1972 // result == 6 14 -1 1
1973 data.push_back(Vertex45(Point(6, 14), -1, 1));
1974 // result == 6 2 -1 1
1975 data.push_back(Vertex45(Point(6, 2), -1, 1));
1976 // result == 6 14 1 -1
1977 data.push_back(Vertex45(Point(6, 14), 1, -1));
1978 // result == 8 0 -1 -1
1979 data.push_back(Vertex45(Point(8, 0), -1, -1));
1980 // result == 8 0 2 -1
1981 data.push_back(Vertex45(Point(8, 0), 2, -1));
1982 // result == 8 4 2 1
1983 data.push_back(Vertex45(Point(8, 4), 2, 1));
1984 // result == 8 4 1 1
1985 data.push_back(Vertex45(Point(8, 4), 1, 1));
1986 // result == 8 12 -1 -1
1987 data.push_back(Vertex45(Point(8, 12), -1, -1));
1988 // result == 8 12 2 -1
1989 data.push_back(Vertex45(Point(8, 12), 2, -1));
1990 // result == 8 16 2 1
1991 data.push_back(Vertex45(Point(8, 16), 2, 1));
1992 // result == 8 16 1 1
1993 data.push_back(Vertex45(Point(8, 16), 1, 1));
1994 // result == 12 8 1 -1
1995 data.push_back(Vertex45(Point(12, 8), 1, -1));
1996 // result == 12 8 -1 1
1997 data.push_back(Vertex45(Point(12, 8), -1, 1));
1998
1999 data.push_back(Vertex45(Point(6, 4), 1, -1));
2000 data.push_back(Vertex45(Point(6, 4), 2, -1));
2001 data.push_back(Vertex45(Point(6, 8), -1, 1));
2002 data.push_back(Vertex45(Point(6, 8), 2, 1));
2003 data.push_back(Vertex45(Point(8, 6), -1, -1));
2004 data.push_back(Vertex45(Point(8, 6), 1, 1));
2005
2006 polygon_sort(data.begin(), data.end());
2007 pf.scan(polys, data.begin(), data.end());
2008 stdcout << "result size: " << polys.size() << "\n";
2009 for(std::size_t i = 0; i < polys.size(); ++i) {
2010 stdcout << polys[i] << "\n";
2011 }
2012 stdcout << "done testing polygon tiling\n";
2013 return true;
2014 }
2015
2016 template <typename stream_type>
2017 static inline bool testPolygon45TilingStarHole2(stream_type& stdcout) {
2018 stdcout << "testing polygon tiling star hole 2\n";
2019 Polygon45Tiling pf;
2020 std::vector<Polygon45WithHoles> polys;
2021 std::vector<Vertex45> data;
2022 // result == 0 8 -1 1
2023 data.push_back(Vertex45(Point(0, 8), -1, 1));
2024 // result == 0 8 1 -1
2025 data.push_back(Vertex45(Point(0, 8), 1, -1));
2026 // result == 4 0 1 1
2027 data.push_back(Vertex45(Point(4, 0), 1, 1));
2028 // result == 4 0 2 1
2029 data.push_back(Vertex45(Point(4, 0), 2, 1));
2030 // result == 4 4 2 -1
2031 data.push_back(Vertex45(Point(4, 4), 2, -1));
2032 // result == 4 4 -1 -1
2033 data.push_back(Vertex45(Point(4, 4), -1, -1));
2034 // result == 4 12 1 1
2035 data.push_back(Vertex45(Point(4, 12), 1, 1));
2036 // result == 4 12 2 1
2037 data.push_back(Vertex45(Point(4, 12), 2, 1));
2038 // result == 4 16 2 -1
2039 data.push_back(Vertex45(Point(4, 16), 2, 1));
2040 // result == 4 16 -1 -1
2041 data.push_back(Vertex45(Point(4, 16), -1, -1));
2042 // result == 6 2 1 -1
2043 data.push_back(Vertex45(Point(6, 2), 1, -1));
2044 // result == 6 14 -1 1
2045 data.push_back(Vertex45(Point(6, 14), -1, 1));
2046 // result == 6 2 -1 1
2047 data.push_back(Vertex45(Point(6, 2), -1, 1));
2048 // result == 6 14 1 -1
2049 data.push_back(Vertex45(Point(6, 14), 1, -1));
2050 // result == 8 0 -1 -1
2051 data.push_back(Vertex45(Point(8, 0), -1, -1));
2052 // result == 8 0 2 -1
2053 data.push_back(Vertex45(Point(8, 0), 2, -1));
2054 // result == 8 4 2 1
2055 data.push_back(Vertex45(Point(8, 4), 2, 1));
2056 // result == 8 4 1 1
2057 data.push_back(Vertex45(Point(8, 4), 1, 1));
2058 // result == 8 12 -1 -1
2059 data.push_back(Vertex45(Point(8, 12), -1, -1));
2060 // result == 8 12 2 -1
2061 data.push_back(Vertex45(Point(8, 12), 2, -1));
2062 // result == 8 16 2 1
2063 data.push_back(Vertex45(Point(8, 16), 2, 1));
2064 // result == 8 16 1 1
2065 data.push_back(Vertex45(Point(8, 16), 1, 1));
2066 // result == 12 8 1 -1
2067 data.push_back(Vertex45(Point(12, 8), 1, -1));
2068 // result == 12 8 -1 1
2069 data.push_back(Vertex45(Point(12, 8), -1, 1));
2070
2071 data.push_back(Vertex45(Point(6, 4), 1, -1));
2072 data.push_back(Vertex45(Point(6, 4), 2, -1));
2073 data.push_back(Vertex45(Point(6, 12), -1, 1));
2074 data.push_back(Vertex45(Point(6, 12), 2, 1));
2075 data.push_back(Vertex45(Point(10, 8), -1, -1));
2076 data.push_back(Vertex45(Point(10, 8), 1, 1));
2077
2078 polygon_sort(data.begin(), data.end());
2079 pf.scan(polys, data.begin(), data.end());
2080 stdcout << "result size: " << polys.size() << "\n";
2081 for(std::size_t i = 0; i < polys.size(); ++i) {
2082 stdcout << polys[i] << "\n";
2083 }
2084 stdcout << "done testing polygon tiling\n";
2085 return true;
2086 }
2087
2088 template <typename stream_type>
2089 static inline bool testPolygon45Tiling(stream_type& stdcout) {
2090 stdcout << "testing polygon tiling\n";
2091 Polygon45Tiling pf;
2092 std::vector<Polygon45WithHoles> polys;
2093 std::vector<Vertex45> data;
2094
2095 data.push_back(Vertex45(Point(0, 0), 0, 1));
2096 data.push_back(Vertex45(Point(0, 0), 2, 1));
2097 data.push_back(Vertex45(Point(0, 100), 2, -1));
2098 data.push_back(Vertex45(Point(0, 100), 0, -1));
2099 data.push_back(Vertex45(Point(100, 0), 0, -1));
2100 data.push_back(Vertex45(Point(100, 0), 2, -1));
2101 data.push_back(Vertex45(Point(100, 100), 2, 1));
2102 data.push_back(Vertex45(Point(100, 100), 0, 1));
2103
2104 data.push_back(Vertex45(Point(2, 2), 0, -1));
2105 data.push_back(Vertex45(Point(2, 2), 2, -1));
2106 data.push_back(Vertex45(Point(2, 10), 2, 1));
2107 data.push_back(Vertex45(Point(2, 10), 0, 1));
2108 data.push_back(Vertex45(Point(10, 2), 0, 1));
2109 data.push_back(Vertex45(Point(10, 2), 2, 1));
2110 data.push_back(Vertex45(Point(10, 10), 2, -1));
2111 data.push_back(Vertex45(Point(10, 10), 0, -1));
2112
2113 data.push_back(Vertex45(Point(2, 12), 0, -1));
2114 data.push_back(Vertex45(Point(2, 12), 2, -1));
2115 data.push_back(Vertex45(Point(2, 22), 2, 1));
2116 data.push_back(Vertex45(Point(2, 22), 0, 1));
2117 data.push_back(Vertex45(Point(10, 12), 0, 1));
2118 data.push_back(Vertex45(Point(10, 12), 2, 1));
2119 data.push_back(Vertex45(Point(10, 22), 2, -1));
2120 data.push_back(Vertex45(Point(10, 22), 0, -1));
2121
2122 polygon_sort(data.begin(), data.end());
2123 pf.scan(polys, data.begin(), data.end());
2124 stdcout << "result size: " << polys.size() << "\n";
2125 for(std::size_t i = 0; i < polys.size(); ++i) {
2126 stdcout << polys[i] << "\n";
2127 }
2128 stdcout << "done testing polygon tiling\n";
2129 return true;
2130 }
2131 };
2132
2133 template <typename Unit>
2134 class PolyLine45HoleData {
2135 public:
2136 typedef typename polygon_45_formation<Unit>::ActiveTail45 ActiveTail45;
2137 typedef typename ActiveTail45::iterator iterator;
2138
2139 typedef polygon_45_concept geometry_type;
2140 typedef Unit coordinate_type;
2141 typedef point_data<Unit> Point;
2142 typedef Point point_type;
2143 // typedef iterator_points_to_compact<iterator, Point> compact_iterator_type;
2144 typedef iterator iterator_type;
2145 typedef typename coordinate_traits<Unit>::area_type area_type;
2146
2147 inline PolyLine45HoleData() : p_(0) {}
2148 inline PolyLine45HoleData(ActiveTail45* p) : p_(p) {}
2149 //use default copy and assign
2150 inline iterator begin() const { return p_->getTail()->begin(); }
2151 inline iterator end() const { return p_->getTail()->end(); }
2152 inline std::size_t size() const { return 0; }
2153 private:
2154 ActiveTail45* p_;
2155 };
2156
2157 template <typename Unit>
2158 class PolyLine45PolygonData {
2159 public:
2160 typedef typename polygon_45_formation<Unit>::ActiveTail45 ActiveTail45;
2161 typedef typename ActiveTail45::iterator iterator;
2162 typedef PolyLine45HoleData<Unit> holeType;
2163
2164 typedef polygon_45_with_holes_concept geometry_type;
2165 typedef Unit coordinate_type;
2166 typedef point_data<Unit> Point;
2167 typedef Point point_type;
2168 // typedef iterator_points_to_compact<iterator, Point> compact_iterator_type;
2169 typedef iterator iterator_type;
2170 typedef holeType hole_type;
2171 typedef typename coordinate_traits<Unit>::area_type area_type;
2172 class iteratorHoles {
2173 private:
2174 typename ActiveTail45::iteratorHoles itr_;
2175 public:
2176 typedef PolyLine45HoleData<Unit> holeType;
2177 typedef holeType value_type;
2178 typedef std::forward_iterator_tag iterator_category;
2179 typedef std::ptrdiff_t difference_type;
2180 typedef const value_type* pointer; //immutable
2181 typedef const value_type& reference; //immutable
2182 inline iteratorHoles() : itr_() {}
2183 inline iteratorHoles(typename ActiveTail45::iteratorHoles itr) : itr_(itr) {}
2184 inline iteratorHoles(const iteratorHoles& that) : itr_(that.itr_) {}
2185 inline iteratorHoles& operator=(const iteratorHoles& that) {
2186 itr_ = that.itr_;
2187 return *this;
2188 }
2189 inline bool operator==(const iteratorHoles& that) { return itr_ == that.itr_; }
2190 inline bool operator!=(const iteratorHoles& that) { return itr_ != that.itr_; }
2191 inline iteratorHoles& operator++() {
2192 ++itr_;
2193 return *this;
2194 }
2195 inline const iteratorHoles operator++(int) {
2196 iteratorHoles tmp = *this;
2197 ++(*this);
2198 return tmp;
2199 }
2200 inline holeType operator*() {
2201 return *itr_;
2202 }
2203 };
2204 typedef iteratorHoles iterator_holes_type;
2205
2206
2207 inline PolyLine45PolygonData() : p_(0) {}
2208 inline PolyLine45PolygonData(ActiveTail45* p) : p_(p) {}
2209 //use default copy and assign
2210 inline iterator begin() const { return p_->getTail()->begin(); }
2211 inline iterator end() const { return p_->getTail()->end(); }
2212 inline iteratorHoles begin_holes() const { return iteratorHoles(p_->getHoles().begin()); }
2213 inline iteratorHoles end_holes() const { return iteratorHoles(p_->getHoles().end()); }
2214 inline ActiveTail45* yield() { return p_; }
2215 //stub out these four required functions that will not be used but are needed for the interface
2216 inline std::size_t size_holes() const { return 0; }
2217 inline std::size_t size() const { return 0; }
2218 private:
2219 ActiveTail45* p_;
2220 };
2221
2222 template <typename T>
2223 struct PolyLineByConcept<T, polygon_45_with_holes_concept> { typedef PolyLine45PolygonData<T> type; };
2224 template <typename T>
2225 struct PolyLineByConcept<T, polygon_with_holes_concept> { typedef PolyLine45PolygonData<T> type; };
2226 template <typename T>
2227 struct PolyLineByConcept<T, polygon_45_concept> { typedef PolyLine45HoleData<T> type; };
2228 template <typename T>
2229 struct PolyLineByConcept<T, polygon_concept> { typedef PolyLine45HoleData<T> type; };
2230
2231 template <typename T>
2232 struct geometry_concept<PolyLine45PolygonData<T> > { typedef polygon_45_with_holes_concept type; };
2233 template <typename T>
2234 struct geometry_concept<PolyLine45HoleData<T> > { typedef polygon_45_concept type; };
2235
2236 }
2237 }
2238 #endif