Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-16 09:28:45

0001 /*
0002     Copyright 2008 Intel Corporation
0003 
0004     Use, modification and distribution are subject to the Boost Software License,
0005     Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0006     http://www.boost.org/LICENSE_1_0.txt).
0007 */
0008 #include<iostream>
0009 #include<cassert>
0010 #ifndef BOOST_POLYGON_POLYGON_FORMATION_HPP
0011 #define BOOST_POLYGON_POLYGON_FORMATION_HPP
0012 namespace boost { namespace polygon{
0013 
0014 namespace polygon_formation {
0015 
0016   /*
0017    * End has two states, HEAD and TAIL as is represented by a bool
0018    */
0019   typedef bool End;
0020 
0021   /*
0022    * HEAD End is represented as false because it is the lesser state
0023    */
0024   const End HEAD = false;
0025 
0026   /*
0027    * TAIL End is represented by true because TAIL comes after head and 1 after 0
0028    */
0029   const End TAIL = true;
0030 
0031   /*
0032    * 2D turning direction, left and right sides (is a boolean value since it has two states.)
0033    */
0034   typedef bool Side;
0035 
0036   /*
0037    * LEFT Side is 0 because we inuitively think left to right; left < right
0038    */
0039   const Side LEFT = false;
0040 
0041   /*
0042    * RIGHT Side is 1 so that right > left
0043    */
0044   const Side RIGHT = true;
0045 
0046   /*
0047    * The PolyLine class is data storage and services for building and representing partial polygons.
0048    * As the polyline is added to it extends its storage to accomodate the data.
0049    * PolyLines can be joined head-to-head/head-to-tail when it is determined that two polylines are
0050    * part of the same polygon.
0051    * PolyLines keep state information about what orientation their incomplete head and tail geometry have,
0052    * which side of the polyline is solid and whether the polyline is joined head-to-head and tail-to-head.
0053    * PolyLines have nothing whatsoever to do with holes.
0054    * It may be valuable to collect a histogram of PolyLine lengths used by an algorithm on its typical data
0055    * sets and tune the allocation of the initial vector of coordinate data to be greater than or equal to
0056    * the mean, median, mode, or mean plus some number of standard deviation, or just generally large enough
0057    * to prevent too much unnecesary reallocations, but not too big that it wastes a lot of memory and degrades cache
0058    * performance.
0059    */
0060   template <typename Unit>
0061   class PolyLine {
0062   private:
0063     //data
0064 
0065     /*
0066      * ptdata_ a vector of coordiantes
0067      * if VERTICAL_HEAD, first coordiante is an X
0068      * else first coordinate is a Y
0069      */
0070     std::vector<Unit> ptdata_;
0071 
0072     /*
0073      * head and tail points to other polylines before and after this in a chain
0074      */
0075     PolyLine* headp_;
0076     PolyLine* tailp_;
0077 
0078     /*
0079      * state bitmask
0080      * bit zero is orientation, 0 H, 1 V
0081      * bit 1 is head connectivity, 0 for head, 1 for tail
0082      * bit 2 is tail connectivity, 0 for head, 1 for tail
0083      * bit 3 is solid to left of PolyLine when 1, right when 0
0084      */
0085     int state_;
0086 
0087   public:
0088     /*
0089      * default constructor (for preallocation)
0090      */
0091     PolyLine();
0092 
0093     /*
0094      * constructor that takes the orientation, coordiante and side to which there is solid
0095      */
0096     PolyLine(orientation_2d orient, Unit coord, Side side);
0097 
0098     //copy constructor
0099     PolyLine(const PolyLine& pline);
0100 
0101     //destructor
0102     ~PolyLine();
0103 
0104     //assignment operator
0105     PolyLine& operator=(const PolyLine& that);
0106 
0107     //equivalence operator
0108     bool operator==(const PolyLine& b) const;
0109 
0110     /*
0111      * valid PolyLine (only default constructed polylines are invalid.)
0112      */
0113     bool isValid() const;
0114 
0115     /*
0116      * Orientation of Head
0117      */
0118     orientation_2d headOrient() const;
0119 
0120     /*
0121      * returns true if first coordinate is an X value (first segment is vertical)
0122      */
0123     bool verticalHead() const;
0124 
0125     /*
0126      * returns the orientation_2d fo the tail
0127      */
0128     orientation_2d tailOrient() const;
0129 
0130     /*
0131      * returns true if last coordinate is an X value (last segment is vertical)
0132      */
0133     bool verticalTail() const;
0134 
0135     /*
0136      * retrun true if PolyLine has odd number of coordiantes
0137      */
0138     bool oddLength() const;
0139 
0140     /*
0141      * retrun the End of the other polyline that the specified end of this polyline is connected to
0142      */
0143     End endConnectivity(End end) const;
0144 
0145     /*
0146      * retrun true if the head of this polyline is connect to the tail of a polyline
0147      */
0148     bool headToTail() const;
0149     /*
0150      * retrun true if the head of this polyline is connect to the head of a polyline
0151      */
0152     bool headToHead() const;
0153 
0154     /*
0155      * retrun true if the tail of this polyline is connect to the tail of a polyline
0156      */
0157     bool tailToTail() const;
0158     /*
0159      * retrun true if the tail of this polyline is connect to the head of a polyline
0160      */
0161     bool tailToHead() const;
0162 
0163     /*
0164      * retrun the side on which there is solid for this polyline
0165      */
0166     Side solidSide() const;
0167 
0168     /*
0169      * retrun true if there is solid to the right of this polyline
0170      */
0171     bool solidToRight() const;
0172 
0173     /*
0174      * returns true if the polyline tail is not connected
0175      */
0176     bool active() const;
0177 
0178     /*
0179      * adds a coordinate value to the end of the polyline changing the tail orientation
0180      */
0181     PolyLine& pushCoordinate(Unit coord);
0182 
0183     /*
0184      * removes a coordinate value at the end of the polyline changing the tail orientation
0185      */
0186     PolyLine& popCoordinate();
0187 
0188     /*
0189      * extends the tail of the polyline to include the point, changing orientation if needed
0190      */
0191     PolyLine& pushPoint(const point_data<Unit>& point);
0192 
0193     /*
0194      * changes the last coordinate of the tail of the polyline by the amount of the delta
0195      */
0196     PolyLine& extendTail(Unit delta);
0197 
0198     /*
0199      * join thisEnd of this polyline to that polyline's end
0200      */
0201     PolyLine& joinTo(End thisEnd, PolyLine& that, End end);
0202 
0203     /*
0204      * join an end of this polyline to the tail of that polyline
0205      */
0206     PolyLine& joinToTail(PolyLine& that, End end);
0207 
0208     /*
0209      * join an end of this polyline to the head of that polyline
0210      */
0211     PolyLine& joinToHead(PolyLine& that, End end);
0212 
0213     /*
0214      * join the head of this polyline to the head of that polyline
0215      */
0216     //join this to that in the given way
0217     PolyLine& joinHeadToHead(PolyLine& that);
0218 
0219     /*
0220      * join the head of this polyline to the tail of that polyline
0221      */
0222     PolyLine& joinHeadToTail(PolyLine& that);
0223 
0224     /*
0225      * join the tail of this polyline to the head of that polyline
0226      */
0227     PolyLine& joinTailToHead(PolyLine& that);
0228 
0229     /*
0230      * join the tail of this polyline to the tail of that polyline
0231      */
0232     PolyLine& joinTailToTail(PolyLine& that);
0233 
0234     /*
0235      * dissconnect the tail at the end of the polygon
0236      */
0237     PolyLine& disconnectTails();
0238 
0239     /*
0240      * get the coordinate at one end of this polyline, by default the tail end
0241      */
0242     Unit getEndCoord(End end = TAIL) const;
0243 
0244     /*
0245      * get the point on the polyline at the given index (polylines have the same number of coordinates as points
0246      */
0247     point_data<Unit> getPoint(unsigned int index) const;
0248 
0249     /*
0250      * get the point on one end of the polyline, by default the tail
0251      */
0252     point_data<Unit> getEndPoint(End end = TAIL) const;
0253 
0254     /*
0255      * get the orientation of a segment by index
0256      */
0257     orientation_2d segmentOrient(unsigned int index = 0) const;
0258 
0259     /*
0260      * get a coordinate by index using the square bracket operator
0261      */
0262     Unit operator[] (unsigned int index) const;
0263 
0264     /*
0265      * get the number of segments/points/coordinates in the polyline
0266      */
0267     unsigned int numSegments() const;
0268 
0269     /*
0270      * get the pointer to the next polyline at one end of this
0271      */
0272     PolyLine* next(End end) const;
0273 
0274     /*
0275      * write out coordinates of this and all attached polylines to a single vector
0276      */
0277     PolyLine* writeOut(std::vector<Unit>& outVec, End startEnd = TAIL) const;
0278 
0279   private:
0280     //methods
0281     PolyLine& joinTo_(End thisEnd, PolyLine& that, End end);
0282   };
0283 
0284   //forward declaration
0285   template<bool orientT, typename Unit>
0286   class PolyLinePolygonData;
0287 
0288   //forward declaration
0289   template<bool orientT, typename Unit>
0290   class PolyLinePolygonWithHolesData;
0291 
0292   /*
0293    * ActiveTail represents an edge of an incomplete polygon.
0294    *
0295    * An ActiveTail object is the active tail end of a polyline object, which may (should) be the attached to
0296    * a chain of polyline objects through a pointer.  The ActiveTail class provides an abstraction between
0297    * and algorithm that builds polygons and the PolyLine data representation of incomplete polygons that are
0298    * being built.  It does this by providing an iterface to access the information about the last edge at the
0299    * tail of the PolyLine it is associated with.  To a polygon constructing algorithm, an ActiveTail is a floating
0300    * edge of an incomplete polygon and has an orientation and coordinate value, as well as knowing which side of
0301    * that edge is supposed to be solid or space.  Any incomplete polygon will have two active tails.  Active tails
0302    * may be joined together to merge two incomplete polygons into a larger incomplete polygon.  If two active tails
0303    * that are to be merged are the oppositve ends of the same incomplete polygon that indicates that the polygon
0304    * has been closed and is complete.  The active tail keeps a pointer to the other active tail of its incomplete
0305    * polygon so that it is easy to check this condition.  These pointers are updated when active tails are joined.
0306    * The active tail also keeps a list of pointers to active tail objects that serve as handles to closed holes.  In
0307    * this way a hole can be associated to another incomplete polygon, which will eventually be its enclosing shell,
0308    * or reassociate the hole to another incomplete polygon in the case that it become a hole itself.  Alternately,
0309    * the active tail may add a filiment to stitch a hole into a shell and "fracture" the hole out of the interior
0310    * of a polygon.  The active tail maintains a static output buffer to temporarily write polygon data to when
0311    * it outputs a figure so that outputting a polygon does not require the allocation of a temporary buffer.  This
0312    * static buffer should be destroyed whenever the program determines that it won't need it anymore and would prefer to
0313    * release the memory it has allocated back to the system.
0314    */
0315   template <typename Unit>
0316   class ActiveTail {
0317   private:
0318     //data
0319     PolyLine<Unit>* tailp_;
0320     ActiveTail *otherTailp_;
0321     std::list<ActiveTail*> holesList_;
0322     //Sum of all the polylines which constitute the active tail (including holes)//
0323     size_t polyLineSize_;
0324   public:
0325 
0326     inline size_t getPolyLineSize(){
0327        return polyLineSize_;
0328     }
0329 
0330     inline void setPolyLineSize(int delta){
0331        polyLineSize_ = delta;
0332     }
0333 
0334     inline void addPolyLineSize(int delta){
0335        polyLineSize_ += delta;
0336     }
0337 
0338     /*
0339      * iterator over coordinates of the figure
0340      */
0341     class iterator {
0342     private:
0343       const PolyLine<Unit>* pLine_;
0344       const PolyLine<Unit>* pLineEnd_;
0345       unsigned int index_;
0346       unsigned int indexEnd_;
0347       End startEnd_;
0348     public:
0349       inline iterator() : pLine_(), pLineEnd_(), index_(), indexEnd_(), startEnd_() {}
0350       inline iterator(const ActiveTail* at, bool isHole, orientation_2d orient) :
0351         pLine_(), pLineEnd_(), index_(), indexEnd_(), startEnd_() {
0352         //if it is a hole and orientation is vertical or it is not a hole and orientation is horizontal
0353         //we want to use this active tail, otherwise we want to use the other active tail
0354         startEnd_ = TAIL;
0355         if(!isHole ^ (orient == HORIZONTAL)) {
0356           //switch winding direction
0357           at = at->getOtherActiveTail();
0358         }
0359         //now we have the right winding direction
0360         //if it is horizontal we need to skip the first element
0361         pLine_ = at->getTail();
0362 
0363         if(at->getTail()->numSegments() > 0)
0364          index_ = at->getTail()->numSegments() - 1;
0365 
0366         if((at->getOrient() == HORIZONTAL) ^ (orient == HORIZONTAL)) {
0367           pLineEnd_ = at->getTail();
0368           indexEnd_ = pLineEnd_->numSegments() - 1;
0369           if(index_ == 0) {
0370             pLine_ = at->getTail()->next(HEAD);
0371             if(at->getTail()->endConnectivity(HEAD) == TAIL) {
0372               index_ = pLine_->numSegments() -1;
0373             } else {
0374               startEnd_ = HEAD;
0375               index_ = 0;
0376             }
0377           } else { --index_; }
0378         } else {
0379           pLineEnd_ = at->getOtherActiveTail()->getTail();
0380           if(pLineEnd_->numSegments() > 0)
0381           indexEnd_ = pLineEnd_->numSegments() - 1;
0382         }
0383         at->getTail()->joinTailToTail(*(at->getOtherActiveTail()->getTail()));
0384       }
0385 
0386       inline size_t size(void){
0387         size_t count = 0;
0388         End dir = startEnd_;
0389         PolyLine<Unit> const * currLine = pLine_;
0390         size_t ops = 0;
0391         while(currLine != pLineEnd_){
0392            ops++;
0393            count += currLine->numSegments();
0394            currLine = currLine->next(dir == HEAD ? TAIL : HEAD);
0395            dir = currLine->endConnectivity(dir == HEAD ? TAIL : HEAD);
0396         }
0397         count += pLineEnd_->numSegments();
0398         return count; //no. of vertices
0399       }
0400 
0401       //use bitwise copy and assign provided by the compiler
0402       inline iterator& operator++() {
0403         if(pLine_ == pLineEnd_ && index_ == indexEnd_) {
0404           pLine_ = 0;
0405           index_ = 0;
0406           return *this;
0407         }
0408         if(startEnd_ == HEAD) {
0409           ++index_;
0410           if(index_ == pLine_->numSegments()) {
0411             End end = pLine_->endConnectivity(TAIL);
0412             pLine_ = pLine_->next(TAIL);
0413             if(end == TAIL) {
0414               startEnd_ = TAIL;
0415               index_ = pLine_->numSegments() -1;
0416             } else {
0417               index_ = 0;
0418             }
0419           }
0420         } else {
0421           if(index_ == 0) {
0422             End end = pLine_->endConnectivity(HEAD);
0423             pLine_ = pLine_->next(HEAD);
0424             if(end == TAIL) {
0425               index_ = pLine_->numSegments() -1;
0426             } else {
0427               startEnd_ = HEAD;
0428               index_ = 0;
0429             }
0430           } else {
0431             --index_;
0432           }
0433         }
0434         return *this;
0435       }
0436       inline const iterator operator++(int) {
0437         iterator tmp(*this);
0438         ++(*this);
0439         return tmp;
0440       }
0441       inline bool operator==(const iterator& that) const {
0442         return pLine_ == that.pLine_ && index_ == that.index_;
0443       }
0444       inline bool operator!=(const iterator& that) const {
0445         return pLine_ != that.pLine_ || index_ != that.index_;
0446       }
0447       inline Unit operator*() { return (*pLine_)[index_]; }
0448     };
0449 
0450     /*
0451      * iterator over holes contained within the figure
0452      */
0453     typedef typename std::list<ActiveTail*>::const_iterator iteratorHoles;
0454 
0455     //default constructor
0456     ActiveTail();
0457 
0458     //constructor
0459     ActiveTail(orientation_2d orient, Unit coord, Side solidToRight, ActiveTail* otherTailp);
0460 
0461     //constructor
0462     ActiveTail(PolyLine<Unit>* active, ActiveTail* otherTailp);
0463 
0464     //copy constructor
0465     ActiveTail(const ActiveTail& that);
0466 
0467     //destructor
0468     ~ActiveTail();
0469 
0470     //assignment operator
0471     ActiveTail& operator=(const ActiveTail& that);
0472 
0473     //equivalence operator
0474     bool operator==(const ActiveTail& b) const;
0475 
0476     /*
0477      * comparison operators, ActiveTail objects are sortable by geometry
0478      */
0479     bool operator<(const ActiveTail& b) const;
0480     bool operator<=(const ActiveTail& b) const;
0481     bool operator>(const ActiveTail& b) const;
0482     bool operator>=(const ActiveTail& b) const;
0483 
0484     /*
0485      * get the pointer to the polyline that this is an active tail of
0486      */
0487     PolyLine<Unit>* getTail() const;
0488 
0489     /*
0490      * get the pointer to the polyline at the other end of the chain
0491      */
0492     PolyLine<Unit>* getOtherTail() const;
0493 
0494     /*
0495      * get the pointer to the activetail at the other end of the chain
0496      */
0497     ActiveTail* getOtherActiveTail() const;
0498 
0499     /*
0500      * test if another active tail is the other end of the chain
0501      */
0502     bool isOtherTail(const ActiveTail& b);
0503 
0504     /*
0505      * update this end of chain pointer to new polyline
0506      */
0507     ActiveTail& updateTail(PolyLine<Unit>* newTail);
0508 
0509     /*
0510      * associate a hole to this active tail by the specified policy
0511      */
0512     ActiveTail* addHole(ActiveTail* hole, bool fractureHoles);
0513 
0514     /*
0515      * get the list of holes
0516      */
0517     const std::list<ActiveTail*>& getHoles() const;
0518 
0519     /*
0520      * copy holes from that to this
0521      */
0522     void copyHoles(ActiveTail& that);
0523 
0524     /*
0525      * find out if solid to right
0526      */
0527     bool solidToRight() const;
0528 
0529     /*
0530      * get coordinate (getCoord and getCoordinate are aliases for eachother)
0531      */
0532     Unit getCoord() const;
0533     Unit getCoordinate() const;
0534 
0535     /*
0536      * get the tail orientation
0537      */
0538     orientation_2d getOrient() const;
0539 
0540     /*
0541      * add a coordinate to the polygon at this active tail end, properly handle degenerate edges by removing redundant coordinate
0542      */
0543     void pushCoordinate(Unit coord);
0544 
0545     /*
0546      * write the figure that this active tail points to out to the temp buffer
0547      */
0548     void writeOutFigure(std::vector<Unit>& outVec, bool isHole = false) const;
0549 
0550     /*
0551      * write the figure that this active tail points to out through iterators
0552      */
0553     void writeOutFigureItrs(iterator& beginOut, iterator& endOut, bool isHole = false, orientation_2d orient = VERTICAL) const;
0554     iterator begin(bool isHole, orientation_2d orient) const;
0555     iterator end() const;
0556 
0557     /*
0558      * write the holes that this active tail points to out through iterators
0559      */
0560     void writeOutFigureHoleItrs(iteratorHoles& beginOut, iteratorHoles& endOut) const;
0561     iteratorHoles beginHoles() const;
0562     iteratorHoles endHoles() const;
0563 
0564     /*
0565      * joins the two chains that the two active tail tails are ends of
0566      * checks for closure of figure and writes out polygons appropriately
0567      * returns a handle to a hole if one is closed
0568      */
0569     static ActiveTail* joinChains(ActiveTail* at1, ActiveTail* at2, bool solid, std::vector<Unit>& outBufferTmp);
0570     template <typename PolygonT>
0571     static ActiveTail* joinChains(ActiveTail* at1, ActiveTail* at2, bool solid, typename std::vector<PolygonT>& outBufferTmp);
0572 
0573     /*
0574      * deallocate temp buffer
0575      */
0576     static void destroyOutBuffer();
0577 
0578     /*
0579      * deallocate all polygon data this active tail points to (deep delete, call only from one of a pair of active tails)
0580      */
0581     void destroyContents();
0582   };
0583 
0584   /* allocate a polyline object */
0585   template <typename Unit>
0586   PolyLine<Unit>* createPolyLine(orientation_2d orient, Unit coord, Side side);
0587 
0588   /* deallocate a polyline object */
0589   template <typename Unit>
0590   void destroyPolyLine(PolyLine<Unit>* pLine);
0591 
0592   /* allocate an activetail object */
0593   template <typename Unit>
0594   ActiveTail<Unit>* createActiveTail();
0595 
0596   /* deallocate an activetail object */
0597   template <typename Unit>
0598   void destroyActiveTail(ActiveTail<Unit>* aTail);
0599 
0600   template<bool orientT, typename Unit>
0601   class PolyLineHoleData {
0602   private:
0603     ActiveTail<Unit>* p_;
0604   public:
0605     typedef Unit coordinate_type;
0606     typedef typename ActiveTail<Unit>::iterator compact_iterator_type;
0607     typedef iterator_compact_to_points<compact_iterator_type, point_data<coordinate_type> > iterator_type;
0608     inline PolyLineHoleData() : p_(0) {}
0609     inline PolyLineHoleData(ActiveTail<Unit>* p) : p_(p) {}
0610     //use default copy and assign
0611     inline compact_iterator_type begin_compact() const { return p_->begin(true, (orientT ? VERTICAL : HORIZONTAL)); }
0612     inline compact_iterator_type end_compact() const { return p_->end(); }
0613     inline iterator_type begin() const { return iterator_type(begin_compact(), end_compact()); }
0614     inline iterator_type end() const { return iterator_type(end_compact(), end_compact()); }
0615     inline std::size_t size() const {
0616        return p_->getPolyLineSize();
0617     }
0618     inline ActiveTail<Unit>* yield() { return p_; }
0619   };
0620 
0621   template<bool orientT, typename Unit>
0622   class PolyLinePolygonWithHolesData {
0623   private:
0624     ActiveTail<Unit>* p_;
0625   public:
0626     typedef Unit coordinate_type;
0627     typedef typename ActiveTail<Unit>::iterator compact_iterator_type;
0628     typedef iterator_compact_to_points<compact_iterator_type, point_data<coordinate_type> > iterator_type;
0629     typedef PolyLineHoleData<orientT, Unit> hole_type;
0630     typedef typename coordinate_traits<Unit>::area_type area_type;
0631     class iteratorHoles {
0632     private:
0633       typename ActiveTail<Unit>::iteratorHoles itr_;
0634     public:
0635       inline iteratorHoles() : itr_() {}
0636       inline iteratorHoles(typename ActiveTail<Unit>::iteratorHoles itr) : itr_(itr) {}
0637       //use bitwise copy and assign provided by the compiler
0638       inline iteratorHoles& operator++() {
0639         ++itr_;
0640         return *this;
0641       }
0642       inline const iteratorHoles operator++(int) {
0643         iteratorHoles tmp(*this);
0644         ++(*this);
0645         return tmp;
0646       }
0647       inline bool operator==(const iteratorHoles& that) const {
0648         return itr_ == that.itr_;
0649       }
0650       inline bool operator!=(const iteratorHoles& that) const {
0651         return itr_ != that.itr_;
0652       }
0653       inline PolyLineHoleData<orientT, Unit> operator*() { return PolyLineHoleData<orientT, Unit>(*itr_);}
0654     };
0655     typedef iteratorHoles iterator_holes_type;
0656 
0657     inline PolyLinePolygonWithHolesData() : p_(0) {}
0658     inline PolyLinePolygonWithHolesData(ActiveTail<Unit>* p) : p_(p) {}
0659     //use default copy and assign
0660     inline compact_iterator_type begin_compact() const { return p_->begin(false, (orientT ? VERTICAL : HORIZONTAL)); }
0661     inline compact_iterator_type end_compact() const { return p_->end(); }
0662     inline iterator_type begin() const { return iterator_type(begin_compact(), end_compact()); }
0663     inline iterator_type end() const { return iterator_type(end_compact(), end_compact()); }
0664     inline iteratorHoles begin_holes() const { return iteratorHoles(p_->beginHoles()); }
0665     inline iteratorHoles end_holes() const { return iteratorHoles(p_->endHoles()); }
0666     inline ActiveTail<Unit>* yield() { return p_; }
0667     //stub out these four required functions that will not be used but are needed for the interface
0668     inline std::size_t size_holes() const { return 0; }
0669     inline std::size_t size() const { return 0; }
0670   };
0671 
0672 
0673   template <bool orientT, typename Unit, typename polygon_concept_type>
0674   struct PolyLineType { };
0675   template <bool orientT, typename Unit>
0676   struct PolyLineType<orientT, Unit, polygon_90_with_holes_concept> { typedef PolyLinePolygonWithHolesData<orientT, Unit> type; };
0677   template <bool orientT, typename Unit>
0678   struct PolyLineType<orientT, Unit, polygon_45_with_holes_concept> { typedef PolyLinePolygonWithHolesData<orientT, Unit> type; };
0679   template <bool orientT, typename Unit>
0680   struct PolyLineType<orientT, Unit, polygon_with_holes_concept> { typedef PolyLinePolygonWithHolesData<orientT, Unit> type; };
0681   template <bool orientT, typename Unit>
0682   struct PolyLineType<orientT, Unit, polygon_90_concept> { typedef PolyLineHoleData<orientT, Unit> type; };
0683   template <bool orientT, typename Unit>
0684   struct PolyLineType<orientT, Unit, polygon_45_concept> { typedef PolyLineHoleData<orientT, Unit> type; };
0685   template <bool orientT, typename Unit>
0686   struct PolyLineType<orientT, Unit, polygon_concept> { typedef PolyLineHoleData<orientT, Unit> type; };
0687 
0688   template <bool orientT, typename Unit, typename polygon_concept_type>
0689   class ScanLineToPolygonItrs {
0690   private:
0691     std::map<Unit, ActiveTail<Unit>*> tailMap_;
0692     typedef typename PolyLineType<orientT, Unit, polygon_concept_type>::type PolyLinePolygonData;
0693     std::vector<PolyLinePolygonData> outputPolygons_;
0694     bool fractureHoles_;
0695   public:
0696     typedef typename std::vector<PolyLinePolygonData>::iterator iterator;
0697     inline ScanLineToPolygonItrs() : tailMap_(), outputPolygons_(), fractureHoles_(false)  {}
0698     /* construct a scanline with the proper offsets, protocol and options */
0699     inline ScanLineToPolygonItrs(bool fractureHoles) : tailMap_(), outputPolygons_(), fractureHoles_(fractureHoles) {}
0700 
0701     ~ScanLineToPolygonItrs() { clearOutput_(); }
0702 
0703     /* process all vertical edges, left and right, at a unique x coordinate, edges must be sorted low to high */
0704     void processEdges(iterator& beginOutput, iterator& endOutput,
0705                       Unit currentX, std::vector<interval_data<Unit> >& leftEdges,
0706                       std::vector<interval_data<Unit> >& rightEdges,
0707                       size_t vertexThreshold=(std::numeric_limits<size_t>::max)() );
0708 
0709    /**********************************************************************
0710     *methods implementing new polygon formation code
0711     *
0712     **********************************************************************/
0713     void updatePartialSimplePolygonsWithRightEdges(Unit currentX,
0714          const std::vector<interval_data<Unit> >& leftEdges, size_t threshold);
0715 
0716     void updatePartialSimplePolygonsWithLeftEdges(Unit currentX,
0717          const std::vector<interval_data<Unit> >& leftEdges, size_t threshold);
0718 
0719     void closePartialSimplePolygon(Unit, ActiveTail<Unit>*, ActiveTail<Unit>*);
0720 
0721     void maintainPartialSimplePolygonInvariant(iterator& ,iterator& ,Unit,
0722          const std::vector<interval_data<Unit> >&,
0723          const std::vector<interval_data<Unit> >&,
0724          size_t vertexThreshold=(std::numeric_limits<size_t>::max)());
0725 
0726     void insertNewLeftEdgeIntoTailMap(Unit, Unit, Unit,
0727       typename std::map<Unit, ActiveTail<Unit>*>::iterator &);
0728     /**********************************************************************/
0729 
0730     inline size_t getTailMapSize(){
0731        typename std::map<Unit, ActiveTail<Unit>* >::const_iterator itr;
0732        size_t tsize = 0;
0733        for(itr=tailMap_.begin(); itr!=tailMap_.end(); ++itr){
0734           tsize +=  (itr->second)->getPolyLineSize();
0735        }
0736        return tsize;
0737     }
0738    /*print the active tails in this map:*/
0739    inline void print(){
0740       typename std::map<Unit, ActiveTail<Unit>* >::const_iterator itr;
0741       printf("=========TailMap[%lu]=========\n", tailMap_.size());
0742       for(itr=tailMap_.begin(); itr!=tailMap_.end(); ++itr){
0743          std::cout<< "[" << itr->first << "] : " << std::endl;
0744          //print active tail//
0745          ActiveTail<Unit> const *t = (itr->second);
0746          PolyLine<Unit> const *pBegin = t->getTail();
0747          PolyLine<Unit> const *pEnd = t->getOtherActiveTail()->getTail();
0748          std::string sorient = pBegin->solidToRight() ? "RIGHT" : "LEFT";
0749          std::cout<< " ActiveTail.tailp_ (solid= " << sorient ;
0750          End dir = TAIL;
0751          while(pBegin!=pEnd){
0752             std::cout << pBegin  << "={ ";
0753             for(size_t i=0; i<pBegin->numSegments(); i++){
0754                point_data<Unit> u = pBegin->getPoint(i);
0755                std::cout << "(" << u.x() << "," << u.y() << ") ";
0756             }
0757             std::cout << "}  ";
0758             pBegin = pBegin->next(dir == HEAD ? TAIL : HEAD);
0759             dir = pBegin->endConnectivity(dir == HEAD ? TAIL : HEAD);
0760          }
0761          if(pEnd){
0762             std::cout << pEnd << "={ ";
0763             for(size_t i=0; i<pEnd->numSegments(); i++){
0764                point_data<Unit> u = pEnd->getPoint(i);
0765                std::cout << "(" << u.x() << "," << u.y() << ") ";
0766             }
0767             std::cout << "}  ";
0768          }
0769          std::cout << " end= " << pEnd << std::endl;
0770       }
0771    }
0772 
0773   private:
0774     void clearOutput_();
0775   };
0776 
0777   /*
0778    * ScanLine does all the work of stitching together polygons from incoming vertical edges
0779    */
0780 //   template <typename Unit, typename polygon_concept_type>
0781 //   class ScanLineToPolygons {
0782 //   private:
0783 //     ScanLineToPolygonItrs<true, Unit> scanline_;
0784 //   public:
0785 //     inline ScanLineToPolygons() : scanline_() {}
0786 //     /* construct a scanline with the proper offsets, protocol and options */
0787 //     inline ScanLineToPolygons(bool fractureHoles) : scanline_(fractureHoles) {}
0788 
0789 //     /* process all vertical edges, left and right, at a unique x coordinate, edges must be sorted low to high */
0790 //     inline void processEdges(std::vector<Unit>& outBufferTmp, Unit currentX, std::vector<interval_data<Unit> >& leftEdges,
0791 //                              std::vector<interval_data<Unit> >& rightEdges) {
0792 //       typename ScanLineToPolygonItrs<true, Unit>::iterator itr, endItr;
0793 //       scanline_.processEdges(itr, endItr, currentX, leftEdges, rightEdges);
0794 //       //copy data into outBufferTmp
0795 //       while(itr != endItr) {
0796 //         typename PolyLinePolygonData<true, Unit>::iterator pditr;
0797 //         outBufferTmp.push_back(0);
0798 //         unsigned int sizeIndex = outBufferTmp.size() - 1;
0799 //         int count = 0;
0800 //         for(pditr = (*itr).begin(); pditr != (*itr).end(); ++pditr) {
0801 //           outBufferTmp.push_back(*pditr);
0802 //           ++count;
0803 //         }
0804 //         outBufferTmp[sizeIndex] = count;
0805 //         typename PolyLinePolygonData<true, Unit>::iteratorHoles pdHoleItr;
0806 //         for(pdHoleItr = (*itr).beginHoles(); pdHoleItr != (*itr).endHoles(); ++pdHoleItr) {
0807 //           outBufferTmp.push_back(0);
0808 //           unsigned int sizeIndex2 = outBufferTmp.size() - 1;
0809 //           int count2 = 0;
0810 //           for(pditr = (*pdHoleItr).begin(); pditr != (*pdHoleItr).end(); ++pditr) {
0811 //             outBufferTmp.push_back(*pditr);
0812 //             ++count2;
0813 //           }
0814 //           outBufferTmp[sizeIndex2] = -count;
0815 //         }
0816 //         ++itr;
0817 //       }
0818 //     }
0819 //   };
0820 
0821   const int VERTICAL_HEAD = 1, HEAD_TO_TAIL = 2, TAIL_TO_TAIL = 4, SOLID_TO_RIGHT = 8;
0822 
0823   //EVERY FUNCTION in this DEF file should be explicitly defined as inline
0824 
0825   //microsoft compiler improperly warns whenever you cast an integer to bool
0826   //call this function on an integer to convert it to bool without a warning
0827   template <class T>
0828   inline bool to_bool(const T& val) { return val != 0; }
0829 
0830   //default constructor (for preallocation)
0831   template <typename Unit>
0832   inline PolyLine<Unit>::PolyLine() : ptdata_() ,headp_(0), tailp_(0), state_(-1) {}
0833 
0834   //constructor
0835   template <typename Unit>
0836   inline PolyLine<Unit>::PolyLine(orientation_2d orient, Unit coord, Side side) :
0837     ptdata_(1, coord),
0838     headp_(0),
0839     tailp_(0),
0840     state_(orient.to_int() +
0841            (side << 3)){}
0842 
0843   //copy constructor
0844   template <typename Unit>
0845   inline PolyLine<Unit>::PolyLine(const PolyLine<Unit>& pline) : ptdata_(pline.ptdata_),
0846                                                      headp_(pline.headp_),
0847                                                      tailp_(pline.tailp_),
0848                                                      state_(pline.state_) {}
0849 
0850   //destructor
0851   template <typename Unit>
0852   inline PolyLine<Unit>::~PolyLine() {
0853     //clear out data just in case it is read later
0854     headp_ = tailp_ = 0;
0855     state_ = 0;
0856   }
0857 
0858   template <typename Unit>
0859   inline PolyLine<Unit>& PolyLine<Unit>::operator=(const PolyLine<Unit>& that) {
0860     if(!(this == &that)) {
0861       headp_ = that.headp_;
0862       tailp_ = that.tailp_;
0863       ptdata_ = that.ptdata_;
0864       state_ = that.state_;
0865     }
0866     return *this;
0867   }
0868 
0869   template <typename Unit>
0870   inline bool PolyLine<Unit>::operator==(const PolyLine<Unit>& b) const {
0871     return this == &b || (state_ == b.state_ &&
0872                           headp_ == b.headp_ &&
0873                           tailp_ == b.tailp_);
0874   }
0875 
0876   //valid PolyLine
0877   template <typename Unit>
0878   inline bool PolyLine<Unit>::isValid() const {
0879     return state_ > -1; }
0880 
0881   //first coordinate is an X value
0882   //first segment is vertical
0883   template <typename Unit>
0884   inline bool PolyLine<Unit>::verticalHead() const {
0885     return state_ & VERTICAL_HEAD;
0886   }
0887 
0888   //retrun true is PolyLine has odd number of coordiantes
0889   template <typename Unit>
0890   inline bool PolyLine<Unit>::oddLength() const {
0891     return to_bool((ptdata_.size()-1) % 2);
0892   }
0893 
0894   //last coordiante is an X value
0895   //last segment is vertical
0896   template <typename Unit>
0897   inline bool PolyLine<Unit>::verticalTail() const {
0898     return to_bool(verticalHead() ^ oddLength());
0899   }
0900 
0901   template <typename Unit>
0902   inline orientation_2d PolyLine<Unit>::tailOrient() const {
0903     return (verticalTail() ? VERTICAL : HORIZONTAL);
0904   }
0905 
0906   template <typename Unit>
0907   inline orientation_2d PolyLine<Unit>::headOrient() const {
0908     return (verticalHead() ? VERTICAL : HORIZONTAL);
0909   }
0910 
0911   template <typename Unit>
0912   inline End PolyLine<Unit>::endConnectivity(End end) const {
0913     //Tail should be defined as true
0914     if(end) { return tailToTail(); }
0915     return headToTail();
0916   }
0917 
0918   template <typename Unit>
0919   inline bool PolyLine<Unit>::headToTail() const {
0920     return to_bool(state_ & HEAD_TO_TAIL);
0921   }
0922 
0923   template <typename Unit>
0924   inline bool PolyLine<Unit>::headToHead() const {
0925     return to_bool(!headToTail());
0926   }
0927 
0928   template <typename Unit>
0929   inline bool PolyLine<Unit>::tailToHead() const {
0930     return to_bool(!tailToTail());
0931   }
0932 
0933   template <typename Unit>
0934   inline bool PolyLine<Unit>::tailToTail() const {
0935     return to_bool(state_ & TAIL_TO_TAIL);
0936   }
0937 
0938   template <typename Unit>
0939   inline Side PolyLine<Unit>::solidSide() const {
0940     return solidToRight(); }
0941 
0942   template <typename Unit>
0943   inline bool PolyLine<Unit>::solidToRight() const {
0944     return to_bool(state_ & SOLID_TO_RIGHT) != 0;
0945   }
0946 
0947   template <typename Unit>
0948   inline bool PolyLine<Unit>::active() const {
0949     return !to_bool(tailp_);
0950   }
0951 
0952   template <typename Unit>
0953   inline PolyLine<Unit>& PolyLine<Unit>::pushCoordinate(Unit coord) {
0954     ptdata_.push_back(coord);
0955     return *this;
0956   }
0957 
0958   template <typename Unit>
0959   inline PolyLine<Unit>& PolyLine<Unit>::popCoordinate() {
0960     ptdata_.pop_back();
0961     return *this;
0962   }
0963 
0964   template <typename Unit>
0965   inline PolyLine<Unit>& PolyLine<Unit>::pushPoint(const point_data<Unit>& point) {
0966      if(numSegments()){
0967        point_data<Unit> endPt = getEndPoint();
0968        //vertical is true, horizontal is false
0969        if((tailOrient().to_int() ? point.get(VERTICAL) == endPt.get(VERTICAL) : point.get(HORIZONTAL) == endPt.get(HORIZONTAL))) {
0970          //we were pushing a colinear segment
0971          return popCoordinate();
0972        }
0973      }
0974     return pushCoordinate(tailOrient().to_int() ? point.get(VERTICAL) : point.get(HORIZONTAL));
0975   }
0976 
0977   template <typename Unit>
0978   inline PolyLine<Unit>& PolyLine<Unit>::extendTail(Unit delta) {
0979     ptdata_.back() += delta;
0980     return *this;
0981   }
0982 
0983   //private member function that creates a link from this PolyLine to that
0984   template <typename Unit>
0985   inline PolyLine<Unit>& PolyLine<Unit>::joinTo_(End thisEnd, PolyLine<Unit>& that, End end) {
0986     if(thisEnd){
0987       tailp_ = &that;
0988       state_ &= ~TAIL_TO_TAIL; //clear any previous state_ of bit (for safety)
0989       state_ |= (end << 2); //place bit into mask
0990     } else {
0991       headp_ = &that;
0992       state_ &= ~HEAD_TO_TAIL; //clear any previous state_ of bit (for safety)
0993       state_ |= (end << 1); //place bit into mask
0994     }
0995     return *this;
0996   }
0997 
0998   //join two PolyLines (both ways of the association)
0999   template <typename Unit>
1000   inline PolyLine<Unit>& PolyLine<Unit>::joinTo(End thisEnd, PolyLine<Unit>& that, End end) {
1001     joinTo_(thisEnd, that, end);
1002     that.joinTo_(end, *this, thisEnd);
1003     return *this;
1004   }
1005 
1006   //convenience functions for joining PolyLines
1007   template <typename Unit>
1008   inline PolyLine<Unit>& PolyLine<Unit>::joinToTail(PolyLine<Unit>& that, End end) {
1009     return joinTo(TAIL, that, end);
1010   }
1011   template <typename Unit>
1012   inline PolyLine<Unit>& PolyLine<Unit>::joinToHead(PolyLine<Unit>& that, End end) {
1013     return joinTo(HEAD, that, end);
1014   }
1015   template <typename Unit>
1016   inline PolyLine<Unit>& PolyLine<Unit>::joinHeadToHead(PolyLine<Unit>& that) {
1017     return joinToHead(that, HEAD);
1018   }
1019   template <typename Unit>
1020   inline PolyLine<Unit>& PolyLine<Unit>::joinHeadToTail(PolyLine<Unit>& that) {
1021     return joinToHead(that, TAIL);
1022   }
1023   template <typename Unit>
1024   inline PolyLine<Unit>& PolyLine<Unit>::joinTailToHead(PolyLine<Unit>& that) {
1025     return joinToTail(that, HEAD);
1026   }
1027   template <typename Unit>
1028   inline PolyLine<Unit>& PolyLine<Unit>::joinTailToTail(PolyLine<Unit>& that) {
1029     return joinToTail(that, TAIL);
1030   }
1031 
1032   template <typename Unit>
1033   inline PolyLine<Unit>& PolyLine<Unit>::disconnectTails() {
1034     next(TAIL)->state_ &= !TAIL_TO_TAIL;
1035     next(TAIL)->tailp_ = 0;
1036     state_ &= !TAIL_TO_TAIL;
1037     tailp_ = 0;
1038     return *this;
1039   }
1040 
1041   template <typename Unit>
1042   inline Unit PolyLine<Unit>::getEndCoord(End end) const {
1043     if(end)
1044       return ptdata_.back();
1045     return ptdata_.front();
1046   }
1047 
1048   template <typename Unit>
1049   inline orientation_2d PolyLine<Unit>::segmentOrient(unsigned int index) const {
1050     return (to_bool((unsigned int)verticalHead() ^ (index % 2)) ? VERTICAL : HORIZONTAL);
1051   }
1052 
1053   template <typename Unit>
1054   inline point_data<Unit> PolyLine<Unit>::getPoint(unsigned int index) const {
1055     //assert(isValid() && headp_->isValid()) ("PolyLine: headp_ must be valid");
1056     point_data<Unit> pt;
1057     pt.set(HORIZONTAL, ptdata_[index]);
1058     pt.set(VERTICAL, ptdata_[index]);
1059     Unit prevCoord;
1060     if(index == 0) {
1061       prevCoord = headp_->getEndCoord(headToTail());
1062     } else {
1063       prevCoord = ptdata_[index-1];
1064     }
1065     pt.set(segmentOrient(index), prevCoord);
1066     return pt;
1067   }
1068 
1069   template <typename Unit>
1070   inline point_data<Unit> PolyLine<Unit>::getEndPoint(End end) const {
1071     return getPoint((end ? numSegments() - 1 : (unsigned int)0));
1072   }
1073 
1074   template <typename Unit>
1075   inline Unit PolyLine<Unit>::operator[] (unsigned int index) const {
1076     //assert(ptdata_.size() > index) ("PolyLine: out of bounds index");
1077     return ptdata_[index];
1078   }
1079 
1080   template <typename Unit>
1081   inline unsigned int PolyLine<Unit>::numSegments() const {
1082     return ptdata_.size();
1083   }
1084 
1085   template <typename Unit>
1086   inline PolyLine<Unit>* PolyLine<Unit>::next(End end) const {
1087     return (end ? tailp_ : headp_);
1088   }
1089 
1090   template <typename Unit>
1091   inline ActiveTail<Unit>::ActiveTail() : tailp_(0), otherTailp_(0), holesList_(),
1092    polyLineSize_(0) {}
1093 
1094   template <typename Unit>
1095   inline ActiveTail<Unit>::ActiveTail(orientation_2d orient, Unit coord, Side solidToRight, ActiveTail* otherTailp) :
1096     tailp_(0), otherTailp_(0), holesList_(), polyLineSize_(0) {
1097     tailp_ = createPolyLine(orient, coord, solidToRight);
1098     otherTailp_ = otherTailp;
1099     polyLineSize_ = tailp_->numSegments();
1100   }
1101 
1102   template <typename Unit>
1103   inline ActiveTail<Unit>::ActiveTail(PolyLine<Unit>* active, ActiveTail<Unit>* otherTailp) :
1104     tailp_(active), otherTailp_(otherTailp), holesList_(),
1105       polyLineSize_(0) {}
1106 
1107   //copy constructor
1108   template <typename Unit>
1109   inline ActiveTail<Unit>::ActiveTail(const ActiveTail<Unit>& that) : tailp_(that.tailp_), otherTailp_(that.otherTailp_), holesList_(), polyLineSize_(that.polyLineSize_) {}
1110 
1111   //destructor
1112   template <typename Unit>
1113   inline ActiveTail<Unit>::~ActiveTail() {
1114     //clear them in case the memory is read later
1115     tailp_ = 0; otherTailp_ = 0;
1116   }
1117 
1118   template <typename Unit>
1119   inline ActiveTail<Unit>& ActiveTail<Unit>::operator=(const ActiveTail<Unit>& that) {
1120     //self assignment is safe in this case
1121     tailp_ = that.tailp_;
1122     otherTailp_ = that.otherTailp_;
1123     polyLineSize_ = that.polyLineSize_;
1124     return *this;
1125   }
1126 
1127   template <typename Unit>
1128   inline bool ActiveTail<Unit>::operator==(const ActiveTail<Unit>& b) const {
1129     return tailp_ == b.tailp_ && otherTailp_ == b.otherTailp_;
1130   }
1131 
1132   template <typename Unit>
1133   inline bool ActiveTail<Unit>::operator<(const ActiveTail<Unit>& b) const {
1134     return tailp_->getEndPoint().get(VERTICAL) < b.tailp_->getEndPoint().get(VERTICAL);
1135   }
1136 
1137   template <typename Unit>
1138   inline bool ActiveTail<Unit>::operator<=(const ActiveTail<Unit>& b) const {
1139     return !(*this > b); }
1140 
1141   template <typename Unit>
1142   inline bool ActiveTail<Unit>::operator>(const ActiveTail<Unit>& b) const {
1143     return b < (*this); }
1144 
1145   template <typename Unit>
1146   inline bool ActiveTail<Unit>::operator>=(const ActiveTail<Unit>& b) const {
1147     return !(*this < b); }
1148 
1149   template <typename Unit>
1150   inline PolyLine<Unit>* ActiveTail<Unit>::getTail() const {
1151     return tailp_; }
1152 
1153   template <typename Unit>
1154   inline PolyLine<Unit>* ActiveTail<Unit>::getOtherTail() const {
1155     return otherTailp_->tailp_; }
1156 
1157   template <typename Unit>
1158   inline ActiveTail<Unit>* ActiveTail<Unit>::getOtherActiveTail() const {
1159     return otherTailp_; }
1160 
1161   template <typename Unit>
1162   inline bool ActiveTail<Unit>::isOtherTail(const ActiveTail<Unit>& b) {
1163     //       assert( (tailp_ == b.getOtherTail() && getOtherTail() == b.tailp_) ||
1164     //                     (tailp_ != b.getOtherTail() && getOtherTail() != b.tailp_))
1165     //         ("ActiveTail: Active tails out of sync");
1166     return otherTailp_ == &b;
1167   }
1168 
1169   template <typename Unit>
1170   inline ActiveTail<Unit>& ActiveTail<Unit>::updateTail(PolyLine<Unit>* newTail) {
1171     //subtract the old size and add new size//
1172     int delta = newTail->numSegments() - tailp_->numSegments();
1173     addPolyLineSize(delta);
1174     otherTailp_->addPolyLineSize(delta);
1175     tailp_ = newTail;
1176     return *this;
1177   }
1178 
1179   template <typename Unit>
1180   inline ActiveTail<Unit>* ActiveTail<Unit>::addHole(ActiveTail<Unit>* hole, bool fractureHoles) {
1181 
1182     if(!fractureHoles){
1183       holesList_.push_back(hole);
1184       copyHoles(*hole);
1185       copyHoles(*(hole->getOtherActiveTail()));
1186       return this;
1187     }
1188     ActiveTail<Unit>* h, *v;
1189     ActiveTail<Unit>* other = hole->getOtherActiveTail();
1190     if(other->getOrient() == VERTICAL) {
1191       //assert that hole.getOrient() == HORIZONTAL
1192       //this case should never happen
1193       h = hole;
1194       v = other;
1195     } else {
1196       //assert that hole.getOrient() == VERTICAL
1197       h = other;
1198       v = hole;
1199     }
1200     h->pushCoordinate(v->getCoordinate());
1201     //assert that h->getOrient() == VERTICAL
1202     //v->pushCoordinate(getCoordinate());
1203     //assert that v->getOrient() == VERTICAL
1204     //I can't close a figure by adding a hole, so pass zero for xMin and yMin
1205     std::vector<Unit> tmpVec;
1206     ActiveTail<Unit>::joinChains(this, h, false, tmpVec);
1207     return v;
1208   }
1209 
1210   template <typename Unit>
1211   inline const std::list<ActiveTail<Unit>*>& ActiveTail<Unit>::getHoles() const {
1212     return holesList_;
1213   }
1214 
1215   template <typename Unit>
1216   inline void ActiveTail<Unit>::copyHoles(ActiveTail<Unit>& that) {
1217     holesList_.splice(holesList_.end(), that.holesList_); //splice the two lists together
1218   }
1219 
1220   template <typename Unit>
1221   inline bool ActiveTail<Unit>::solidToRight() const {
1222     return getTail()->solidToRight(); }
1223 
1224   template <typename Unit>
1225   inline Unit ActiveTail<Unit>::getCoord() const {
1226     return getTail()->getEndCoord(); }
1227 
1228   template <typename Unit>
1229   inline Unit ActiveTail<Unit>::getCoordinate() const {
1230     return getCoord(); }
1231 
1232   template <typename Unit>
1233   inline orientation_2d ActiveTail<Unit>::getOrient() const {
1234     return getTail()->tailOrient(); }
1235 
1236   template <typename Unit>
1237   inline void ActiveTail<Unit>::pushCoordinate(Unit coord) {
1238     //appropriately handle any co-linear polyline segments by calling push point internally
1239     point_data<Unit> p;
1240     p.set(HORIZONTAL, coord);
1241     p.set(VERTICAL, coord);
1242     //if we are vertical assign the last coordinate (an X) to p.x, else to p.y
1243     p.set(getOrient().get_perpendicular(), getCoordinate());
1244     int oldSegments = tailp_->numSegments();
1245     tailp_->pushPoint(p);
1246     int delta = tailp_->numSegments() - oldSegments;
1247     addPolyLineSize(delta);
1248     otherTailp_->addPolyLineSize(delta);
1249   }
1250 
1251 
1252   //global utility functions
1253   template <typename Unit>
1254   inline PolyLine<Unit>* createPolyLine(orientation_2d orient, Unit coord, Side side) {
1255     return new PolyLine<Unit>(orient, coord, side);
1256   }
1257 
1258   template <typename Unit>
1259   inline void destroyPolyLine(PolyLine<Unit>* pLine) {
1260     delete pLine;
1261   }
1262 
1263   template <typename Unit>
1264   inline ActiveTail<Unit>* createActiveTail() {
1265     //consider replacing system allocator with ActiveTail memory pool
1266     return new ActiveTail<Unit>();
1267   }
1268 
1269   template <typename Unit>
1270   inline void destroyActiveTail(ActiveTail<Unit>* aTail) {
1271     delete aTail;
1272   }
1273 
1274 
1275   //no recursion, to prevent max recursion depth errors
1276   template <typename Unit>
1277   inline void ActiveTail<Unit>::destroyContents() {
1278     tailp_->disconnectTails();
1279     PolyLine<Unit>* nextPolyLinep = tailp_->next(HEAD);
1280     End end = tailp_->endConnectivity(HEAD);
1281     destroyPolyLine(tailp_);
1282     while(nextPolyLinep) {
1283       End nextEnd = nextPolyLinep->endConnectivity(!end); //get the direction of next polyLine
1284       PolyLine<Unit>* nextNextPolyLinep = nextPolyLinep->next(!end); //get the next polyline
1285       destroyPolyLine(nextPolyLinep); //destroy the current polyline
1286       end = nextEnd;
1287       nextPolyLinep = nextNextPolyLinep;
1288     }
1289   }
1290 
1291   template <typename Unit>
1292   inline typename ActiveTail<Unit>::iterator ActiveTail<Unit>::begin(bool isHole, orientation_2d orient) const {
1293     return iterator(this, isHole, orient);
1294   }
1295 
1296   template <typename Unit>
1297   inline typename ActiveTail<Unit>::iterator ActiveTail<Unit>::end() const {
1298     return iterator();
1299   }
1300 
1301   template <typename Unit>
1302   inline typename ActiveTail<Unit>::iteratorHoles ActiveTail<Unit>::beginHoles() const {
1303     return holesList_.begin();
1304   }
1305 
1306   template <typename Unit>
1307   inline typename ActiveTail<Unit>::iteratorHoles ActiveTail<Unit>::endHoles() const {
1308     return holesList_.end();
1309   }
1310 
1311   template <typename Unit>
1312   inline void ActiveTail<Unit>::writeOutFigureItrs(iterator& beginOut, iterator& endOut, bool isHole, orientation_2d orient) const {
1313     beginOut = begin(isHole, orient);
1314     endOut = end();
1315   }
1316 
1317   template <typename Unit>
1318   inline void ActiveTail<Unit>::writeOutFigureHoleItrs(iteratorHoles& beginOut, iteratorHoles& endOut) const {
1319     beginOut = beginHoles();
1320     endOut = endHoles();
1321   }
1322 
1323   template <typename Unit>
1324   inline void ActiveTail<Unit>::writeOutFigure(std::vector<Unit>& outVec, bool isHole) const {
1325     //we start writing out the polyLine that this active tail points to at its tail
1326     std::size_t size = outVec.size();
1327     outVec.push_back(0); //place holder for size
1328     PolyLine<Unit>* nextPolyLinep = 0;
1329     if(!isHole){
1330       nextPolyLinep = otherTailp_->tailp_->writeOut(outVec);
1331     } else {
1332       nextPolyLinep = tailp_->writeOut(outVec);
1333     }
1334     Unit firsty = outVec[size + 1];
1335     if((getOrient() == HORIZONTAL) ^ !isHole) {
1336       //our first coordinate is a y value, so we need to rotate it to the end
1337       typename std::vector<Unit>::iterator tmpItr = outVec.begin();
1338       tmpItr += size;
1339       outVec.erase(++tmpItr); //erase the 2nd element
1340     }
1341     End startEnd = tailp_->endConnectivity(HEAD);
1342     if(isHole) startEnd = otherTailp_->tailp_->endConnectivity(HEAD);
1343     while(nextPolyLinep) {
1344       bool nextStartEnd = nextPolyLinep->endConnectivity(!startEnd);
1345       nextPolyLinep = nextPolyLinep->writeOut(outVec, startEnd);
1346       startEnd = nextStartEnd;
1347     }
1348     if((getOrient() == HORIZONTAL) ^ !isHole) {
1349       //we want to push the y value onto the end since we ought to have ended with an x
1350       outVec.push_back(firsty); //should never be executed because we want first value to be an x
1351     }
1352     //the vector contains the coordinates of the linked list of PolyLines in the correct order
1353     //first element is supposed to be the size
1354     outVec[size] = outVec.size() - 1 - size;  //number of coordinates in vector
1355     //assert outVec[size] % 2 == 0 //it should be even
1356     //make the size negative for holes
1357     outVec[size] *= (isHole ? -1 : 1);
1358   }
1359 
1360   //no recursion to prevent max recursion depth errors
1361   template <typename Unit>
1362   inline PolyLine<Unit>* PolyLine<Unit>::writeOut(std::vector<Unit>& outVec, End startEnd) const {
1363     if(startEnd == HEAD){
1364       //forward order
1365       outVec.insert(outVec.end(), ptdata_.begin(), ptdata_.end());
1366       return tailp_;
1367     }else{
1368       //reverse order
1369       //do not reserve because we expect outVec to be large enough already
1370       for(int i = ptdata_.size() - 1; i >= 0; --i){
1371         outVec.push_back(ptdata_[i]);
1372       }
1373       //NT didn't know about this version of the API....
1374       //outVec.insert(outVec.end(), ptdata_.rbegin(), ptdata_.rend());
1375       return headp_;
1376     }
1377   }
1378 
1379   //solid indicates if it was joined by a solit or a space
1380   template <typename Unit>
1381   inline ActiveTail<Unit>* ActiveTail<Unit>::joinChains(ActiveTail<Unit>* at1, ActiveTail<Unit>* at2, bool solid, std::vector<Unit>& outBufferTmp)
1382   {
1383     //checks to see if we closed a figure
1384     if(at1->isOtherTail(*at2)){
1385       //value of solid tells us if we closed solid or hole
1386       //and output the solid or handle the hole appropriately
1387       //if the hole needs to fracture across horizontal partition boundary we need to notify
1388       //the calling context to do so
1389       if(solid) {
1390         //the chains are being joined because there is solid to the right
1391         //this means that if the figure is closed at this point it must be a hole
1392         //because otherwise it would have to have another vertex to the right of this one
1393         //and would not be closed at this point
1394         return at1;
1395       } else {
1396         //assert pG != 0
1397         //the figure that was closed is a shell
1398         at1->writeOutFigure(outBufferTmp);
1399         //process holes of the polygon
1400         at1->copyHoles(*at2); //there should not be holes on at2, but if there are, copy them over
1401         const std::list<ActiveTail<Unit>*>& holes = at1->getHoles();
1402         for(typename std::list<ActiveTail<Unit>*>::const_iterator litr = holes.begin(); litr != holes.end(); ++litr) {
1403           (*litr)->writeOutFigure(outBufferTmp, true);
1404           //delete the hole
1405           (*litr)->destroyContents();
1406           destroyActiveTail((*litr)->getOtherActiveTail());
1407           destroyActiveTail((*litr));
1408         }
1409         //delete the polygon
1410         at1->destroyContents();
1411         //at2 contents are the same as at1, so it should not destroy them
1412         destroyActiveTail(at1);
1413         destroyActiveTail(at2);
1414       }
1415       return 0;
1416     }
1417     //join the two partial polygons into one large partial polygon
1418     at1->getTail()->joinTailToTail(*(at2->getTail()));
1419     *(at1->getOtherActiveTail()) = ActiveTail(at1->getOtherTail(), at2->getOtherActiveTail());
1420     *(at2->getOtherActiveTail()) = ActiveTail(at2->getOtherTail(), at1->getOtherActiveTail());
1421 
1422     int accumulate = at2->getPolyLineSize() + at1->getPolyLineSize();
1423     (at1->getOtherActiveTail())->setPolyLineSize(accumulate);
1424     (at2->getOtherActiveTail())->setPolyLineSize(accumulate);
1425 
1426     at1->getOtherActiveTail()->copyHoles(*at1);
1427     at1->getOtherActiveTail()->copyHoles(*at2);
1428     destroyActiveTail(at1);
1429     destroyActiveTail(at2);
1430     return 0;
1431   }
1432 
1433   //solid indicates if it was joined by a solit or a space
1434   template <typename Unit>
1435   template <typename PolygonT>
1436   inline ActiveTail<Unit>* ActiveTail<Unit>::joinChains(ActiveTail<Unit>* at1, ActiveTail<Unit>* at2, bool solid,
1437                                                         std::vector<PolygonT>& outBufferTmp) {
1438     //checks to see if we closed a figure
1439     if(at1->isOtherTail(*at2)){
1440       //value of solid tells us if we closed solid or hole
1441       //and output the solid or handle the hole appropriately
1442       //if the hole needs to fracture across horizontal partition boundary we need to notify
1443       //the calling context to do so
1444       if(solid) {
1445         //the chains are being joined because there is solid to the right
1446         //this means that if the figure is closed at this point it must be a hole
1447         //because otherwise it would have to have another vertex to the right of this one
1448         //and would not be closed at this point
1449         return at1;
1450       } else {
1451         //assert pG != 0
1452         //the figure that was closed is a shell
1453         outBufferTmp.push_back(at1);
1454         at1->copyHoles(*at2); //there should not be holes on at2, but if there are, copy them over
1455       }
1456       return 0;
1457     }
1458     //join the two partial polygons into one large partial polygon
1459     at1->getTail()->joinTailToTail(*(at2->getTail()));
1460     *(at1->getOtherActiveTail()) = ActiveTail<Unit>(at1->getOtherTail(), at2->getOtherActiveTail());
1461     *(at2->getOtherActiveTail()) = ActiveTail<Unit>(at2->getOtherTail(), at1->getOtherActiveTail());
1462 
1463     int accumulate = at2->getPolyLineSize() + at1->getPolyLineSize();
1464     (at1->getOtherActiveTail())->setPolyLineSize(accumulate);
1465     (at2->getOtherActiveTail())->setPolyLineSize(accumulate);
1466 
1467     at1->getOtherActiveTail()->copyHoles(*at1);
1468     at1->getOtherActiveTail()->copyHoles(*at2);
1469     destroyActiveTail(at1);
1470     destroyActiveTail(at2);
1471     return 0;
1472   }
1473 
1474   template <class TKey, class T> inline typename std::map<TKey, T>::iterator findAtNext(std::map<TKey, T>& theMap,
1475                                                                                         typename std::map<TKey, T>::iterator pos, const TKey& key)
1476   {
1477     if(pos == theMap.end()) return theMap.find(key);
1478     //if they match the mapItr is pointing to the correct position
1479     if(pos->first < key) {
1480       return theMap.find(key);
1481     }
1482     if(pos->first > key) {
1483       return theMap.end();
1484     }
1485     //else they are equal and no need to do anything to the iterator
1486     return pos;
1487   }
1488 
1489   // createActiveTailsAsPair is called in these two end cases of geometry
1490   // 1. lower left concave corner
1491   //         ###|
1492   //         ###|
1493   //         ###|###
1494   //         ###|###
1495   // 2. lower left convex corner
1496   //            |###
1497   //            |###
1498   //            |
1499   //            |
1500   // In case 1 there may be a hole propigated up from the bottom.  If the fracture option is enabled
1501   // the two active tails that form the filament fracture line edges can become the new active tail pair
1502   // by pushing x and y onto them.  Otherwise the hole simply needs to be associated to one of the new active tails
1503   // with add hole
1504   template <typename Unit>
1505   inline std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> createActiveTailsAsPair(Unit x, Unit y, bool solid, ActiveTail<Unit>* phole, bool fractureHoles) {
1506     ActiveTail<Unit>* at1 = 0;
1507     ActiveTail<Unit>* at2 = 0;
1508     if(!phole || !fractureHoles){
1509       at1 = createActiveTail<Unit>();
1510       at2 = createActiveTail<Unit>();
1511       (*at1) = ActiveTail<Unit>(VERTICAL, x, solid, at2);
1512       (*at2) = ActiveTail<Unit>(HORIZONTAL, y, !solid, at1);
1513       //provide a function through activeTail class to provide this
1514       at1->getTail()->joinHeadToHead(*(at2->getTail()));
1515 
1516       at1->addPolyLineSize(1);
1517       at2->addPolyLineSize(1);
1518 
1519       if(phole)
1520         at1->addHole(phole, fractureHoles); //assert fractureHoles == false
1521       return std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*>(at1, at2);
1522     }
1523     //assert phole is not null
1524     //assert fractureHoles is true
1525     if(phole->getOrient() == VERTICAL) {
1526       at2 = phole;
1527     } else {
1528       at2 = phole->getOtherActiveTail(); //should never be executed since orientation is expected to be vertical
1529     }
1530     //assert solid == false, we should be creating a corner with solid below and to the left if there was a hole
1531     at1 = at2->getOtherActiveTail();
1532     //assert at1 is horizontal
1533     at1->pushCoordinate(x);
1534     //assert at2 is vertical
1535     at2->pushCoordinate(y);
1536 
1537     return std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*>(at1, at2);
1538   }
1539 
1540   /*
1541    *     |
1542    *     |
1543    *     =
1544    *     |########
1545    *     |########  (add a new ActiveTail in the tailMap_).
1546    *     |########
1547    *     |########
1548    *     |########
1549    *     =
1550    *     |
1551    *     |
1552    *
1553    * NOTE: Call this only if you are sure that the $ledege$ is not in the tailMap_
1554    */
1555   template<bool orientT, typename Unit, typename polygon_concept_type>
1556   inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
1557   insertNewLeftEdgeIntoTailMap(Unit currentX, Unit yBegin, Unit yEnd,
1558    typename std::map<Unit, ActiveTail<Unit> *>::iterator &hint){
1559      ActiveTail<Unit> *currentTail = NULL;
1560      std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair =
1561       createActiveTailsAsPair(currentX, yBegin, true, currentTail,
1562          fractureHoles_);
1563      currentTail = tailPair.first;
1564      if(!tailMap_.empty()){
1565         ++hint;
1566      }
1567      hint = tailMap_.insert(hint, std::make_pair(yBegin, tailPair.second));
1568      currentTail->pushCoordinate(yEnd); ++hint;
1569      hint = tailMap_.insert(hint, std::make_pair(yEnd, currentTail));
1570   }
1571 
1572   template<bool orientT, typename Unit, typename polygon_concept_type>
1573   inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
1574   closePartialSimplePolygon(Unit currentX, ActiveTail<Unit>*pfig,
1575       ActiveTail<Unit>*ppfig){
1576      pfig->pushCoordinate(currentX);
1577      ActiveTail<Unit>::joinChains(pfig, ppfig, false, outputPolygons_);
1578   }
1579   /*
1580    * If the invariant is maintained correctly then left edges can do the
1581    * following.
1582    *
1583    *               =###
1584    *            #######
1585    *            #######
1586    *            #######
1587    *            #######
1588    *               =###
1589    *               |### (input left edge)
1590    *               |###
1591    *               =###
1592    *            #######
1593    *            #######
1594    *               =###
1595    */
1596   template<bool orientT, typename Unit, typename polygon_concept_type>
1597   inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
1598   updatePartialSimplePolygonsWithLeftEdges(Unit currentX,
1599    const std::vector<interval_data<Unit> > &leftEdges, size_t vertexThreshold){
1600      typename std::map<Unit, ActiveTail<Unit>* >::iterator succ, succ1;
1601      typename std::map<Unit, ActiveTail<Unit>* >::iterator pred, pred1, hint;
1602      Unit begin, end;
1603      ActiveTail<Unit> *pfig, *ppfig;
1604      std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair;
1605      size_t pfig_size = 0;
1606 
1607      hint = tailMap_.begin();
1608      for(size_t i=0; i < leftEdges.size(); i++){
1609         begin = leftEdges[i].get(LOW); end = leftEdges[i].get(HIGH);
1610         succ = findAtNext(tailMap_, hint, begin);
1611         pred = findAtNext(tailMap_, hint, end);
1612 
1613         if(succ != tailMap_.end() && pred != tailMap_.end()){ //CASE-1//
1614            //join the corresponding active tails//
1615            pfig = succ->second; ppfig = pred->second;
1616            pfig_size = pfig->getPolyLineSize() + ppfig->getPolyLineSize();
1617 
1618            if(pfig_size >= vertexThreshold){
1619               size_t bsize = pfig->getPolyLineSize();
1620               size_t usize = ppfig->getPolyLineSize();
1621 
1622               if(usize+2 < vertexThreshold){
1623                  //cut-off the lower piece (succ1, succ) join (succ1, pred)//
1624                  succ1 = succ; --succ1;
1625                  assert((succ1 != tailMap_.end()) &&
1626                   ((succ->second)->getOtherActiveTail() == succ1->second));
1627                  closePartialSimplePolygon(currentX, succ1->second, succ->second);
1628                  tailPair = createActiveTailsAsPair<Unit>(currentX, succ1->first,
1629                      true, NULL, fractureHoles_);
1630 
1631                  //just update the succ1 with new ActiveTail<Unit>*//
1632                  succ1->second = tailPair.second;
1633                  ActiveTail<Unit>::joinChains(tailPair.first, pred->second, true,
1634                      outputPolygons_);
1635               }else if(bsize+2 < vertexThreshold){
1636                  //cut-off the upper piece () join ()//
1637                  pred1 = pred; ++pred1;
1638                  assert(pred1 != tailMap_.end() &&
1639                   ((pred1->second)->getOtherActiveTail() == pred->second));
1640                  closePartialSimplePolygon(currentX, pred->second, pred1->second);
1641 
1642                  //just update the pred1 with ActiveTail<Unit>* = pfig//
1643                  pred1->second = pfig;
1644                  pfig->pushCoordinate(currentX);
1645                  pfig->pushCoordinate(pred1->first);
1646               }else{
1647                  //cut both and create an left edge between (pred->first, succ1)//
1648                  succ1 = succ; --succ1;
1649                  pred1 = pred; ++pred1;
1650                  assert(pred1 != tailMap_.end() && succ1 != tailMap_.end());
1651                  assert((pred1->second)->getOtherActiveTail() == pred->second);
1652                  assert((succ1->second)->getOtherActiveTail() == succ->second);
1653 
1654                  closePartialSimplePolygon(currentX, succ1->second, succ->second);
1655                  closePartialSimplePolygon(currentX, pred->second, pred1->second);
1656 
1657                  tailPair = createActiveTailsAsPair<Unit>(currentX, succ1->first,
1658                      true, NULL, fractureHoles_);
1659                  succ1->second = tailPair.second;
1660                  pred1->second = tailPair.first;
1661                  (tailPair.first)->pushCoordinate(pred1->first);
1662               }
1663            }else{
1664               //just join them with closing//
1665               pfig->pushCoordinate(currentX);
1666               ActiveTail<Unit>::joinChains(pfig, ppfig, true, outputPolygons_);
1667            }
1668            hint = pred; ++hint;
1669            tailMap_.erase(succ); tailMap_.erase(pred);
1670         }else if(succ == tailMap_.end() && pred != tailMap_.end()){ //CASE-2//
1671            //succ is missing in the map, first insert it into the map//
1672            tailPair = createActiveTailsAsPair<Unit>(currentX, begin, true, NULL,
1673                fractureHoles_);
1674            hint = pred; ++hint;
1675            hint = tailMap_.insert(hint, std::make_pair(begin, tailPair.second));
1676 
1677            pfig = pred->second;
1678            pfig_size = pfig->getPolyLineSize() + 2;
1679            if(pfig_size >= vertexThreshold){
1680               //cut-off piece from [pred, pred1] , add [begin, pred1]//
1681               pred1 = pred; ++pred1;
1682               assert((pred1 != tailMap_.end()) &&
1683                ((pred1->second)->getOtherActiveTail() == pred->second));
1684               closePartialSimplePolygon(currentX, pred->second, pred1->second);
1685 
1686               //update: we need left edge between (begin, pred1->first)//
1687               pred1->second = tailPair.first;
1688               (tailPair.first)->pushCoordinate(pred1->first);
1689            }else{
1690               //just join//
1691               ActiveTail<Unit>::joinChains(tailPair.first, pfig,
1692                   true, outputPolygons_);
1693            }
1694            tailMap_.erase(pred);
1695         }else if(succ != tailMap_.end() && pred == tailMap_.end()){ //CASE-3//
1696             //pred is missing in the map, first insert it into the map//
1697             hint = succ; ++hint;
1698             hint = tailMap_.insert(hint, std::make_pair(end, (ActiveTail<Unit> *) NULL));
1699             pfig = succ->second;
1700             pfig_size = pfig->getPolyLineSize() + 2;
1701             if(pfig_size >= vertexThreshold){
1702                //this figure needs cutting here//
1703                succ1 = succ; --succ1;
1704                assert((succ1 != tailMap_.end()) &&
1705                   (succ1->second == pfig->getOtherActiveTail()));
1706                ppfig = succ1->second;
1707                closePartialSimplePolygon(currentX, ppfig, pfig);
1708 
1709                //update: we need a left edge between (succ1->first, end)//
1710                tailPair = createActiveTailsAsPair<Unit>(currentX, succ1->first,
1711                   true, NULL, fractureHoles_);
1712                succ1->second = tailPair.second;
1713                hint->second = tailPair.first;
1714                (tailPair.first)->pushCoordinate(end);
1715             }else{
1716                //no cutting needed//
1717                hint->second = pfig;
1718                pfig->pushCoordinate(currentX);
1719                pfig->pushCoordinate(end);
1720             }
1721             tailMap_.erase(succ);
1722         }else{
1723            //insert both pred and succ//
1724            insertNewLeftEdgeIntoTailMap(currentX, begin, end, hint);
1725         }
1726      }
1727   }
1728 
1729   template<bool orientT, typename Unit, typename polygon_concept_type>
1730   inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
1731   updatePartialSimplePolygonsWithRightEdges(Unit currentX,
1732    const std::vector<interval_data<Unit> > &rightEdges, size_t vertexThreshold)
1733    {
1734 
1735      typename std::map<Unit, ActiveTail<Unit>* >::iterator succ, pred, hint;
1736      std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair;
1737      Unit begin, end;
1738      size_t i = 0;
1739      //If rightEdges is non-empty Then tailMap_ is non-empty //
1740      assert(rightEdges.empty() || !tailMap_.empty() );
1741 
1742      while( i < rightEdges.size() ){
1743         //find the interval in the tailMap which contains this interval//
1744         pred = tailMap_.lower_bound(rightEdges[i].get(HIGH));
1745         assert(pred != tailMap_.end());
1746         succ = pred; --succ;
1747         assert(pred != succ);
1748         end =  pred->first; begin = succ->first;
1749 
1750         //we now have a [begin, end] //
1751         bool found_solid_opening = false;
1752         bool erase_succ = true, erase_pred = true;
1753         Unit solid_opening_begin = 0;
1754         Unit solid_opening_end = 0;
1755         size_t j = i+1;
1756         ActiveTail<Unit> *pfig = succ->second;
1757         ActiveTail<Unit> *ppfig = pred->second;
1758         size_t partial_fig_size = pfig->getPolyLineSize();
1759         //Invariant://
1760         assert(succ->second && (pfig)->getOtherActiveTail() == ppfig);
1761 
1762         hint = succ;
1763         Unit key = rightEdges[i].get(LOW);
1764         if(begin != key){
1765            found_solid_opening = true;
1766            solid_opening_begin = begin; solid_opening_end = key;
1767         }
1768 
1769         while(j < rightEdges.size() && rightEdges[j].get(HIGH) <= end){
1770            if(rightEdges[j-1].get(HIGH) != rightEdges[j].get(LOW)){
1771               if(!found_solid_opening){
1772                  found_solid_opening = true;
1773                  solid_opening_begin = rightEdges[j-1].get(HIGH);
1774                  solid_opening_end = rightEdges[j].get(LOW);
1775               }else{
1776                  ++hint;
1777                  insertNewLeftEdgeIntoTailMap(currentX,
1778                      rightEdges[j-1].get(HIGH), rightEdges[j].get(LOW), hint);
1779               }
1780            }
1781            j++;
1782         }
1783 
1784         //trailing edge//
1785         if(end != rightEdges[j-1].get(HIGH)){
1786            if(!found_solid_opening){
1787               found_solid_opening = true;
1788               solid_opening_begin = rightEdges[j-1].get(HIGH); solid_opening_end = end;
1789            }else{
1790               // a solid opening has been found already, we need to insert a new left
1791               // between [rightEdges[j-1].get(HIGH), end]
1792               Unit lbegin = rightEdges[j-1].get(HIGH);
1793               tailPair = createActiveTailsAsPair<Unit>(currentX, lbegin, true, NULL,
1794                   fractureHoles_);
1795               hint = tailMap_.insert(pred, std::make_pair(lbegin, tailPair.second));
1796               pred->second = tailPair.first;
1797               (tailPair.first)->pushCoordinate(end);
1798               erase_pred = false;
1799            }
1800         }
1801 
1802         size_t vertex_delta = ((begin != solid_opening_begin) &&
1803                (end != solid_opening_end)) ? 4 : 2;
1804 
1805         if(!found_solid_opening){
1806            //just close the figure, TODO: call closePartialPolygon//
1807            pfig->pushCoordinate(currentX);
1808            ActiveTail<Unit>::joinChains(pfig, ppfig, false, outputPolygons_);
1809            hint = pred; ++hint;
1810         }else if(partial_fig_size+vertex_delta >= vertexThreshold){
1811            //close the figure and add a pseudo left-edge//
1812            closePartialSimplePolygon(currentX, pfig, ppfig);
1813            assert(begin != solid_opening_begin || end != solid_opening_end);
1814 
1815            if(begin != solid_opening_begin && end != solid_opening_end){
1816                insertNewLeftEdgeIntoTailMap(currentX, solid_opening_begin,
1817                      solid_opening_end, hint);
1818            }else if(begin == solid_opening_begin){
1819               //we just need to update the succ in the tailMap_//
1820               tailPair = createActiveTailsAsPair<Unit>(currentX, solid_opening_begin,
1821                   true, NULL, fractureHoles_);
1822               succ->second = tailPair.second;
1823               hint = succ; ++hint;
1824               hint = tailMap_.insert(pred, std::make_pair(solid_opening_end,
1825                   tailPair.first));
1826               (tailPair.first)->pushCoordinate(solid_opening_end);
1827               erase_succ = false;
1828            }else{
1829               //we just need to update the pred in the tailMap_//
1830               tailPair = createActiveTailsAsPair<Unit>(currentX, solid_opening_begin,
1831                   true, NULL, fractureHoles_);
1832               hint = tailMap_.insert(pred, std::make_pair(solid_opening_begin,
1833                   tailPair.second));
1834               pred->second = tailPair.first;
1835               (tailPair.first)->pushCoordinate(solid_opening_end);
1836               erase_pred = false;
1837            }
1838         }else{
1839            //continue the figure (by adding at-most two new vertices)//
1840            if(begin != solid_opening_begin){
1841               pfig->pushCoordinate(currentX);
1842               pfig->pushCoordinate(solid_opening_begin);
1843               //insert solid_opening_begin//
1844               hint = succ; ++hint;
1845               hint = tailMap_.insert(hint, std::make_pair(solid_opening_begin, pfig));
1846            }else{
1847               erase_succ = false;
1848            }
1849 
1850            if(end != solid_opening_end){
1851               std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair =
1852                createActiveTailsAsPair<Unit>(currentX, solid_opening_end, false,
1853                      NULL, fractureHoles_);
1854               hint = pred; ++hint;
1855               hint = tailMap_.insert(hint, std::make_pair(solid_opening_end,
1856                   tailPair.second));
1857               ActiveTail<Unit>::joinChains(tailPair.first, ppfig, false,
1858                   outputPolygons_);
1859            }else{
1860               erase_pred = false;
1861            }
1862         }
1863 
1864         //Remove the pred and succ if necessary//
1865         if(erase_succ){
1866            tailMap_.erase(succ);
1867         }
1868         if(erase_pred){
1869            tailMap_.erase(pred);
1870         }
1871         i = j;
1872      }
1873  }
1874 
1875  // Maintains the following invariant:
1876  // a. All the partial polygons formed at any state can be closed
1877  //    by a single edge.
1878  template<bool orientT, typename Unit, typename polygon_concept_type>
1879  inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
1880  maintainPartialSimplePolygonInvariant(iterator& beginOutput,
1881    iterator& endOutput, Unit currentX, const std::vector<interval_data<Unit> >& l,
1882       const std::vector<interval_data<Unit> >& r, size_t vertexThreshold) {
1883 
1884       clearOutput_();
1885       if(!l.empty()){
1886          updatePartialSimplePolygonsWithLeftEdges(currentX, l, vertexThreshold);
1887       }
1888 
1889       if(!r.empty()){
1890          updatePartialSimplePolygonsWithRightEdges(currentX, r, vertexThreshold);
1891       }
1892       beginOutput = outputPolygons_.begin();
1893       endOutput = outputPolygons_.end();
1894 
1895   }
1896 
1897   //Process edges connects vertical input edges (right or left edges of figures) to horizontal edges stored as member
1898   //data of the scanline object.  It also creates now horizontal edges as needed to construct figures from edge data.
1899   //
1900   //There are only 12 geometric end cases where the scanline intersects a horizontal edge and even fewer unique
1901   //actions to take:
1902   // 1. Solid on both sides of the vertical partition after the current position and space on both sides before
1903   //         ###|###
1904   //         ###|###
1905   //            |
1906   //            |
1907   //    This case does not need to be handled because there is no vertical edge at the current x coordinate.
1908   //
1909   // 2. Solid on both sides of the vertical partition before the current position and space on both sides after
1910   //            |
1911   //            |
1912   //         ###|###
1913   //         ###|###
1914   //    This case does not need to be handled because there is no vertical edge at the current x coordinate.
1915   //
1916   // 3. Solid on the left of the vertical partition after the current position and space elsewhere
1917   //         ###|
1918   //         ###|
1919   //            |
1920   //            |
1921   //    The horizontal edge from the left is found and turns upward because of the vertical right edge to become
1922   //    the currently active vertical edge.
1923   //
1924   // 4. Solid on the left of the vertical partion before the current position and space elsewhere
1925   //            |
1926   //            |
1927   //         ###|
1928   //         ###|
1929   //    The horizontal edge from the left is found and joined to the currently active vertical edge.
1930   //
1931   // 5. Solid to the right above and below and solid to the left above current position.
1932   //         ###|###
1933   //         ###|###
1934   //            |###
1935   //            |###
1936   //    The horizontal edge from the left is found and joined to the currently active vertical edge,
1937   //    potentially closing a hole.
1938   //
1939   // 6. Solid on the left of the vertical partion before the current position and solid to the right above and below
1940   //            |###
1941   //            |###
1942   //         ###|###
1943   //         ###|###
1944   //    The horizontal edge from the left is found and turns upward because of the vertical right edge to become
1945   //    the currently active vertical edge.
1946   //
1947   // 7. Solid on the right of the vertical partition after the current position and space elsewhere
1948   //            |###
1949   //            |###
1950   //            |
1951   //            |
1952   //    Create two new ActiveTails, one is added to the horizontal edges and the other becomes the vertical currentTail
1953   //
1954   // 8. Solid on the right of the vertical partion before the current position and space elsewhere
1955   //            |
1956   //            |
1957   //            |###
1958   //            |###
1959   //    The currentTail vertical edge turns right and is added to the horizontal edges data
1960   //
1961   // 9. Solid to the right above and solid to the left above and below current position.
1962   //         ###|###
1963   //         ###|###
1964   //         ###|
1965   //         ###|
1966   //    The currentTail vertical edge turns right and is added to the horizontal edges data
1967   //
1968   // 10. Solid on the left of the vertical partion above and below the current position and solid to the right below
1969   //         ###|
1970   //         ###|
1971   //         ###|###
1972   //         ###|###
1973   //    Create two new ActiveTails, one is added to the horizontal edges data and the other becomes the vertical currentTail
1974   //
1975   // 11. Solid to the right above and solid to the left below current position.
1976   //            |###
1977   //            |###
1978   //         ###|
1979   //         ###|
1980   //    The currentTail vertical edge joins the horizontal edge from the left (may close a polygon)
1981   //    Create two new ActiveTails, one is added to the horizontal edges data and the other becomes the vertical currentTail
1982   //
1983   // 12. Solid on the left of the vertical partion above the current position and solid to the right below
1984   //         ###|
1985   //         ###|
1986   //            |###
1987   //            |###
1988   //    The currentTail vertical edge turns right and is added to the horizontal edges data.
1989   //    The horizontal edge from the left turns upward and becomes the currentTail vertical edge
1990   //
1991   template <bool orientT, typename Unit, typename polygon_concept_type>
1992   inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
1993   processEdges(iterator& beginOutput, iterator& endOutput,
1994                Unit currentX, std::vector<interval_data<Unit> >& leftEdges,
1995                std::vector<interval_data<Unit> >& rightEdges,
1996                size_t vertexThreshold) {
1997     clearOutput_();
1998     typename std::map<Unit, ActiveTail<Unit>*>::iterator nextMapItr;
1999     //foreach edge
2000     unsigned int leftIndex = 0;
2001     unsigned int rightIndex = 0;
2002     bool bottomAlreadyProcessed = false;
2003     ActiveTail<Unit>* currentTail = 0;
2004     const Unit UnitMax = (std::numeric_limits<Unit>::max)();
2005 
2006     if(vertexThreshold < (std::numeric_limits<size_t>::max)()){
2007       maintainPartialSimplePolygonInvariant(beginOutput, endOutput, currentX,
2008          leftEdges, rightEdges, vertexThreshold);
2009       return;
2010     }
2011 
2012     nextMapItr = tailMap_.begin();
2013     while(leftIndex < leftEdges.size() || rightIndex < rightEdges.size()) {
2014       interval_data<Unit>  edges[2] = {interval_data<Unit> (UnitMax, UnitMax),
2015          interval_data<Unit> (UnitMax, UnitMax)};
2016       bool haveNextEdge = true;
2017       if(leftIndex < leftEdges.size())
2018         edges[0] = leftEdges[leftIndex];
2019       else
2020         haveNextEdge = false;
2021       if(rightIndex < rightEdges.size())
2022         edges[1] = rightEdges[rightIndex];
2023       else
2024         haveNextEdge = false;
2025       bool trailingEdge = edges[1].get(LOW) < edges[0].get(LOW);
2026       interval_data<Unit> & edge = edges[trailingEdge];
2027       interval_data<Unit> & nextEdge = edges[!trailingEdge];
2028       //process this edge
2029       if(!bottomAlreadyProcessed) {
2030         //assert currentTail = 0
2031 
2032         //process the bottom end of this edge
2033         typename std::map<Unit, ActiveTail<Unit>*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(LOW));
2034         if(thisMapItr != tailMap_.end()) {
2035           //there is an edge in the map at the low end of this edge
2036           //it needs to turn upward and become the current tail
2037           ActiveTail<Unit>* tail = thisMapItr->second;
2038           if(currentTail) {
2039             //stitch currentTail into this tail
2040             currentTail = tail->addHole(currentTail, fractureHoles_);
2041             if(!fractureHoles_)
2042               currentTail->pushCoordinate(currentX);
2043           } else {
2044             currentTail = tail;
2045             currentTail->pushCoordinate(currentX);
2046           }
2047           //assert currentTail->getOrient() == VERTICAL
2048           nextMapItr = thisMapItr; //set nextMapItr to the next position after this one
2049           ++nextMapItr;
2050           //remove thisMapItr from the map
2051           tailMap_.erase(thisMapItr);
2052         } else {
2053           //there is no edge in the map at the low end of this edge
2054           //we need to create one and another one to be the current vertical tail
2055           //if this is a trailing edge then there is space to the right of the vertical edge
2056           //so pass the inverse of trailingEdge to indicate solid to the right
2057           std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair =
2058             createActiveTailsAsPair(currentX, edge.get(LOW), !trailingEdge, currentTail, fractureHoles_);
2059           currentTail = tailPair.first;
2060           tailMap_.insert(nextMapItr, std::pair<Unit, ActiveTail<Unit>*>(edge.get(LOW), tailPair.second));
2061           // leave nextMapItr unchanged
2062         }
2063 
2064       }
2065       if(haveNextEdge && edge.get(HIGH) == nextEdge.get(LOW)) {
2066         //the top of this edge is equal to the bottom of the next edge, process them both
2067         bottomAlreadyProcessed = true;
2068         typename std::map<Unit, ActiveTail<Unit>*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(HIGH));
2069         if(thisMapItr == tailMap_.end()) //assert this should never happen
2070           return;
2071         if(trailingEdge) {
2072           //geometry at this position
2073           //   |##
2074           //   |##
2075           // -----
2076           // ##|
2077           // ##|
2078           //current tail should join thisMapItr tail
2079           ActiveTail<Unit>* tail = thisMapItr->second;
2080           //pass false because they are being joined because space is to the right and it will close a solid figure
2081           ActiveTail<Unit>::joinChains(currentTail, tail, false, outputPolygons_);
2082           //two new tails are created, the vertical becomes current tail, the horizontal becomes thisMapItr tail
2083           //pass true becuase they are created at the lower left corner of some solid
2084           //pass null because there is no hole pointer possible
2085           std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair =
2086             createActiveTailsAsPair<Unit>(currentX, edge.get(HIGH), true, 0, fractureHoles_);
2087           currentTail = tailPair.first;
2088           thisMapItr->second = tailPair.second;
2089         } else {
2090           //geometry at this position
2091           // ##|
2092           // ##|
2093           // -----
2094           //   |##
2095           //   |##
2096           //current tail should turn right
2097           currentTail->pushCoordinate(edge.get(HIGH));
2098           //thisMapItr tail should turn up
2099           thisMapItr->second->pushCoordinate(currentX);
2100           //thisMapItr tail becomes current tail and current tail becomes thisMapItr tail
2101           std::swap(currentTail, thisMapItr->second);
2102         }
2103         nextMapItr = thisMapItr; //set nextMapItr to the next position after this one
2104         ++nextMapItr;
2105       } else {
2106         //there is a gap between the top of this edge and the bottom of the next, process the top of this edge
2107         bottomAlreadyProcessed = false;
2108         //process the top of this edge
2109         typename std::map<Unit, ActiveTail<Unit>*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(HIGH));
2110         if(thisMapItr != tailMap_.end()) {
2111           //thisMapItr is pointing to a horizontal edge in the map at the top of this vertical edge
2112           //we need to join them and potentially close a figure
2113           //assert currentTail != 0
2114           ActiveTail<Unit>* tail = thisMapItr->second;
2115           //pass the opositve of trailing edge to mean that they are joined because of solid to the right
2116           currentTail = ActiveTail<Unit>::joinChains(currentTail, tail, !trailingEdge, outputPolygons_);
2117           nextMapItr = thisMapItr; //set nextMapItr to the next position after this one
2118           ++nextMapItr;
2119           if(currentTail) { //figure is not closed//
2120             Unit nextItrY = UnitMax;
2121             if(nextMapItr != tailMap_.end()) {
2122               nextItrY = nextMapItr->first;
2123             }
2124             //for it to be a hole this must have been a left edge
2125             Unit leftY = UnitMax;
2126             if(leftIndex + 1 < leftEdges.size())
2127               leftY = leftEdges[leftIndex+1].get(LOW);
2128             Unit rightY = nextEdge.get(LOW);
2129             if(!haveNextEdge || (nextItrY < leftY && nextItrY < rightY)) {
2130               //we need to add it to the next edge above it in the map
2131               tail = nextMapItr->second;
2132               tail = tail->addHole(currentTail, fractureHoles_);
2133               if(fractureHoles_) {
2134                 //some small additional work stitching in the filament
2135                 tail->pushCoordinate(nextItrY);
2136                 nextMapItr->second = tail;
2137               }
2138               //set current tail to null
2139               currentTail = 0;
2140             }
2141           }
2142           //delete thisMapItr from the map
2143           tailMap_.erase(thisMapItr);
2144         } else {
2145           //currentTail must turn right and be added into the map
2146           currentTail->pushCoordinate(edge.get(HIGH));
2147           //assert currentTail->getOrient() == HORIZONTAL
2148           tailMap_.insert(nextMapItr, std::pair<Unit, ActiveTail<Unit>*>(edge.get(HIGH), currentTail));
2149           //set currentTail to null
2150           currentTail = 0;
2151           //leave nextMapItr unchanged, it is still next
2152         }
2153       }
2154 
2155       //increment index
2156       leftIndex += !trailingEdge;
2157       rightIndex += trailingEdge;
2158     } //end while
2159     beginOutput = outputPolygons_.begin();
2160     endOutput = outputPolygons_.end();
2161   } //end function
2162 
2163   template<bool orientT, typename Unit, typename polygon_concept_type>
2164   inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::clearOutput_() {
2165     for(std::size_t i = 0; i < outputPolygons_.size(); ++i) {
2166       ActiveTail<Unit>* at1 = outputPolygons_[i].yield();
2167       const std::list<ActiveTail<Unit>*>& holes = at1->getHoles();
2168       for(typename std::list<ActiveTail<Unit>*>::const_iterator litr = holes.begin(); litr != holes.end(); ++litr) {
2169         //delete the hole
2170         (*litr)->destroyContents();
2171         destroyActiveTail((*litr)->getOtherActiveTail());
2172         destroyActiveTail((*litr));
2173       }
2174       //delete the polygon
2175       at1->destroyContents();
2176       //at2 contents are the same as at1, so it should not destroy them
2177       destroyActiveTail((at1)->getOtherActiveTail());
2178       destroyActiveTail(at1);
2179     }
2180     outputPolygons_.clear();
2181   }
2182 
2183 } //polygon_formation namespace
2184 
2185   template <bool orientT, typename Unit>
2186   struct geometry_concept<polygon_formation::PolyLinePolygonWithHolesData<orientT, Unit> > {
2187     typedef polygon_90_with_holes_concept type;
2188   };
2189 
2190   template <bool orientT, typename Unit>
2191   struct geometry_concept<polygon_formation::PolyLineHoleData<orientT, Unit> > {
2192     typedef polygon_90_concept type;
2193   };
2194 
2195   //public API to access polygon formation algorithm
2196   template <typename output_container, typename iterator_type, typename concept_type>
2197   unsigned int get_polygons(output_container& container,
2198       iterator_type begin, iterator_type end, orientation_2d orient,
2199       bool fracture_holes, concept_type,
2200       size_t sliceThreshold = (std::numeric_limits<size_t>::max)() ) {
2201     typedef typename output_container::value_type polygon_type;
2202     typedef typename std::iterator_traits<iterator_type>::value_type::first_type coordinate_type;
2203     polygon_type poly;
2204     unsigned int countPolygons = 0;
2205     typedef typename geometry_concept<polygon_type>::type polygon_concept_type;
2206     polygon_formation::ScanLineToPolygonItrs<true, coordinate_type, polygon_concept_type> scanlineToPolygonItrsV(fracture_holes);
2207     polygon_formation::ScanLineToPolygonItrs<false, coordinate_type, polygon_concept_type> scanlineToPolygonItrsH(fracture_holes);
2208     std::vector<interval_data<coordinate_type> > leftEdges;
2209     std::vector<interval_data<coordinate_type> > rightEdges;
2210     coordinate_type prevPos = (std::numeric_limits<coordinate_type>::max)();
2211     coordinate_type prevY = (std::numeric_limits<coordinate_type>::max)();
2212     int count = 0;
2213     for(iterator_type itr = begin;
2214         itr != end; ++ itr) {
2215       coordinate_type pos = (*itr).first;
2216       if(pos != prevPos) {
2217         if(orient == VERTICAL) {
2218           typename polygon_formation::ScanLineToPolygonItrs<true, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd;
2219            scanlineToPolygonItrsV.processEdges(itrPoly, itrPolyEnd, prevPos,
2220                leftEdges, rightEdges, sliceThreshold);
2221           for( ; itrPoly != itrPolyEnd; ++ itrPoly) {
2222             ++countPolygons;
2223             assign(poly, *itrPoly);
2224             container.insert(container.end(), poly);
2225           }
2226         } else {
2227           typename polygon_formation::ScanLineToPolygonItrs<false, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd;
2228           scanlineToPolygonItrsH.processEdges(itrPoly, itrPolyEnd, prevPos,
2229                leftEdges, rightEdges, sliceThreshold);
2230           for( ; itrPoly != itrPolyEnd; ++ itrPoly) {
2231             ++countPolygons;
2232             assign(poly, *itrPoly);
2233             container.insert(container.end(), poly);
2234           }
2235         }
2236         leftEdges.clear();
2237         rightEdges.clear();
2238         prevPos = pos;
2239         prevY = (*itr).second.first;
2240         count = (*itr).second.second;
2241         continue;
2242       }
2243       coordinate_type y = (*itr).second.first;
2244       if(count != 0 && y != prevY) {
2245         std::pair<interval_data<coordinate_type>, int> element(interval_data<coordinate_type>(prevY, y), count);
2246         if(element.second == 1) {
2247           if(leftEdges.size() && leftEdges.back().high() == element.first.low()) {
2248             encompass(leftEdges.back(), element.first);
2249           } else {
2250             leftEdges.push_back(element.first);
2251           }
2252         } else {
2253           if(rightEdges.size() && rightEdges.back().high() == element.first.low()) {
2254             encompass(rightEdges.back(), element.first);
2255           } else {
2256             rightEdges.push_back(element.first);
2257           }
2258         }
2259 
2260       }
2261       prevY = y;
2262       count += (*itr).second.second;
2263     }
2264     if(orient == VERTICAL) {
2265       typename polygon_formation::ScanLineToPolygonItrs<true, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd;
2266       scanlineToPolygonItrsV.processEdges(itrPoly, itrPolyEnd, prevPos, leftEdges, rightEdges, sliceThreshold);
2267       for( ; itrPoly != itrPolyEnd; ++ itrPoly) {
2268         ++countPolygons;
2269         assign(poly, *itrPoly);
2270         container.insert(container.end(), poly);
2271       }
2272     } else {
2273       typename polygon_formation::ScanLineToPolygonItrs<false, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd;
2274       scanlineToPolygonItrsH.processEdges(itrPoly, itrPolyEnd, prevPos, leftEdges, rightEdges,  sliceThreshold);
2275 
2276       for( ; itrPoly != itrPolyEnd; ++ itrPoly) {
2277         ++countPolygons;
2278         assign(poly, *itrPoly);
2279         container.insert(container.end(), poly);
2280       }
2281     }
2282     return countPolygons;
2283   }
2284 
2285 }
2286 }
2287 #endif