annotate DEPENDENCIES/generic/include/boost/polygon/detail/polygon_formation.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 /*
Chris@16 2 Copyright 2008 Intel Corporation
Chris@16 3
Chris@16 4 Use, modification and distribution are subject to the Boost Software License,
Chris@16 5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 http://www.boost.org/LICENSE_1_0.txt).
Chris@16 7 */
Chris@16 8 #include<iostream>
Chris@16 9 #include<cassert>
Chris@16 10 #ifndef BOOST_POLYGON_POLYGON_FORMATION_HPP
Chris@16 11 #define BOOST_POLYGON_POLYGON_FORMATION_HPP
Chris@16 12 namespace boost { namespace polygon{
Chris@16 13
Chris@16 14 namespace polygon_formation {
Chris@16 15
Chris@16 16 /*
Chris@16 17 * End has two states, HEAD and TAIL as is represented by a bool
Chris@16 18 */
Chris@16 19 typedef bool End;
Chris@16 20
Chris@16 21 /*
Chris@16 22 * HEAD End is represented as false because it is the lesser state
Chris@16 23 */
Chris@16 24 const End HEAD = false;
Chris@16 25
Chris@16 26 /*
Chris@16 27 * TAIL End is represented by true because TAIL comes after head and 1 after 0
Chris@16 28 */
Chris@16 29 const End TAIL = true;
Chris@16 30
Chris@16 31 /*
Chris@16 32 * 2D turning direction, left and right sides (is a boolean value since it has two states.)
Chris@16 33 */
Chris@16 34 typedef bool Side;
Chris@16 35
Chris@16 36 /*
Chris@16 37 * LEFT Side is 0 because we inuitively think left to right; left < right
Chris@16 38 */
Chris@16 39 const Side LEFT = false;
Chris@16 40
Chris@16 41 /*
Chris@16 42 * RIGHT Side is 1 so that right > left
Chris@16 43 */
Chris@16 44 const Side RIGHT = true;
Chris@16 45
Chris@16 46 /*
Chris@16 47 * The PolyLine class is data storage and services for building and representing partial polygons.
Chris@16 48 * As the polyline is added to it extends its storage to accomodate the data.
Chris@16 49 * PolyLines can be joined head-to-head/head-to-tail when it is determined that two polylines are
Chris@16 50 * part of the same polygon.
Chris@16 51 * PolyLines keep state information about what orientation their incomplete head and tail geometry have,
Chris@16 52 * which side of the polyline is solid and whether the polyline is joined head-to-head and tail-to-head.
Chris@16 53 * PolyLines have nothing whatsoever to do with holes.
Chris@16 54 * It may be valuable to collect a histogram of PolyLine lengths used by an algorithm on its typical data
Chris@16 55 * sets and tune the allocation of the initial vector of coordinate data to be greater than or equal to
Chris@16 56 * the mean, median, mode, or mean plus some number of standard deviation, or just generally large enough
Chris@16 57 * to prevent too much unnecesary reallocations, but not too big that it wastes a lot of memory and degrades cache
Chris@16 58 * performance.
Chris@16 59 */
Chris@16 60 template <typename Unit>
Chris@16 61 class PolyLine {
Chris@16 62 private:
Chris@16 63 //data
Chris@16 64
Chris@16 65 /*
Chris@16 66 * ptdata_ a vector of coordiantes
Chris@16 67 * if VERTICAL_HEAD, first coordiante is an X
Chris@16 68 * else first coordinate is a Y
Chris@16 69 */
Chris@16 70 std::vector<Unit> ptdata_;
Chris@16 71
Chris@16 72 /*
Chris@16 73 * head and tail points to other polylines before and after this in a chain
Chris@16 74 */
Chris@16 75 PolyLine* headp_;
Chris@16 76 PolyLine* tailp_;
Chris@16 77
Chris@16 78 /*
Chris@16 79 * state bitmask
Chris@16 80 * bit zero is orientation, 0 H, 1 V
Chris@16 81 * bit 1 is head connectivity, 0 for head, 1 for tail
Chris@16 82 * bit 2 is tail connectivity, 0 for head, 1 for tail
Chris@16 83 * bit 3 is solid to left of PolyLine when 1, right when 0
Chris@16 84 */
Chris@16 85 int state_;
Chris@16 86
Chris@16 87 public:
Chris@16 88 /*
Chris@16 89 * default constructor (for preallocation)
Chris@16 90 */
Chris@16 91 PolyLine();
Chris@16 92
Chris@16 93 /*
Chris@16 94 * constructor that takes the orientation, coordiante and side to which there is solid
Chris@16 95 */
Chris@16 96 PolyLine(orientation_2d orient, Unit coord, Side side);
Chris@16 97
Chris@16 98 //copy constructor
Chris@16 99 PolyLine(const PolyLine& pline);
Chris@16 100
Chris@16 101 //destructor
Chris@16 102 ~PolyLine();
Chris@16 103
Chris@16 104 //assignment operator
Chris@16 105 PolyLine& operator=(const PolyLine& that);
Chris@16 106
Chris@16 107 //equivalence operator
Chris@16 108 bool operator==(const PolyLine& b) const;
Chris@16 109
Chris@16 110 /*
Chris@16 111 * valid PolyLine (only default constructed polylines are invalid.)
Chris@16 112 */
Chris@16 113 bool isValid() const;
Chris@16 114
Chris@16 115 /*
Chris@16 116 * Orientation of Head
Chris@16 117 */
Chris@16 118 orientation_2d headOrient() const;
Chris@16 119
Chris@16 120 /*
Chris@16 121 * returns true if first coordinate is an X value (first segment is vertical)
Chris@16 122 */
Chris@16 123 bool verticalHead() const;
Chris@16 124
Chris@16 125 /*
Chris@16 126 * returns the orientation_2d fo the tail
Chris@16 127 */
Chris@16 128 orientation_2d tailOrient() const;
Chris@16 129
Chris@16 130 /*
Chris@16 131 * returns true if last coordinate is an X value (last segment is vertical)
Chris@16 132 */
Chris@16 133 bool verticalTail() const;
Chris@16 134
Chris@16 135 /*
Chris@16 136 * retrun true if PolyLine has odd number of coordiantes
Chris@16 137 */
Chris@16 138 bool oddLength() const;
Chris@16 139
Chris@16 140 /*
Chris@16 141 * retrun the End of the other polyline that the specified end of this polyline is connected to
Chris@16 142 */
Chris@16 143 End endConnectivity(End end) const;
Chris@16 144
Chris@16 145 /*
Chris@16 146 * retrun true if the head of this polyline is connect to the tail of a polyline
Chris@16 147 */
Chris@16 148 bool headToTail() const;
Chris@16 149 /*
Chris@16 150 * retrun true if the head of this polyline is connect to the head of a polyline
Chris@16 151 */
Chris@16 152 bool headToHead() const;
Chris@16 153
Chris@16 154 /*
Chris@16 155 * retrun true if the tail of this polyline is connect to the tail of a polyline
Chris@16 156 */
Chris@16 157 bool tailToTail() const;
Chris@16 158 /*
Chris@16 159 * retrun true if the tail of this polyline is connect to the head of a polyline
Chris@16 160 */
Chris@16 161 bool tailToHead() const;
Chris@16 162
Chris@16 163 /*
Chris@16 164 * retrun the side on which there is solid for this polyline
Chris@16 165 */
Chris@16 166 Side solidSide() const;
Chris@16 167
Chris@16 168 /*
Chris@16 169 * retrun true if there is solid to the right of this polyline
Chris@16 170 */
Chris@16 171 bool solidToRight() const;
Chris@16 172
Chris@16 173 /*
Chris@16 174 * returns true if the polyline tail is not connected
Chris@16 175 */
Chris@16 176 bool active() const;
Chris@16 177
Chris@16 178 /*
Chris@16 179 * adds a coordinate value to the end of the polyline changing the tail orientation
Chris@16 180 */
Chris@16 181 PolyLine& pushCoordinate(Unit coord);
Chris@16 182
Chris@16 183 /*
Chris@16 184 * removes a coordinate value at the end of the polyline changing the tail orientation
Chris@16 185 */
Chris@16 186 PolyLine& popCoordinate();
Chris@16 187
Chris@16 188 /*
Chris@16 189 * extends the tail of the polyline to include the point, changing orientation if needed
Chris@16 190 */
Chris@16 191 PolyLine& pushPoint(const point_data<Unit>& point);
Chris@16 192
Chris@16 193 /*
Chris@16 194 * changes the last coordinate of the tail of the polyline by the amount of the delta
Chris@16 195 */
Chris@16 196 PolyLine& extendTail(Unit delta);
Chris@16 197
Chris@16 198 /*
Chris@16 199 * join thisEnd of this polyline to that polyline's end
Chris@16 200 */
Chris@16 201 PolyLine& joinTo(End thisEnd, PolyLine& that, End end);
Chris@16 202
Chris@16 203 /*
Chris@16 204 * join an end of this polyline to the tail of that polyline
Chris@16 205 */
Chris@16 206 PolyLine& joinToTail(PolyLine& that, End end);
Chris@16 207
Chris@16 208 /*
Chris@16 209 * join an end of this polyline to the head of that polyline
Chris@16 210 */
Chris@16 211 PolyLine& joinToHead(PolyLine& that, End end);
Chris@16 212
Chris@16 213 /*
Chris@16 214 * join the head of this polyline to the head of that polyline
Chris@16 215 */
Chris@16 216 //join this to that in the given way
Chris@16 217 PolyLine& joinHeadToHead(PolyLine& that);
Chris@16 218
Chris@16 219 /*
Chris@16 220 * join the head of this polyline to the tail of that polyline
Chris@16 221 */
Chris@16 222 PolyLine& joinHeadToTail(PolyLine& that);
Chris@16 223
Chris@16 224 /*
Chris@16 225 * join the tail of this polyline to the head of that polyline
Chris@16 226 */
Chris@16 227 PolyLine& joinTailToHead(PolyLine& that);
Chris@16 228
Chris@16 229 /*
Chris@16 230 * join the tail of this polyline to the tail of that polyline
Chris@16 231 */
Chris@16 232 PolyLine& joinTailToTail(PolyLine& that);
Chris@16 233
Chris@16 234 /*
Chris@16 235 * dissconnect the tail at the end of the polygon
Chris@16 236 */
Chris@16 237 PolyLine& disconnectTails();
Chris@16 238
Chris@16 239 /*
Chris@16 240 * get the coordinate at one end of this polyline, by default the tail end
Chris@16 241 */
Chris@16 242 Unit getEndCoord(End end = TAIL) const;
Chris@16 243
Chris@16 244 /*
Chris@16 245 * get the point on the polyline at the given index (polylines have the same number of coordinates as points
Chris@16 246 */
Chris@16 247 point_data<Unit> getPoint(unsigned int index) const;
Chris@16 248
Chris@16 249 /*
Chris@16 250 * get the point on one end of the polyline, by default the tail
Chris@16 251 */
Chris@16 252 point_data<Unit> getEndPoint(End end = TAIL) const;
Chris@16 253
Chris@16 254 /*
Chris@16 255 * get the orientation of a segment by index
Chris@16 256 */
Chris@16 257 orientation_2d segmentOrient(unsigned int index = 0) const;
Chris@16 258
Chris@16 259 /*
Chris@16 260 * get a coordinate by index using the square bracket operator
Chris@16 261 */
Chris@16 262 Unit operator[] (unsigned int index) const;
Chris@16 263
Chris@16 264 /*
Chris@16 265 * get the number of segments/points/coordinates in the polyline
Chris@16 266 */
Chris@16 267 unsigned int numSegments() const;
Chris@16 268
Chris@16 269 /*
Chris@16 270 * get the pointer to the next polyline at one end of this
Chris@16 271 */
Chris@16 272 PolyLine* next(End end) const;
Chris@16 273
Chris@16 274 /*
Chris@16 275 * write out coordinates of this and all attached polylines to a single vector
Chris@16 276 */
Chris@16 277 PolyLine* writeOut(std::vector<Unit>& outVec, End startEnd = TAIL) const;
Chris@16 278
Chris@16 279 private:
Chris@16 280 //methods
Chris@16 281 PolyLine& joinTo_(End thisEnd, PolyLine& that, End end);
Chris@16 282 };
Chris@16 283
Chris@16 284 //forward declaration
Chris@16 285 template<bool orientT, typename Unit>
Chris@16 286 class PolyLinePolygonData;
Chris@16 287
Chris@16 288 //forward declaration
Chris@16 289 template<bool orientT, typename Unit>
Chris@16 290 class PolyLinePolygonWithHolesData;
Chris@16 291
Chris@16 292 /*
Chris@16 293 * ActiveTail represents an edge of an incomplete polygon.
Chris@16 294 *
Chris@16 295 * An ActiveTail object is the active tail end of a polyline object, which may (should) be the attached to
Chris@16 296 * a chain of polyline objects through a pointer. The ActiveTail class provides an abstraction between
Chris@16 297 * and algorithm that builds polygons and the PolyLine data representation of incomplete polygons that are
Chris@16 298 * being built. It does this by providing an iterface to access the information about the last edge at the
Chris@16 299 * tail of the PolyLine it is associated with. To a polygon constructing algorithm, an ActiveTail is a floating
Chris@16 300 * edge of an incomplete polygon and has an orientation and coordinate value, as well as knowing which side of
Chris@16 301 * that edge is supposed to be solid or space. Any incomplete polygon will have two active tails. Active tails
Chris@16 302 * may be joined together to merge two incomplete polygons into a larger incomplete polygon. If two active tails
Chris@16 303 * that are to be merged are the oppositve ends of the same incomplete polygon that indicates that the polygon
Chris@16 304 * has been closed and is complete. The active tail keeps a pointer to the other active tail of its incomplete
Chris@16 305 * polygon so that it is easy to check this condition. These pointers are updated when active tails are joined.
Chris@16 306 * The active tail also keeps a list of pointers to active tail objects that serve as handles to closed holes. In
Chris@16 307 * this way a hole can be associated to another incomplete polygon, which will eventually be its enclosing shell,
Chris@16 308 * or reassociate the hole to another incomplete polygon in the case that it become a hole itself. Alternately,
Chris@16 309 * the active tail may add a filiment to stitch a hole into a shell and "fracture" the hole out of the interior
Chris@16 310 * of a polygon. The active tail maintains a static output buffer to temporarily write polygon data to when
Chris@16 311 * it outputs a figure so that outputting a polygon does not require the allocation of a temporary buffer. This
Chris@16 312 * static buffer should be destroyed whenever the program determines that it won't need it anymore and would prefer to
Chris@16 313 * release the memory it has allocated back to the system.
Chris@16 314 */
Chris@16 315 template <typename Unit>
Chris@16 316 class ActiveTail {
Chris@16 317 private:
Chris@16 318 //data
Chris@16 319 PolyLine<Unit>* tailp_;
Chris@16 320 ActiveTail *otherTailp_;
Chris@16 321 std::list<ActiveTail*> holesList_;
Chris@16 322 //Sum of all the polylines which constitute the active tail (including holes)//
Chris@16 323 size_t polyLineSize_;
Chris@16 324 public:
Chris@16 325
Chris@16 326 inline size_t getPolyLineSize(){
Chris@16 327 return polyLineSize_;
Chris@16 328 }
Chris@16 329
Chris@16 330 inline void setPolyLineSize(int delta){
Chris@16 331 polyLineSize_ = delta;
Chris@16 332 }
Chris@16 333
Chris@16 334 inline void addPolyLineSize(int delta){
Chris@16 335 polyLineSize_ += delta;
Chris@16 336 }
Chris@16 337
Chris@16 338 /*
Chris@16 339 * iterator over coordinates of the figure
Chris@16 340 */
Chris@16 341 class iterator {
Chris@16 342 private:
Chris@16 343 const PolyLine<Unit>* pLine_;
Chris@16 344 const PolyLine<Unit>* pLineEnd_;
Chris@16 345 unsigned int index_;
Chris@16 346 unsigned int indexEnd_;
Chris@16 347 End startEnd_;
Chris@16 348 public:
Chris@16 349 inline iterator() : pLine_(), pLineEnd_(), index_(), indexEnd_(), startEnd_() {}
Chris@16 350 inline iterator(const ActiveTail* at, bool isHole, orientation_2d orient) :
Chris@16 351 pLine_(), pLineEnd_(), index_(), indexEnd_(), startEnd_() {
Chris@16 352 //if it is a hole and orientation is vertical or it is not a hole and orientation is horizontal
Chris@16 353 //we want to use this active tail, otherwise we want to use the other active tail
Chris@16 354 startEnd_ = TAIL;
Chris@16 355 if(!isHole ^ (orient == HORIZONTAL)) {
Chris@16 356 //switch winding direction
Chris@16 357 at = at->getOtherActiveTail();
Chris@16 358 }
Chris@16 359 //now we have the right winding direction
Chris@16 360 //if it is horizontal we need to skip the first element
Chris@16 361 pLine_ = at->getTail();
Chris@16 362
Chris@16 363 if(at->getTail()->numSegments() > 0)
Chris@16 364 index_ = at->getTail()->numSegments() - 1;
Chris@16 365
Chris@16 366 if((at->getOrient() == HORIZONTAL) ^ (orient == HORIZONTAL)) {
Chris@16 367 pLineEnd_ = at->getTail();
Chris@16 368 indexEnd_ = pLineEnd_->numSegments() - 1;
Chris@16 369 if(index_ == 0) {
Chris@16 370 pLine_ = at->getTail()->next(HEAD);
Chris@16 371 if(at->getTail()->endConnectivity(HEAD) == TAIL) {
Chris@16 372 index_ = pLine_->numSegments() -1;
Chris@16 373 } else {
Chris@16 374 startEnd_ = HEAD;
Chris@16 375 index_ = 0;
Chris@16 376 }
Chris@16 377 } else { --index_; }
Chris@16 378 } else {
Chris@16 379 pLineEnd_ = at->getOtherActiveTail()->getTail();
Chris@16 380 if(pLineEnd_->numSegments() > 0)
Chris@16 381 indexEnd_ = pLineEnd_->numSegments() - 1;
Chris@16 382 }
Chris@16 383 at->getTail()->joinTailToTail(*(at->getOtherActiveTail()->getTail()));
Chris@16 384 }
Chris@16 385
Chris@16 386 inline size_t size(void){
Chris@16 387 size_t count = 0;
Chris@16 388 End dir = startEnd_;
Chris@16 389 PolyLine<Unit> const * currLine = pLine_;
Chris@16 390 size_t ops = 0;
Chris@16 391 while(currLine != pLineEnd_){
Chris@16 392 ops++;
Chris@16 393 count += currLine->numSegments();
Chris@16 394 currLine = currLine->next(dir == HEAD ? TAIL : HEAD);
Chris@16 395 dir = currLine->endConnectivity(dir == HEAD ? TAIL : HEAD);
Chris@16 396 }
Chris@16 397 count += pLineEnd_->numSegments();
Chris@16 398 return count; //no. of vertices
Chris@16 399 }
Chris@16 400
Chris@16 401 //use bitwise copy and assign provided by the compiler
Chris@16 402 inline iterator& operator++() {
Chris@16 403 if(pLine_ == pLineEnd_ && index_ == indexEnd_) {
Chris@16 404 pLine_ = 0;
Chris@16 405 index_ = 0;
Chris@16 406 return *this;
Chris@16 407 }
Chris@16 408 if(startEnd_ == HEAD) {
Chris@16 409 ++index_;
Chris@16 410 if(index_ == pLine_->numSegments()) {
Chris@16 411 End end = pLine_->endConnectivity(TAIL);
Chris@16 412 pLine_ = pLine_->next(TAIL);
Chris@16 413 if(end == TAIL) {
Chris@16 414 startEnd_ = TAIL;
Chris@16 415 index_ = pLine_->numSegments() -1;
Chris@16 416 } else {
Chris@16 417 index_ = 0;
Chris@16 418 }
Chris@16 419 }
Chris@16 420 } else {
Chris@16 421 if(index_ == 0) {
Chris@16 422 End end = pLine_->endConnectivity(HEAD);
Chris@16 423 pLine_ = pLine_->next(HEAD);
Chris@16 424 if(end == TAIL) {
Chris@16 425 index_ = pLine_->numSegments() -1;
Chris@16 426 } else {
Chris@16 427 startEnd_ = HEAD;
Chris@16 428 index_ = 0;
Chris@16 429 }
Chris@16 430 } else {
Chris@16 431 --index_;
Chris@16 432 }
Chris@16 433 }
Chris@16 434 return *this;
Chris@16 435 }
Chris@16 436 inline const iterator operator++(int) {
Chris@16 437 iterator tmp(*this);
Chris@16 438 ++(*this);
Chris@16 439 return tmp;
Chris@16 440 }
Chris@16 441 inline bool operator==(const iterator& that) const {
Chris@16 442 return pLine_ == that.pLine_ && index_ == that.index_;
Chris@16 443 }
Chris@16 444 inline bool operator!=(const iterator& that) const {
Chris@16 445 return pLine_ != that.pLine_ || index_ != that.index_;
Chris@16 446 }
Chris@16 447 inline Unit operator*() { return (*pLine_)[index_]; }
Chris@16 448 };
Chris@16 449
Chris@16 450 /*
Chris@16 451 * iterator over holes contained within the figure
Chris@16 452 */
Chris@16 453 typedef typename std::list<ActiveTail*>::const_iterator iteratorHoles;
Chris@16 454
Chris@16 455 //default constructor
Chris@16 456 ActiveTail();
Chris@16 457
Chris@16 458 //constructor
Chris@16 459 ActiveTail(orientation_2d orient, Unit coord, Side solidToRight, ActiveTail* otherTailp);
Chris@16 460
Chris@16 461 //constructor
Chris@16 462 ActiveTail(PolyLine<Unit>* active, ActiveTail* otherTailp);
Chris@16 463
Chris@16 464 //copy constructor
Chris@16 465 ActiveTail(const ActiveTail& that);
Chris@16 466
Chris@16 467 //destructor
Chris@16 468 ~ActiveTail();
Chris@16 469
Chris@16 470 //assignment operator
Chris@16 471 ActiveTail& operator=(const ActiveTail& that);
Chris@16 472
Chris@16 473 //equivalence operator
Chris@16 474 bool operator==(const ActiveTail& b) const;
Chris@16 475
Chris@16 476 /*
Chris@16 477 * comparison operators, ActiveTail objects are sortable by geometry
Chris@16 478 */
Chris@16 479 bool operator<(const ActiveTail& b) const;
Chris@16 480 bool operator<=(const ActiveTail& b) const;
Chris@16 481 bool operator>(const ActiveTail& b) const;
Chris@16 482 bool operator>=(const ActiveTail& b) const;
Chris@16 483
Chris@16 484 /*
Chris@16 485 * get the pointer to the polyline that this is an active tail of
Chris@16 486 */
Chris@16 487 PolyLine<Unit>* getTail() const;
Chris@16 488
Chris@16 489 /*
Chris@16 490 * get the pointer to the polyline at the other end of the chain
Chris@16 491 */
Chris@16 492 PolyLine<Unit>* getOtherTail() const;
Chris@16 493
Chris@16 494 /*
Chris@16 495 * get the pointer to the activetail at the other end of the chain
Chris@16 496 */
Chris@16 497 ActiveTail* getOtherActiveTail() const;
Chris@16 498
Chris@16 499 /*
Chris@16 500 * test if another active tail is the other end of the chain
Chris@16 501 */
Chris@16 502 bool isOtherTail(const ActiveTail& b);
Chris@16 503
Chris@16 504 /*
Chris@16 505 * update this end of chain pointer to new polyline
Chris@16 506 */
Chris@16 507 ActiveTail& updateTail(PolyLine<Unit>* newTail);
Chris@16 508
Chris@16 509 /*
Chris@16 510 * associate a hole to this active tail by the specified policy
Chris@16 511 */
Chris@16 512 ActiveTail* addHole(ActiveTail* hole, bool fractureHoles);
Chris@16 513
Chris@16 514 /*
Chris@16 515 * get the list of holes
Chris@16 516 */
Chris@16 517 const std::list<ActiveTail*>& getHoles() const;
Chris@16 518
Chris@16 519 /*
Chris@16 520 * copy holes from that to this
Chris@16 521 */
Chris@16 522 void copyHoles(ActiveTail& that);
Chris@16 523
Chris@16 524 /*
Chris@16 525 * find out if solid to right
Chris@16 526 */
Chris@16 527 bool solidToRight() const;
Chris@16 528
Chris@16 529 /*
Chris@16 530 * get coordinate (getCoord and getCoordinate are aliases for eachother)
Chris@16 531 */
Chris@16 532 Unit getCoord() const;
Chris@16 533 Unit getCoordinate() const;
Chris@16 534
Chris@16 535 /*
Chris@16 536 * get the tail orientation
Chris@16 537 */
Chris@16 538 orientation_2d getOrient() const;
Chris@16 539
Chris@16 540 /*
Chris@16 541 * add a coordinate to the polygon at this active tail end, properly handle degenerate edges by removing redundant coordinate
Chris@16 542 */
Chris@16 543 void pushCoordinate(Unit coord);
Chris@16 544
Chris@16 545 /*
Chris@16 546 * write the figure that this active tail points to out to the temp buffer
Chris@16 547 */
Chris@16 548 void writeOutFigure(std::vector<Unit>& outVec, bool isHole = false) const;
Chris@16 549
Chris@16 550 /*
Chris@16 551 * write the figure that this active tail points to out through iterators
Chris@16 552 */
Chris@16 553 void writeOutFigureItrs(iterator& beginOut, iterator& endOut, bool isHole = false, orientation_2d orient = VERTICAL) const;
Chris@16 554 iterator begin(bool isHole, orientation_2d orient) const;
Chris@16 555 iterator end() const;
Chris@16 556
Chris@16 557 /*
Chris@16 558 * write the holes that this active tail points to out through iterators
Chris@16 559 */
Chris@16 560 void writeOutFigureHoleItrs(iteratorHoles& beginOut, iteratorHoles& endOut) const;
Chris@16 561 iteratorHoles beginHoles() const;
Chris@16 562 iteratorHoles endHoles() const;
Chris@16 563
Chris@16 564 /*
Chris@16 565 * joins the two chains that the two active tail tails are ends of
Chris@16 566 * checks for closure of figure and writes out polygons appropriately
Chris@16 567 * returns a handle to a hole if one is closed
Chris@16 568 */
Chris@16 569 static ActiveTail* joinChains(ActiveTail* at1, ActiveTail* at2, bool solid, std::vector<Unit>& outBufferTmp);
Chris@16 570 template <typename PolygonT>
Chris@16 571 static ActiveTail* joinChains(ActiveTail* at1, ActiveTail* at2, bool solid, typename std::vector<PolygonT>& outBufferTmp);
Chris@16 572
Chris@16 573 /*
Chris@16 574 * deallocate temp buffer
Chris@16 575 */
Chris@16 576 static void destroyOutBuffer();
Chris@16 577
Chris@16 578 /*
Chris@16 579 * deallocate all polygon data this active tail points to (deep delete, call only from one of a pair of active tails)
Chris@16 580 */
Chris@16 581 void destroyContents();
Chris@16 582 };
Chris@16 583
Chris@16 584 /* allocate a polyline object */
Chris@16 585 template <typename Unit>
Chris@16 586 PolyLine<Unit>* createPolyLine(orientation_2d orient, Unit coord, Side side);
Chris@16 587
Chris@16 588 /* deallocate a polyline object */
Chris@16 589 template <typename Unit>
Chris@16 590 void destroyPolyLine(PolyLine<Unit>* pLine);
Chris@16 591
Chris@16 592 /* allocate an activetail object */
Chris@16 593 template <typename Unit>
Chris@16 594 ActiveTail<Unit>* createActiveTail();
Chris@16 595
Chris@16 596 /* deallocate an activetail object */
Chris@16 597 template <typename Unit>
Chris@16 598 void destroyActiveTail(ActiveTail<Unit>* aTail);
Chris@16 599
Chris@16 600 template<bool orientT, typename Unit>
Chris@16 601 class PolyLineHoleData {
Chris@16 602 private:
Chris@16 603 ActiveTail<Unit>* p_;
Chris@16 604 public:
Chris@16 605 typedef Unit coordinate_type;
Chris@16 606 typedef typename ActiveTail<Unit>::iterator compact_iterator_type;
Chris@16 607 typedef iterator_compact_to_points<compact_iterator_type, point_data<coordinate_type> > iterator_type;
Chris@16 608 inline PolyLineHoleData() : p_(0) {}
Chris@16 609 inline PolyLineHoleData(ActiveTail<Unit>* p) : p_(p) {}
Chris@16 610 //use default copy and assign
Chris@16 611 inline compact_iterator_type begin_compact() const { return p_->begin(true, (orientT ? VERTICAL : HORIZONTAL)); }
Chris@16 612 inline compact_iterator_type end_compact() const { return p_->end(); }
Chris@16 613 inline iterator_type begin() const { return iterator_type(begin_compact(), end_compact()); }
Chris@16 614 inline iterator_type end() const { return iterator_type(end_compact(), end_compact()); }
Chris@16 615 inline std::size_t size() const {
Chris@16 616 return p_->getPolyLineSize();
Chris@16 617 }
Chris@16 618 inline ActiveTail<Unit>* yield() { return p_; }
Chris@16 619 template<class iT>
Chris@16 620 inline PolyLineHoleData& set(iT inputBegin, iT inputEnd) {
Chris@16 621 return *this;
Chris@16 622 }
Chris@16 623 template<class iT>
Chris@16 624 inline PolyLineHoleData& set_compact(iT inputBegin, iT inputEnd) {
Chris@16 625 return *this;
Chris@16 626 }
Chris@16 627
Chris@16 628 };
Chris@16 629
Chris@16 630 template<bool orientT, typename Unit>
Chris@16 631 class PolyLinePolygonWithHolesData {
Chris@16 632 private:
Chris@16 633 ActiveTail<Unit>* p_;
Chris@16 634 public:
Chris@16 635 typedef Unit coordinate_type;
Chris@16 636 typedef typename ActiveTail<Unit>::iterator compact_iterator_type;
Chris@16 637 typedef iterator_compact_to_points<compact_iterator_type, point_data<coordinate_type> > iterator_type;
Chris@16 638 typedef PolyLineHoleData<orientT, Unit> hole_type;
Chris@16 639 typedef typename coordinate_traits<Unit>::area_type area_type;
Chris@16 640 class iteratorHoles {
Chris@16 641 private:
Chris@16 642 typename ActiveTail<Unit>::iteratorHoles itr_;
Chris@16 643 public:
Chris@16 644 inline iteratorHoles() : itr_() {}
Chris@16 645 inline iteratorHoles(typename ActiveTail<Unit>::iteratorHoles itr) : itr_(itr) {}
Chris@16 646 //use bitwise copy and assign provided by the compiler
Chris@16 647 inline iteratorHoles& operator++() {
Chris@16 648 ++itr_;
Chris@16 649 return *this;
Chris@16 650 }
Chris@16 651 inline const iteratorHoles operator++(int) {
Chris@16 652 iteratorHoles tmp(*this);
Chris@16 653 ++(*this);
Chris@16 654 return tmp;
Chris@16 655 }
Chris@16 656 inline bool operator==(const iteratorHoles& that) const {
Chris@16 657 return itr_ == that.itr_;
Chris@16 658 }
Chris@16 659 inline bool operator!=(const iteratorHoles& that) const {
Chris@16 660 return itr_ != that.itr_;
Chris@16 661 }
Chris@16 662 inline PolyLineHoleData<orientT, Unit> operator*() { return PolyLineHoleData<orientT, Unit>(*itr_);}
Chris@16 663 };
Chris@16 664 typedef iteratorHoles iterator_holes_type;
Chris@16 665
Chris@16 666 inline PolyLinePolygonWithHolesData() : p_(0) {}
Chris@16 667 inline PolyLinePolygonWithHolesData(ActiveTail<Unit>* p) : p_(p) {}
Chris@16 668 //use default copy and assign
Chris@16 669 inline compact_iterator_type begin_compact() const { return p_->begin(false, (orientT ? VERTICAL : HORIZONTAL)); }
Chris@16 670 inline compact_iterator_type end_compact() const { return p_->end(); }
Chris@16 671 inline iterator_type begin() const { return iterator_type(begin_compact(), end_compact()); }
Chris@16 672 inline iterator_type end() const { return iterator_type(end_compact(), end_compact()); }
Chris@16 673 inline iteratorHoles begin_holes() const { return iteratorHoles(p_->beginHoles()); }
Chris@16 674 inline iteratorHoles end_holes() const { return iteratorHoles(p_->endHoles()); }
Chris@16 675 inline ActiveTail<Unit>* yield() { return p_; }
Chris@16 676 //stub out these four required functions that will not be used but are needed for the interface
Chris@16 677 inline std::size_t size_holes() const { return 0; }
Chris@16 678 inline std::size_t size() const { return 0; }
Chris@16 679 template<class iT>
Chris@16 680 inline PolyLinePolygonWithHolesData& set(iT inputBegin, iT inputEnd) {
Chris@16 681 return *this;
Chris@16 682 }
Chris@16 683 template<class iT>
Chris@16 684 inline PolyLinePolygonWithHolesData& set_compact(iT inputBegin, iT inputEnd) {
Chris@16 685 return *this;
Chris@16 686 }
Chris@16 687
Chris@16 688 // initialize a polygon from x,y values, it is assumed that the first is an x
Chris@16 689 // and that the input is a well behaved polygon
Chris@16 690 template<class iT>
Chris@16 691 inline PolyLinePolygonWithHolesData& set_holes(iT inputBegin, iT inputEnd) {
Chris@16 692 return *this;
Chris@16 693 }
Chris@16 694 };
Chris@16 695
Chris@16 696
Chris@16 697 template <bool orientT, typename Unit, typename polygon_concept_type>
Chris@16 698 struct PolyLineType { };
Chris@16 699 template <bool orientT, typename Unit>
Chris@16 700 struct PolyLineType<orientT, Unit, polygon_90_with_holes_concept> { typedef PolyLinePolygonWithHolesData<orientT, Unit> type; };
Chris@16 701 template <bool orientT, typename Unit>
Chris@16 702 struct PolyLineType<orientT, Unit, polygon_45_with_holes_concept> { typedef PolyLinePolygonWithHolesData<orientT, Unit> type; };
Chris@16 703 template <bool orientT, typename Unit>
Chris@16 704 struct PolyLineType<orientT, Unit, polygon_with_holes_concept> { typedef PolyLinePolygonWithHolesData<orientT, Unit> type; };
Chris@16 705 template <bool orientT, typename Unit>
Chris@16 706 struct PolyLineType<orientT, Unit, polygon_90_concept> { typedef PolyLineHoleData<orientT, Unit> type; };
Chris@16 707 template <bool orientT, typename Unit>
Chris@16 708 struct PolyLineType<orientT, Unit, polygon_45_concept> { typedef PolyLineHoleData<orientT, Unit> type; };
Chris@16 709 template <bool orientT, typename Unit>
Chris@16 710 struct PolyLineType<orientT, Unit, polygon_concept> { typedef PolyLineHoleData<orientT, Unit> type; };
Chris@16 711
Chris@16 712 template <bool orientT, typename Unit, typename polygon_concept_type>
Chris@16 713 class ScanLineToPolygonItrs {
Chris@16 714 private:
Chris@16 715 std::map<Unit, ActiveTail<Unit>*> tailMap_;
Chris@16 716 typedef typename PolyLineType<orientT, Unit, polygon_concept_type>::type PolyLinePolygonData;
Chris@16 717 std::vector<PolyLinePolygonData> outputPolygons_;
Chris@16 718 bool fractureHoles_;
Chris@16 719 public:
Chris@16 720 typedef typename std::vector<PolyLinePolygonData>::iterator iterator;
Chris@16 721 inline ScanLineToPolygonItrs() : tailMap_(), outputPolygons_(), fractureHoles_(false) {}
Chris@16 722 /* construct a scanline with the proper offsets, protocol and options */
Chris@16 723 inline ScanLineToPolygonItrs(bool fractureHoles) : tailMap_(), outputPolygons_(), fractureHoles_(fractureHoles) {}
Chris@16 724
Chris@16 725 ~ScanLineToPolygonItrs() { clearOutput_(); }
Chris@16 726
Chris@16 727 /* process all vertical edges, left and right, at a unique x coordinate, edges must be sorted low to high */
Chris@16 728 void processEdges(iterator& beginOutput, iterator& endOutput,
Chris@16 729 Unit currentX, std::vector<interval_data<Unit> >& leftEdges,
Chris@16 730 std::vector<interval_data<Unit> >& rightEdges,
Chris@16 731 size_t vertexThreshold=(std::numeric_limits<size_t>::max)() );
Chris@16 732
Chris@16 733 /**********************************************************************
Chris@16 734 *methods implementing new polygon formation code
Chris@16 735 *
Chris@16 736 **********************************************************************/
Chris@16 737 void updatePartialSimplePolygonsWithRightEdges(Unit currentX,
Chris@16 738 const std::vector<interval_data<Unit> >& leftEdges, size_t threshold);
Chris@16 739
Chris@16 740 void updatePartialSimplePolygonsWithLeftEdges(Unit currentX,
Chris@16 741 const std::vector<interval_data<Unit> >& leftEdges, size_t threshold);
Chris@16 742
Chris@16 743 void closePartialSimplePolygon(Unit, ActiveTail<Unit>*, ActiveTail<Unit>*);
Chris@16 744
Chris@16 745 void maintainPartialSimplePolygonInvariant(iterator& ,iterator& ,Unit,
Chris@16 746 const std::vector<interval_data<Unit> >&,
Chris@16 747 const std::vector<interval_data<Unit> >&,
Chris@16 748 size_t vertexThreshold=(std::numeric_limits<size_t>::max)());
Chris@16 749
Chris@16 750 void insertNewLeftEdgeIntoTailMap(Unit, Unit, Unit,
Chris@16 751 typename std::map<Unit, ActiveTail<Unit>*>::iterator &);
Chris@16 752 /**********************************************************************/
Chris@16 753
Chris@16 754 inline size_t getTailMapSize(){
Chris@16 755 typename std::map<Unit, ActiveTail<Unit>* >::const_iterator itr;
Chris@16 756 size_t tsize = 0;
Chris@16 757 for(itr=tailMap_.begin(); itr!=tailMap_.end(); ++itr){
Chris@16 758 tsize += (itr->second)->getPolyLineSize();
Chris@16 759 }
Chris@16 760 return tsize;
Chris@16 761 }
Chris@16 762 /*print the active tails in this map:*/
Chris@16 763 inline void print(){
Chris@16 764 typename std::map<Unit, ActiveTail<Unit>* >::const_iterator itr;
Chris@16 765 printf("=========TailMap[%lu]=========\n", tailMap_.size());
Chris@16 766 for(itr=tailMap_.begin(); itr!=tailMap_.end(); ++itr){
Chris@16 767 std::cout<< "[" << itr->first << "] : " << std::endl;
Chris@16 768 //print active tail//
Chris@16 769 ActiveTail<Unit> const *t = (itr->second);
Chris@16 770 PolyLine<Unit> const *pBegin = t->getTail();
Chris@16 771 PolyLine<Unit> const *pEnd = t->getOtherActiveTail()->getTail();
Chris@16 772 std::string sorient = pBegin->solidToRight() ? "RIGHT" : "LEFT";
Chris@16 773 std::cout<< " ActiveTail.tailp_ (solid= " << sorient ;
Chris@16 774 End dir = TAIL;
Chris@16 775 while(pBegin!=pEnd){
Chris@16 776 std::cout << pBegin << "={ ";
Chris@16 777 for(size_t i=0; i<pBegin->numSegments(); i++){
Chris@16 778 point_data<Unit> u = pBegin->getPoint(i);
Chris@16 779 std::cout << "(" << u.x() << "," << u.y() << ") ";
Chris@16 780 }
Chris@16 781 std::cout << "} ";
Chris@16 782 pBegin = pBegin->next(dir == HEAD ? TAIL : HEAD);
Chris@16 783 dir = pBegin->endConnectivity(dir == HEAD ? TAIL : HEAD);
Chris@16 784 }
Chris@16 785 if(pEnd){
Chris@16 786 std::cout << pEnd << "={ ";
Chris@16 787 for(size_t i=0; i<pEnd->numSegments(); i++){
Chris@16 788 point_data<Unit> u = pEnd->getPoint(i);
Chris@16 789 std::cout << "(" << u.x() << "," << u.y() << ") ";
Chris@16 790 }
Chris@16 791 std::cout << "} ";
Chris@16 792 }
Chris@16 793 std::cout << " end= " << pEnd << std::endl;
Chris@16 794 }
Chris@16 795 }
Chris@16 796
Chris@16 797 private:
Chris@16 798 void clearOutput_();
Chris@16 799 };
Chris@16 800
Chris@16 801 /*
Chris@16 802 * ScanLine does all the work of stitching together polygons from incoming vertical edges
Chris@16 803 */
Chris@16 804 // template <typename Unit, typename polygon_concept_type>
Chris@16 805 // class ScanLineToPolygons {
Chris@16 806 // private:
Chris@16 807 // ScanLineToPolygonItrs<true, Unit> scanline_;
Chris@16 808 // public:
Chris@16 809 // inline ScanLineToPolygons() : scanline_() {}
Chris@16 810 // /* construct a scanline with the proper offsets, protocol and options */
Chris@16 811 // inline ScanLineToPolygons(bool fractureHoles) : scanline_(fractureHoles) {}
Chris@16 812
Chris@16 813 // /* process all vertical edges, left and right, at a unique x coordinate, edges must be sorted low to high */
Chris@16 814 // inline void processEdges(std::vector<Unit>& outBufferTmp, Unit currentX, std::vector<interval_data<Unit> >& leftEdges,
Chris@16 815 // std::vector<interval_data<Unit> >& rightEdges) {
Chris@16 816 // typename ScanLineToPolygonItrs<true, Unit>::iterator itr, endItr;
Chris@16 817 // scanline_.processEdges(itr, endItr, currentX, leftEdges, rightEdges);
Chris@16 818 // //copy data into outBufferTmp
Chris@16 819 // while(itr != endItr) {
Chris@16 820 // typename PolyLinePolygonData<true, Unit>::iterator pditr;
Chris@16 821 // outBufferTmp.push_back(0);
Chris@16 822 // unsigned int sizeIndex = outBufferTmp.size() - 1;
Chris@16 823 // int count = 0;
Chris@16 824 // for(pditr = (*itr).begin(); pditr != (*itr).end(); ++pditr) {
Chris@16 825 // outBufferTmp.push_back(*pditr);
Chris@16 826 // ++count;
Chris@16 827 // }
Chris@16 828 // outBufferTmp[sizeIndex] = count;
Chris@16 829 // typename PolyLinePolygonData<true, Unit>::iteratorHoles pdHoleItr;
Chris@16 830 // for(pdHoleItr = (*itr).beginHoles(); pdHoleItr != (*itr).endHoles(); ++pdHoleItr) {
Chris@16 831 // outBufferTmp.push_back(0);
Chris@16 832 // unsigned int sizeIndex2 = outBufferTmp.size() - 1;
Chris@16 833 // int count2 = 0;
Chris@16 834 // for(pditr = (*pdHoleItr).begin(); pditr != (*pdHoleItr).end(); ++pditr) {
Chris@16 835 // outBufferTmp.push_back(*pditr);
Chris@16 836 // ++count2;
Chris@16 837 // }
Chris@16 838 // outBufferTmp[sizeIndex2] = -count;
Chris@16 839 // }
Chris@16 840 // ++itr;
Chris@16 841 // }
Chris@16 842 // }
Chris@16 843 // };
Chris@16 844
Chris@16 845 const int VERTICAL_HEAD = 1, HEAD_TO_TAIL = 2, TAIL_TO_TAIL = 4, SOLID_TO_RIGHT = 8;
Chris@16 846
Chris@16 847 //EVERY FUNCTION in this DEF file should be explicitly defined as inline
Chris@16 848
Chris@16 849 //microsoft compiler improperly warns whenever you cast an integer to bool
Chris@16 850 //call this function on an integer to convert it to bool without a warning
Chris@16 851 template <class T>
Chris@16 852 inline bool to_bool(const T& val) { return val != 0; }
Chris@16 853
Chris@16 854 //default constructor (for preallocation)
Chris@16 855 template <typename Unit>
Chris@16 856 inline PolyLine<Unit>::PolyLine() : ptdata_() ,headp_(0), tailp_(0), state_(-1) {}
Chris@16 857
Chris@16 858 //constructor
Chris@16 859 template <typename Unit>
Chris@16 860 inline PolyLine<Unit>::PolyLine(orientation_2d orient, Unit coord, Side side) :
Chris@16 861 ptdata_(1, coord),
Chris@16 862 headp_(0),
Chris@16 863 tailp_(0),
Chris@16 864 state_(orient.to_int() +
Chris@16 865 (side << 3)){}
Chris@16 866
Chris@16 867 //copy constructor
Chris@16 868 template <typename Unit>
Chris@16 869 inline PolyLine<Unit>::PolyLine(const PolyLine<Unit>& pline) : ptdata_(pline.ptdata_),
Chris@16 870 headp_(pline.headp_),
Chris@16 871 tailp_(pline.tailp_),
Chris@16 872 state_(pline.state_) {}
Chris@16 873
Chris@16 874 //destructor
Chris@16 875 template <typename Unit>
Chris@16 876 inline PolyLine<Unit>::~PolyLine() {
Chris@16 877 //clear out data just in case it is read later
Chris@16 878 headp_ = tailp_ = 0;
Chris@16 879 state_ = 0;
Chris@16 880 }
Chris@16 881
Chris@16 882 template <typename Unit>
Chris@16 883 inline PolyLine<Unit>& PolyLine<Unit>::operator=(const PolyLine<Unit>& that) {
Chris@16 884 if(!(this == &that)) {
Chris@16 885 headp_ = that.headp_;
Chris@16 886 tailp_ = that.tailp_;
Chris@16 887 ptdata_ = that.ptdata_;
Chris@16 888 state_ = that.state_;
Chris@16 889 }
Chris@16 890 return *this;
Chris@16 891 }
Chris@16 892
Chris@16 893 template <typename Unit>
Chris@16 894 inline bool PolyLine<Unit>::operator==(const PolyLine<Unit>& b) const {
Chris@16 895 return this == &b || (state_ == b.state_ &&
Chris@16 896 headp_ == b.headp_ &&
Chris@16 897 tailp_ == b.tailp_);
Chris@16 898 }
Chris@16 899
Chris@16 900 //valid PolyLine
Chris@16 901 template <typename Unit>
Chris@16 902 inline bool PolyLine<Unit>::isValid() const {
Chris@16 903 return state_ > -1; }
Chris@16 904
Chris@16 905 //first coordinate is an X value
Chris@16 906 //first segment is vertical
Chris@16 907 template <typename Unit>
Chris@16 908 inline bool PolyLine<Unit>::verticalHead() const {
Chris@16 909 return state_ & VERTICAL_HEAD;
Chris@16 910 }
Chris@16 911
Chris@16 912 //retrun true is PolyLine has odd number of coordiantes
Chris@16 913 template <typename Unit>
Chris@16 914 inline bool PolyLine<Unit>::oddLength() const {
Chris@16 915 return to_bool((ptdata_.size()-1) % 2);
Chris@16 916 }
Chris@16 917
Chris@16 918 //last coordiante is an X value
Chris@16 919 //last segment is vertical
Chris@16 920 template <typename Unit>
Chris@16 921 inline bool PolyLine<Unit>::verticalTail() const {
Chris@16 922 return to_bool(verticalHead() ^ oddLength());
Chris@16 923 }
Chris@16 924
Chris@16 925 template <typename Unit>
Chris@16 926 inline orientation_2d PolyLine<Unit>::tailOrient() const {
Chris@16 927 return (verticalTail() ? VERTICAL : HORIZONTAL);
Chris@16 928 }
Chris@16 929
Chris@16 930 template <typename Unit>
Chris@16 931 inline orientation_2d PolyLine<Unit>::headOrient() const {
Chris@16 932 return (verticalHead() ? VERTICAL : HORIZONTAL);
Chris@16 933 }
Chris@16 934
Chris@16 935 template <typename Unit>
Chris@16 936 inline End PolyLine<Unit>::endConnectivity(End end) const {
Chris@16 937 //Tail should be defined as true
Chris@16 938 if(end) { return tailToTail(); }
Chris@16 939 return headToTail();
Chris@16 940 }
Chris@16 941
Chris@16 942 template <typename Unit>
Chris@16 943 inline bool PolyLine<Unit>::headToTail() const {
Chris@16 944 return to_bool(state_ & HEAD_TO_TAIL);
Chris@16 945 }
Chris@16 946
Chris@16 947 template <typename Unit>
Chris@16 948 inline bool PolyLine<Unit>::headToHead() const {
Chris@16 949 return to_bool(!headToTail());
Chris@16 950 }
Chris@16 951
Chris@16 952 template <typename Unit>
Chris@16 953 inline bool PolyLine<Unit>::tailToHead() const {
Chris@16 954 return to_bool(!tailToTail());
Chris@16 955 }
Chris@16 956
Chris@16 957 template <typename Unit>
Chris@16 958 inline bool PolyLine<Unit>::tailToTail() const {
Chris@16 959 return to_bool(state_ & TAIL_TO_TAIL);
Chris@16 960 }
Chris@16 961
Chris@16 962 template <typename Unit>
Chris@16 963 inline Side PolyLine<Unit>::solidSide() const {
Chris@16 964 return solidToRight(); }
Chris@16 965
Chris@16 966 template <typename Unit>
Chris@16 967 inline bool PolyLine<Unit>::solidToRight() const {
Chris@16 968 return to_bool(state_ & SOLID_TO_RIGHT) != 0;
Chris@16 969 }
Chris@16 970
Chris@16 971 template <typename Unit>
Chris@16 972 inline bool PolyLine<Unit>::active() const {
Chris@16 973 return !to_bool(tailp_);
Chris@16 974 }
Chris@16 975
Chris@16 976 template <typename Unit>
Chris@16 977 inline PolyLine<Unit>& PolyLine<Unit>::pushCoordinate(Unit coord) {
Chris@16 978 ptdata_.push_back(coord);
Chris@16 979 return *this;
Chris@16 980 }
Chris@16 981
Chris@16 982 template <typename Unit>
Chris@16 983 inline PolyLine<Unit>& PolyLine<Unit>::popCoordinate() {
Chris@16 984 ptdata_.pop_back();
Chris@16 985 return *this;
Chris@16 986 }
Chris@16 987
Chris@16 988 template <typename Unit>
Chris@16 989 inline PolyLine<Unit>& PolyLine<Unit>::pushPoint(const point_data<Unit>& point) {
Chris@16 990 if(numSegments()){
Chris@16 991 point_data<Unit> endPt = getEndPoint();
Chris@16 992 //vertical is true, horizontal is false
Chris@16 993 if((tailOrient().to_int() ? point.get(VERTICAL) == endPt.get(VERTICAL) : point.get(HORIZONTAL) == endPt.get(HORIZONTAL))) {
Chris@16 994 //we were pushing a colinear segment
Chris@16 995 return popCoordinate();
Chris@16 996 }
Chris@16 997 }
Chris@16 998 return pushCoordinate(tailOrient().to_int() ? point.get(VERTICAL) : point.get(HORIZONTAL));
Chris@16 999 }
Chris@16 1000
Chris@16 1001 template <typename Unit>
Chris@16 1002 inline PolyLine<Unit>& PolyLine<Unit>::extendTail(Unit delta) {
Chris@16 1003 ptdata_.back() += delta;
Chris@16 1004 return *this;
Chris@16 1005 }
Chris@16 1006
Chris@16 1007 //private member function that creates a link from this PolyLine to that
Chris@16 1008 template <typename Unit>
Chris@16 1009 inline PolyLine<Unit>& PolyLine<Unit>::joinTo_(End thisEnd, PolyLine<Unit>& that, End end) {
Chris@16 1010 if(thisEnd){
Chris@16 1011 tailp_ = &that;
Chris@16 1012 state_ &= ~TAIL_TO_TAIL; //clear any previous state_ of bit (for safety)
Chris@16 1013 state_ |= (end << 2); //place bit into mask
Chris@16 1014 } else {
Chris@16 1015 headp_ = &that;
Chris@16 1016 state_ &= ~HEAD_TO_TAIL; //clear any previous state_ of bit (for safety)
Chris@16 1017 state_ |= (end << 1); //place bit into mask
Chris@16 1018 }
Chris@16 1019 return *this;
Chris@16 1020 }
Chris@16 1021
Chris@16 1022 //join two PolyLines (both ways of the association)
Chris@16 1023 template <typename Unit>
Chris@16 1024 inline PolyLine<Unit>& PolyLine<Unit>::joinTo(End thisEnd, PolyLine<Unit>& that, End end) {
Chris@16 1025 joinTo_(thisEnd, that, end);
Chris@16 1026 that.joinTo_(end, *this, thisEnd);
Chris@16 1027 return *this;
Chris@16 1028 }
Chris@16 1029
Chris@16 1030 //convenience functions for joining PolyLines
Chris@16 1031 template <typename Unit>
Chris@16 1032 inline PolyLine<Unit>& PolyLine<Unit>::joinToTail(PolyLine<Unit>& that, End end) {
Chris@16 1033 return joinTo(TAIL, that, end);
Chris@16 1034 }
Chris@16 1035 template <typename Unit>
Chris@16 1036 inline PolyLine<Unit>& PolyLine<Unit>::joinToHead(PolyLine<Unit>& that, End end) {
Chris@16 1037 return joinTo(HEAD, that, end);
Chris@16 1038 }
Chris@16 1039 template <typename Unit>
Chris@16 1040 inline PolyLine<Unit>& PolyLine<Unit>::joinHeadToHead(PolyLine<Unit>& that) {
Chris@16 1041 return joinToHead(that, HEAD);
Chris@16 1042 }
Chris@16 1043 template <typename Unit>
Chris@16 1044 inline PolyLine<Unit>& PolyLine<Unit>::joinHeadToTail(PolyLine<Unit>& that) {
Chris@16 1045 return joinToHead(that, TAIL);
Chris@16 1046 }
Chris@16 1047 template <typename Unit>
Chris@16 1048 inline PolyLine<Unit>& PolyLine<Unit>::joinTailToHead(PolyLine<Unit>& that) {
Chris@16 1049 return joinToTail(that, HEAD);
Chris@16 1050 }
Chris@16 1051 template <typename Unit>
Chris@16 1052 inline PolyLine<Unit>& PolyLine<Unit>::joinTailToTail(PolyLine<Unit>& that) {
Chris@16 1053 return joinToTail(that, TAIL);
Chris@16 1054 }
Chris@16 1055
Chris@16 1056 template <typename Unit>
Chris@16 1057 inline PolyLine<Unit>& PolyLine<Unit>::disconnectTails() {
Chris@16 1058 next(TAIL)->state_ &= !TAIL_TO_TAIL;
Chris@16 1059 next(TAIL)->tailp_ = 0;
Chris@16 1060 state_ &= !TAIL_TO_TAIL;
Chris@16 1061 tailp_ = 0;
Chris@16 1062 return *this;
Chris@16 1063 }
Chris@16 1064
Chris@16 1065 template <typename Unit>
Chris@16 1066 inline Unit PolyLine<Unit>::getEndCoord(End end) const {
Chris@16 1067 if(end)
Chris@16 1068 return ptdata_.back();
Chris@16 1069 return ptdata_.front();
Chris@16 1070 }
Chris@16 1071
Chris@16 1072 template <typename Unit>
Chris@16 1073 inline orientation_2d PolyLine<Unit>::segmentOrient(unsigned int index) const {
Chris@16 1074 return (to_bool((unsigned int)verticalHead() ^ (index % 2)) ? VERTICAL : HORIZONTAL);
Chris@16 1075 }
Chris@16 1076
Chris@16 1077 template <typename Unit>
Chris@16 1078 inline point_data<Unit> PolyLine<Unit>::getPoint(unsigned int index) const {
Chris@16 1079 //assert(isValid() && headp_->isValid()) ("PolyLine: headp_ must be valid");
Chris@16 1080 point_data<Unit> pt;
Chris@16 1081 pt.set(HORIZONTAL, ptdata_[index]);
Chris@16 1082 pt.set(VERTICAL, ptdata_[index]);
Chris@16 1083 Unit prevCoord;
Chris@16 1084 if(index == 0) {
Chris@16 1085 prevCoord = headp_->getEndCoord(headToTail());
Chris@16 1086 } else {
Chris@16 1087 prevCoord = ptdata_[index-1];
Chris@16 1088 }
Chris@16 1089 pt.set(segmentOrient(index), prevCoord);
Chris@16 1090 return pt;
Chris@16 1091 }
Chris@16 1092
Chris@16 1093 template <typename Unit>
Chris@16 1094 inline point_data<Unit> PolyLine<Unit>::getEndPoint(End end) const {
Chris@16 1095 return getPoint((end ? numSegments() - 1 : (unsigned int)0));
Chris@16 1096 }
Chris@16 1097
Chris@16 1098 template <typename Unit>
Chris@16 1099 inline Unit PolyLine<Unit>::operator[] (unsigned int index) const {
Chris@16 1100 //assert(ptdata_.size() > index) ("PolyLine: out of bounds index");
Chris@16 1101 return ptdata_[index];
Chris@16 1102 }
Chris@16 1103
Chris@16 1104 template <typename Unit>
Chris@16 1105 inline unsigned int PolyLine<Unit>::numSegments() const {
Chris@16 1106 return ptdata_.size();
Chris@16 1107 }
Chris@16 1108
Chris@16 1109 template <typename Unit>
Chris@16 1110 inline PolyLine<Unit>* PolyLine<Unit>::next(End end) const {
Chris@16 1111 return (end ? tailp_ : headp_);
Chris@16 1112 }
Chris@16 1113
Chris@16 1114 template <typename Unit>
Chris@16 1115 inline ActiveTail<Unit>::ActiveTail() : tailp_(0), otherTailp_(0), holesList_(),
Chris@16 1116 polyLineSize_(0) {}
Chris@16 1117
Chris@16 1118 template <typename Unit>
Chris@16 1119 inline ActiveTail<Unit>::ActiveTail(orientation_2d orient, Unit coord, Side solidToRight, ActiveTail* otherTailp) :
Chris@16 1120 tailp_(0), otherTailp_(0), holesList_(), polyLineSize_(0) {
Chris@16 1121 tailp_ = createPolyLine(orient, coord, solidToRight);
Chris@16 1122 otherTailp_ = otherTailp;
Chris@16 1123 polyLineSize_ = tailp_->numSegments();
Chris@16 1124 }
Chris@16 1125
Chris@16 1126 template <typename Unit>
Chris@16 1127 inline ActiveTail<Unit>::ActiveTail(PolyLine<Unit>* active, ActiveTail<Unit>* otherTailp) :
Chris@16 1128 tailp_(active), otherTailp_(otherTailp), holesList_(),
Chris@16 1129 polyLineSize_(0) {}
Chris@16 1130
Chris@16 1131 //copy constructor
Chris@16 1132 template <typename Unit>
Chris@16 1133 inline ActiveTail<Unit>::ActiveTail(const ActiveTail<Unit>& that) : tailp_(that.tailp_), otherTailp_(that.otherTailp_), holesList_(), polyLineSize_(that.polyLineSize_) {}
Chris@16 1134
Chris@16 1135 //destructor
Chris@16 1136 template <typename Unit>
Chris@16 1137 inline ActiveTail<Unit>::~ActiveTail() {
Chris@16 1138 //clear them in case the memory is read later
Chris@16 1139 tailp_ = 0; otherTailp_ = 0;
Chris@16 1140 }
Chris@16 1141
Chris@16 1142 template <typename Unit>
Chris@16 1143 inline ActiveTail<Unit>& ActiveTail<Unit>::operator=(const ActiveTail<Unit>& that) {
Chris@16 1144 //self assignment is safe in this case
Chris@16 1145 tailp_ = that.tailp_;
Chris@16 1146 otherTailp_ = that.otherTailp_;
Chris@16 1147 polyLineSize_ = that.polyLineSize_;
Chris@16 1148 return *this;
Chris@16 1149 }
Chris@16 1150
Chris@16 1151 template <typename Unit>
Chris@16 1152 inline bool ActiveTail<Unit>::operator==(const ActiveTail<Unit>& b) const {
Chris@16 1153 return tailp_ == b.tailp_ && otherTailp_ == b.otherTailp_;
Chris@16 1154 }
Chris@16 1155
Chris@16 1156 template <typename Unit>
Chris@16 1157 inline bool ActiveTail<Unit>::operator<(const ActiveTail<Unit>& b) const {
Chris@16 1158 return tailp_->getEndPoint().get(VERTICAL) < b.tailp_->getEndPoint().get(VERTICAL);
Chris@16 1159 }
Chris@16 1160
Chris@16 1161 template <typename Unit>
Chris@16 1162 inline bool ActiveTail<Unit>::operator<=(const ActiveTail<Unit>& b) const {
Chris@16 1163 return !(*this > b); }
Chris@16 1164
Chris@16 1165 template <typename Unit>
Chris@16 1166 inline bool ActiveTail<Unit>::operator>(const ActiveTail<Unit>& b) const {
Chris@16 1167 return b < (*this); }
Chris@16 1168
Chris@16 1169 template <typename Unit>
Chris@16 1170 inline bool ActiveTail<Unit>::operator>=(const ActiveTail<Unit>& b) const {
Chris@16 1171 return !(*this < b); }
Chris@16 1172
Chris@16 1173 template <typename Unit>
Chris@16 1174 inline PolyLine<Unit>* ActiveTail<Unit>::getTail() const {
Chris@16 1175 return tailp_; }
Chris@16 1176
Chris@16 1177 template <typename Unit>
Chris@16 1178 inline PolyLine<Unit>* ActiveTail<Unit>::getOtherTail() const {
Chris@16 1179 return otherTailp_->tailp_; }
Chris@16 1180
Chris@16 1181 template <typename Unit>
Chris@16 1182 inline ActiveTail<Unit>* ActiveTail<Unit>::getOtherActiveTail() const {
Chris@16 1183 return otherTailp_; }
Chris@16 1184
Chris@16 1185 template <typename Unit>
Chris@16 1186 inline bool ActiveTail<Unit>::isOtherTail(const ActiveTail<Unit>& b) {
Chris@16 1187 // assert( (tailp_ == b.getOtherTail() && getOtherTail() == b.tailp_) ||
Chris@16 1188 // (tailp_ != b.getOtherTail() && getOtherTail() != b.tailp_))
Chris@16 1189 // ("ActiveTail: Active tails out of sync");
Chris@16 1190 return otherTailp_ == &b;
Chris@16 1191 }
Chris@16 1192
Chris@16 1193 template <typename Unit>
Chris@16 1194 inline ActiveTail<Unit>& ActiveTail<Unit>::updateTail(PolyLine<Unit>* newTail) {
Chris@16 1195 //subtract the old size and add new size//
Chris@16 1196 int delta = newTail->numSegments() - tailp_->numSegments();
Chris@16 1197 addPolyLineSize(delta);
Chris@16 1198 otherTailp_->addPolyLineSize(delta);
Chris@16 1199 tailp_ = newTail;
Chris@16 1200 return *this;
Chris@16 1201 }
Chris@16 1202
Chris@16 1203 template <typename Unit>
Chris@16 1204 inline ActiveTail<Unit>* ActiveTail<Unit>::addHole(ActiveTail<Unit>* hole, bool fractureHoles) {
Chris@16 1205
Chris@16 1206 if(!fractureHoles){
Chris@16 1207 holesList_.push_back(hole);
Chris@16 1208 copyHoles(*hole);
Chris@16 1209 copyHoles(*(hole->getOtherActiveTail()));
Chris@16 1210 return this;
Chris@16 1211 }
Chris@16 1212 ActiveTail<Unit>* h, *v;
Chris@16 1213 ActiveTail<Unit>* other = hole->getOtherActiveTail();
Chris@16 1214 if(other->getOrient() == VERTICAL) {
Chris@16 1215 //assert that hole.getOrient() == HORIZONTAL
Chris@16 1216 //this case should never happen
Chris@16 1217 h = hole;
Chris@16 1218 v = other;
Chris@16 1219 } else {
Chris@16 1220 //assert that hole.getOrient() == VERTICAL
Chris@16 1221 h = other;
Chris@16 1222 v = hole;
Chris@16 1223 }
Chris@16 1224 h->pushCoordinate(v->getCoordinate());
Chris@16 1225 //assert that h->getOrient() == VERTICAL
Chris@16 1226 //v->pushCoordinate(getCoordinate());
Chris@16 1227 //assert that v->getOrient() == VERTICAL
Chris@16 1228 //I can't close a figure by adding a hole, so pass zero for xMin and yMin
Chris@16 1229 std::vector<Unit> tmpVec;
Chris@16 1230 ActiveTail<Unit>::joinChains(this, h, false, tmpVec);
Chris@16 1231 return v;
Chris@16 1232 }
Chris@16 1233
Chris@16 1234 template <typename Unit>
Chris@16 1235 inline const std::list<ActiveTail<Unit>*>& ActiveTail<Unit>::getHoles() const {
Chris@16 1236 return holesList_;
Chris@16 1237 }
Chris@16 1238
Chris@16 1239 template <typename Unit>
Chris@16 1240 inline void ActiveTail<Unit>::copyHoles(ActiveTail<Unit>& that) {
Chris@16 1241 holesList_.splice(holesList_.end(), that.holesList_); //splice the two lists together
Chris@16 1242 }
Chris@16 1243
Chris@16 1244 template <typename Unit>
Chris@16 1245 inline bool ActiveTail<Unit>::solidToRight() const {
Chris@16 1246 return getTail()->solidToRight(); }
Chris@16 1247
Chris@16 1248 template <typename Unit>
Chris@16 1249 inline Unit ActiveTail<Unit>::getCoord() const {
Chris@16 1250 return getTail()->getEndCoord(); }
Chris@16 1251
Chris@16 1252 template <typename Unit>
Chris@16 1253 inline Unit ActiveTail<Unit>::getCoordinate() const {
Chris@16 1254 return getCoord(); }
Chris@16 1255
Chris@16 1256 template <typename Unit>
Chris@16 1257 inline orientation_2d ActiveTail<Unit>::getOrient() const {
Chris@16 1258 return getTail()->tailOrient(); }
Chris@16 1259
Chris@16 1260 template <typename Unit>
Chris@16 1261 inline void ActiveTail<Unit>::pushCoordinate(Unit coord) {
Chris@16 1262 //appropriately handle any co-linear polyline segments by calling push point internally
Chris@16 1263 point_data<Unit> p;
Chris@16 1264 p.set(HORIZONTAL, coord);
Chris@16 1265 p.set(VERTICAL, coord);
Chris@16 1266 //if we are vertical assign the last coordinate (an X) to p.x, else to p.y
Chris@16 1267 p.set(getOrient().get_perpendicular(), getCoordinate());
Chris@16 1268 int oldSegments = tailp_->numSegments();
Chris@16 1269 tailp_->pushPoint(p);
Chris@16 1270 int delta = tailp_->numSegments() - oldSegments;
Chris@16 1271 addPolyLineSize(delta);
Chris@16 1272 otherTailp_->addPolyLineSize(delta);
Chris@16 1273 }
Chris@16 1274
Chris@16 1275
Chris@16 1276 //global utility functions
Chris@16 1277 template <typename Unit>
Chris@16 1278 inline PolyLine<Unit>* createPolyLine(orientation_2d orient, Unit coord, Side side) {
Chris@16 1279 return new PolyLine<Unit>(orient, coord, side);
Chris@16 1280 }
Chris@16 1281
Chris@16 1282 template <typename Unit>
Chris@16 1283 inline void destroyPolyLine(PolyLine<Unit>* pLine) {
Chris@16 1284 delete pLine;
Chris@16 1285 }
Chris@16 1286
Chris@16 1287 template <typename Unit>
Chris@16 1288 inline ActiveTail<Unit>* createActiveTail() {
Chris@16 1289 //consider replacing system allocator with ActiveTail memory pool
Chris@16 1290 return new ActiveTail<Unit>();
Chris@16 1291 }
Chris@16 1292
Chris@16 1293 template <typename Unit>
Chris@16 1294 inline void destroyActiveTail(ActiveTail<Unit>* aTail) {
Chris@16 1295 delete aTail;
Chris@16 1296 }
Chris@16 1297
Chris@16 1298
Chris@16 1299 //no recursion, to prevent max recursion depth errors
Chris@16 1300 template <typename Unit>
Chris@16 1301 inline void ActiveTail<Unit>::destroyContents() {
Chris@16 1302 tailp_->disconnectTails();
Chris@16 1303 PolyLine<Unit>* nextPolyLinep = tailp_->next(HEAD);
Chris@16 1304 End end = tailp_->endConnectivity(HEAD);
Chris@16 1305 destroyPolyLine(tailp_);
Chris@16 1306 while(nextPolyLinep) {
Chris@16 1307 End nextEnd = nextPolyLinep->endConnectivity(!end); //get the direction of next polyLine
Chris@16 1308 PolyLine<Unit>* nextNextPolyLinep = nextPolyLinep->next(!end); //get the next polyline
Chris@16 1309 destroyPolyLine(nextPolyLinep); //destroy the current polyline
Chris@16 1310 end = nextEnd;
Chris@16 1311 nextPolyLinep = nextNextPolyLinep;
Chris@16 1312 }
Chris@16 1313 }
Chris@16 1314
Chris@16 1315 template <typename Unit>
Chris@16 1316 inline typename ActiveTail<Unit>::iterator ActiveTail<Unit>::begin(bool isHole, orientation_2d orient) const {
Chris@16 1317 return iterator(this, isHole, orient);
Chris@16 1318 }
Chris@16 1319
Chris@16 1320 template <typename Unit>
Chris@16 1321 inline typename ActiveTail<Unit>::iterator ActiveTail<Unit>::end() const {
Chris@16 1322 return iterator();
Chris@16 1323 }
Chris@16 1324
Chris@16 1325 template <typename Unit>
Chris@16 1326 inline typename ActiveTail<Unit>::iteratorHoles ActiveTail<Unit>::beginHoles() const {
Chris@16 1327 return holesList_.begin();
Chris@16 1328 }
Chris@16 1329
Chris@16 1330 template <typename Unit>
Chris@16 1331 inline typename ActiveTail<Unit>::iteratorHoles ActiveTail<Unit>::endHoles() const {
Chris@16 1332 return holesList_.end();
Chris@16 1333 }
Chris@16 1334
Chris@16 1335 template <typename Unit>
Chris@16 1336 inline void ActiveTail<Unit>::writeOutFigureItrs(iterator& beginOut, iterator& endOut, bool isHole, orientation_2d orient) const {
Chris@16 1337 beginOut = begin(isHole, orient);
Chris@16 1338 endOut = end();
Chris@16 1339 }
Chris@16 1340
Chris@16 1341 template <typename Unit>
Chris@16 1342 inline void ActiveTail<Unit>::writeOutFigureHoleItrs(iteratorHoles& beginOut, iteratorHoles& endOut) const {
Chris@16 1343 beginOut = beginHoles();
Chris@16 1344 endOut = endHoles();
Chris@16 1345 }
Chris@16 1346
Chris@16 1347 template <typename Unit>
Chris@16 1348 inline void ActiveTail<Unit>::writeOutFigure(std::vector<Unit>& outVec, bool isHole) const {
Chris@16 1349 //we start writing out the polyLine that this active tail points to at its tail
Chris@16 1350 std::size_t size = outVec.size();
Chris@16 1351 outVec.push_back(0); //place holder for size
Chris@16 1352 PolyLine<Unit>* nextPolyLinep = 0;
Chris@16 1353 if(!isHole){
Chris@16 1354 nextPolyLinep = otherTailp_->tailp_->writeOut(outVec);
Chris@16 1355 } else {
Chris@16 1356 nextPolyLinep = tailp_->writeOut(outVec);
Chris@16 1357 }
Chris@16 1358 Unit firsty = outVec[size + 1];
Chris@16 1359 if((getOrient() == HORIZONTAL) ^ !isHole) {
Chris@16 1360 //our first coordinate is a y value, so we need to rotate it to the end
Chris@16 1361 typename std::vector<Unit>::iterator tmpItr = outVec.begin();
Chris@16 1362 tmpItr += size;
Chris@16 1363 outVec.erase(++tmpItr); //erase the 2nd element
Chris@16 1364 }
Chris@16 1365 End startEnd = tailp_->endConnectivity(HEAD);
Chris@16 1366 if(isHole) startEnd = otherTailp_->tailp_->endConnectivity(HEAD);
Chris@16 1367 while(nextPolyLinep) {
Chris@16 1368 bool nextStartEnd = nextPolyLinep->endConnectivity(!startEnd);
Chris@16 1369 nextPolyLinep = nextPolyLinep->writeOut(outVec, startEnd);
Chris@16 1370 startEnd = nextStartEnd;
Chris@16 1371 }
Chris@16 1372 if((getOrient() == HORIZONTAL) ^ !isHole) {
Chris@16 1373 //we want to push the y value onto the end since we ought to have ended with an x
Chris@16 1374 outVec.push_back(firsty); //should never be executed because we want first value to be an x
Chris@16 1375 }
Chris@16 1376 //the vector contains the coordinates of the linked list of PolyLines in the correct order
Chris@16 1377 //first element is supposed to be the size
Chris@16 1378 outVec[size] = outVec.size() - 1 - size; //number of coordinates in vector
Chris@16 1379 //assert outVec[size] % 2 == 0 //it should be even
Chris@16 1380 //make the size negative for holes
Chris@16 1381 outVec[size] *= (isHole ? -1 : 1);
Chris@16 1382 }
Chris@16 1383
Chris@16 1384 //no recursion to prevent max recursion depth errors
Chris@16 1385 template <typename Unit>
Chris@16 1386 inline PolyLine<Unit>* PolyLine<Unit>::writeOut(std::vector<Unit>& outVec, End startEnd) const {
Chris@16 1387 if(startEnd == HEAD){
Chris@16 1388 //forward order
Chris@16 1389 outVec.insert(outVec.end(), ptdata_.begin(), ptdata_.end());
Chris@16 1390 return tailp_;
Chris@16 1391 }else{
Chris@16 1392 //reverse order
Chris@16 1393 //do not reserve because we expect outVec to be large enough already
Chris@16 1394 for(int i = ptdata_.size() - 1; i >= 0; --i){
Chris@16 1395 outVec.push_back(ptdata_[i]);
Chris@16 1396 }
Chris@16 1397 //NT didn't know about this version of the API....
Chris@16 1398 //outVec.insert(outVec.end(), ptdata_.rbegin(), ptdata_.rend());
Chris@16 1399 return headp_;
Chris@16 1400 }
Chris@16 1401 }
Chris@16 1402
Chris@16 1403 //solid indicates if it was joined by a solit or a space
Chris@16 1404 template <typename Unit>
Chris@16 1405 inline ActiveTail<Unit>* ActiveTail<Unit>::joinChains(ActiveTail<Unit>* at1, ActiveTail<Unit>* at2, bool solid, std::vector<Unit>& outBufferTmp)
Chris@16 1406 {
Chris@16 1407 //checks to see if we closed a figure
Chris@16 1408 if(at1->isOtherTail(*at2)){
Chris@16 1409 //value of solid tells us if we closed solid or hole
Chris@16 1410 //and output the solid or handle the hole appropriately
Chris@16 1411 //if the hole needs to fracture across horizontal partition boundary we need to notify
Chris@16 1412 //the calling context to do so
Chris@16 1413 if(solid) {
Chris@16 1414 //the chains are being joined because there is solid to the right
Chris@16 1415 //this means that if the figure is closed at this point it must be a hole
Chris@16 1416 //because otherwise it would have to have another vertex to the right of this one
Chris@16 1417 //and would not be closed at this point
Chris@16 1418 return at1;
Chris@16 1419 } else {
Chris@16 1420 //assert pG != 0
Chris@16 1421 //the figure that was closed is a shell
Chris@16 1422 at1->writeOutFigure(outBufferTmp);
Chris@16 1423 //process holes of the polygon
Chris@16 1424 at1->copyHoles(*at2); //there should not be holes on at2, but if there are, copy them over
Chris@16 1425 const std::list<ActiveTail<Unit>*>& holes = at1->getHoles();
Chris@16 1426 for(typename std::list<ActiveTail<Unit>*>::const_iterator litr = holes.begin(); litr != holes.end(); ++litr) {
Chris@16 1427 (*litr)->writeOutFigure(outBufferTmp, true);
Chris@16 1428 //delete the hole
Chris@16 1429 (*litr)->destroyContents();
Chris@16 1430 destroyActiveTail((*litr)->getOtherActiveTail());
Chris@16 1431 destroyActiveTail((*litr));
Chris@16 1432 }
Chris@16 1433 //delete the polygon
Chris@16 1434 at1->destroyContents();
Chris@16 1435 //at2 contents are the same as at1, so it should not destroy them
Chris@16 1436 destroyActiveTail(at1);
Chris@16 1437 destroyActiveTail(at2);
Chris@16 1438 }
Chris@16 1439 return 0;
Chris@16 1440 }
Chris@16 1441 //join the two partial polygons into one large partial polygon
Chris@16 1442 at1->getTail()->joinTailToTail(*(at2->getTail()));
Chris@16 1443 *(at1->getOtherActiveTail()) = ActiveTail(at1->getOtherTail(), at2->getOtherActiveTail());
Chris@16 1444 *(at2->getOtherActiveTail()) = ActiveTail(at2->getOtherTail(), at1->getOtherActiveTail());
Chris@16 1445
Chris@16 1446 int accumulate = at2->getPolyLineSize() + at1->getPolyLineSize();
Chris@16 1447 (at1->getOtherActiveTail())->setPolyLineSize(accumulate);
Chris@16 1448 (at2->getOtherActiveTail())->setPolyLineSize(accumulate);
Chris@16 1449
Chris@16 1450 at1->getOtherActiveTail()->copyHoles(*at1);
Chris@16 1451 at1->getOtherActiveTail()->copyHoles(*at2);
Chris@16 1452 destroyActiveTail(at1);
Chris@16 1453 destroyActiveTail(at2);
Chris@16 1454 return 0;
Chris@16 1455 }
Chris@16 1456
Chris@16 1457 //solid indicates if it was joined by a solit or a space
Chris@16 1458 template <typename Unit>
Chris@16 1459 template <typename PolygonT>
Chris@16 1460 inline ActiveTail<Unit>* ActiveTail<Unit>::joinChains(ActiveTail<Unit>* at1, ActiveTail<Unit>* at2, bool solid,
Chris@16 1461 std::vector<PolygonT>& outBufferTmp) {
Chris@16 1462 //checks to see if we closed a figure
Chris@16 1463 if(at1->isOtherTail(*at2)){
Chris@16 1464 //value of solid tells us if we closed solid or hole
Chris@16 1465 //and output the solid or handle the hole appropriately
Chris@16 1466 //if the hole needs to fracture across horizontal partition boundary we need to notify
Chris@16 1467 //the calling context to do so
Chris@16 1468 if(solid) {
Chris@16 1469 //the chains are being joined because there is solid to the right
Chris@16 1470 //this means that if the figure is closed at this point it must be a hole
Chris@16 1471 //because otherwise it would have to have another vertex to the right of this one
Chris@16 1472 //and would not be closed at this point
Chris@16 1473 return at1;
Chris@16 1474 } else {
Chris@16 1475 //assert pG != 0
Chris@16 1476 //the figure that was closed is a shell
Chris@16 1477 outBufferTmp.push_back(at1);
Chris@16 1478 at1->copyHoles(*at2); //there should not be holes on at2, but if there are, copy them over
Chris@16 1479 }
Chris@16 1480 return 0;
Chris@16 1481 }
Chris@16 1482 //join the two partial polygons into one large partial polygon
Chris@16 1483 at1->getTail()->joinTailToTail(*(at2->getTail()));
Chris@16 1484 *(at1->getOtherActiveTail()) = ActiveTail<Unit>(at1->getOtherTail(), at2->getOtherActiveTail());
Chris@16 1485 *(at2->getOtherActiveTail()) = ActiveTail<Unit>(at2->getOtherTail(), at1->getOtherActiveTail());
Chris@16 1486
Chris@16 1487 int accumulate = at2->getPolyLineSize() + at1->getPolyLineSize();
Chris@16 1488 (at1->getOtherActiveTail())->setPolyLineSize(accumulate);
Chris@16 1489 (at2->getOtherActiveTail())->setPolyLineSize(accumulate);
Chris@16 1490
Chris@16 1491 at1->getOtherActiveTail()->copyHoles(*at1);
Chris@16 1492 at1->getOtherActiveTail()->copyHoles(*at2);
Chris@16 1493 destroyActiveTail(at1);
Chris@16 1494 destroyActiveTail(at2);
Chris@16 1495 return 0;
Chris@16 1496 }
Chris@16 1497
Chris@16 1498 template <class TKey, class T> inline typename std::map<TKey, T>::iterator findAtNext(std::map<TKey, T>& theMap,
Chris@16 1499 typename std::map<TKey, T>::iterator pos, const TKey& key)
Chris@16 1500 {
Chris@16 1501 if(pos == theMap.end()) return theMap.find(key);
Chris@16 1502 //if they match the mapItr is pointing to the correct position
Chris@16 1503 if(pos->first < key) {
Chris@16 1504 return theMap.find(key);
Chris@16 1505 }
Chris@16 1506 if(pos->first > key) {
Chris@16 1507 return theMap.end();
Chris@16 1508 }
Chris@16 1509 //else they are equal and no need to do anything to the iterator
Chris@16 1510 return pos;
Chris@16 1511 }
Chris@16 1512
Chris@16 1513 // createActiveTailsAsPair is called in these two end cases of geometry
Chris@16 1514 // 1. lower left concave corner
Chris@16 1515 // ###|
Chris@16 1516 // ###|
Chris@16 1517 // ###|###
Chris@16 1518 // ###|###
Chris@16 1519 // 2. lower left convex corner
Chris@16 1520 // |###
Chris@16 1521 // |###
Chris@16 1522 // |
Chris@16 1523 // |
Chris@16 1524 // In case 1 there may be a hole propigated up from the bottom. If the fracture option is enabled
Chris@16 1525 // the two active tails that form the filament fracture line edges can become the new active tail pair
Chris@16 1526 // by pushing x and y onto them. Otherwise the hole simply needs to be associated to one of the new active tails
Chris@16 1527 // with add hole
Chris@16 1528 template <typename Unit>
Chris@16 1529 inline std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> createActiveTailsAsPair(Unit x, Unit y, bool solid, ActiveTail<Unit>* phole, bool fractureHoles) {
Chris@16 1530 ActiveTail<Unit>* at1 = 0;
Chris@16 1531 ActiveTail<Unit>* at2 = 0;
Chris@16 1532 if(!phole || !fractureHoles){
Chris@16 1533 at1 = createActiveTail<Unit>();
Chris@16 1534 at2 = createActiveTail<Unit>();
Chris@16 1535 (*at1) = ActiveTail<Unit>(VERTICAL, x, solid, at2);
Chris@16 1536 (*at2) = ActiveTail<Unit>(HORIZONTAL, y, !solid, at1);
Chris@16 1537 //provide a function through activeTail class to provide this
Chris@16 1538 at1->getTail()->joinHeadToHead(*(at2->getTail()));
Chris@16 1539
Chris@16 1540 at1->addPolyLineSize(1);
Chris@16 1541 at2->addPolyLineSize(1);
Chris@16 1542
Chris@16 1543 if(phole)
Chris@16 1544 at1->addHole(phole, fractureHoles); //assert fractureHoles == false
Chris@16 1545 return std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*>(at1, at2);
Chris@16 1546 }
Chris@16 1547 //assert phole is not null
Chris@16 1548 //assert fractureHoles is true
Chris@16 1549 if(phole->getOrient() == VERTICAL) {
Chris@16 1550 at2 = phole;
Chris@16 1551 } else {
Chris@16 1552 at2 = phole->getOtherActiveTail(); //should never be executed since orientation is expected to be vertical
Chris@16 1553 }
Chris@16 1554 //assert solid == false, we should be creating a corner with solid below and to the left if there was a hole
Chris@16 1555 at1 = at2->getOtherActiveTail();
Chris@16 1556 //assert at1 is horizontal
Chris@16 1557 at1->pushCoordinate(x);
Chris@16 1558 //assert at2 is vertical
Chris@16 1559 at2->pushCoordinate(y);
Chris@16 1560
Chris@16 1561 return std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*>(at1, at2);
Chris@16 1562 }
Chris@16 1563
Chris@16 1564 /*
Chris@16 1565 * |
Chris@16 1566 * |
Chris@16 1567 * =
Chris@16 1568 * |########
Chris@16 1569 * |######## (add a new ActiveTail in the tailMap_).
Chris@16 1570 * |########
Chris@16 1571 * |########
Chris@16 1572 * |########
Chris@16 1573 * =
Chris@16 1574 * |
Chris@16 1575 * |
Chris@16 1576 *
Chris@16 1577 * NOTE: Call this only if you are sure that the $ledege$ is not in the tailMap_
Chris@16 1578 */
Chris@16 1579 template<bool orientT, typename Unit, typename polygon_concept_type>
Chris@16 1580 inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
Chris@16 1581 insertNewLeftEdgeIntoTailMap(Unit currentX, Unit yBegin, Unit yEnd,
Chris@16 1582 typename std::map<Unit, ActiveTail<Unit> *>::iterator &hint){
Chris@16 1583 ActiveTail<Unit> *currentTail = NULL;
Chris@16 1584 std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair =
Chris@16 1585 createActiveTailsAsPair(currentX, yBegin, true, currentTail,
Chris@16 1586 fractureHoles_);
Chris@16 1587 currentTail = tailPair.first;
Chris@16 1588 if(!tailMap_.empty()){
Chris@16 1589 ++hint;
Chris@16 1590 }
Chris@16 1591 hint = tailMap_.insert(hint, std::make_pair(yBegin, tailPair.second));
Chris@16 1592 currentTail->pushCoordinate(yEnd); ++hint;
Chris@16 1593 hint = tailMap_.insert(hint, std::make_pair(yEnd, currentTail));
Chris@16 1594 }
Chris@16 1595
Chris@16 1596 template<bool orientT, typename Unit, typename polygon_concept_type>
Chris@16 1597 inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
Chris@16 1598 closePartialSimplePolygon(Unit currentX, ActiveTail<Unit>*pfig,
Chris@16 1599 ActiveTail<Unit>*ppfig){
Chris@16 1600 pfig->pushCoordinate(currentX);
Chris@16 1601 ActiveTail<Unit>::joinChains(pfig, ppfig, false, outputPolygons_);
Chris@16 1602 }
Chris@16 1603 /*
Chris@16 1604 * If the invariant is maintained correctly then left edges can do the
Chris@16 1605 * following.
Chris@16 1606 *
Chris@16 1607 * =###
Chris@16 1608 * #######
Chris@16 1609 * #######
Chris@16 1610 * #######
Chris@16 1611 * #######
Chris@16 1612 * =###
Chris@16 1613 * |### (input left edge)
Chris@16 1614 * |###
Chris@16 1615 * =###
Chris@16 1616 * #######
Chris@16 1617 * #######
Chris@16 1618 * =###
Chris@16 1619 */
Chris@16 1620 template<bool orientT, typename Unit, typename polygon_concept_type>
Chris@16 1621 inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
Chris@16 1622 updatePartialSimplePolygonsWithLeftEdges(Unit currentX,
Chris@16 1623 const std::vector<interval_data<Unit> > &leftEdges, size_t vertexThreshold){
Chris@16 1624 typename std::map<Unit, ActiveTail<Unit>* >::iterator succ, succ1;
Chris@16 1625 typename std::map<Unit, ActiveTail<Unit>* >::iterator pred, pred1, hint;
Chris@16 1626 Unit begin, end;
Chris@16 1627 ActiveTail<Unit> *pfig, *ppfig;
Chris@16 1628 std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair;
Chris@16 1629 size_t pfig_size = 0;
Chris@16 1630
Chris@16 1631 hint = tailMap_.begin();
Chris@16 1632 for(size_t i=0; i < leftEdges.size(); i++){
Chris@16 1633 begin = leftEdges[i].get(LOW); end = leftEdges[i].get(HIGH);
Chris@16 1634 succ = findAtNext(tailMap_, hint, begin);
Chris@16 1635 pred = findAtNext(tailMap_, hint, end);
Chris@16 1636
Chris@16 1637 if(succ != tailMap_.end() && pred != tailMap_.end()){ //CASE-1//
Chris@16 1638 //join the corresponding active tails//
Chris@16 1639 pfig = succ->second; ppfig = pred->second;
Chris@16 1640 pfig_size = pfig->getPolyLineSize() + ppfig->getPolyLineSize();
Chris@16 1641
Chris@16 1642 if(pfig_size >= vertexThreshold){
Chris@16 1643 size_t bsize = pfig->getPolyLineSize();
Chris@16 1644 size_t usize = ppfig->getPolyLineSize();
Chris@16 1645
Chris@16 1646 if(usize+2 < vertexThreshold){
Chris@16 1647 //cut-off the lower piece (succ1, succ) join (succ1, pred)//
Chris@16 1648 succ1 = succ; --succ1;
Chris@16 1649 assert((succ1 != tailMap_.end()) &&
Chris@16 1650 ((succ->second)->getOtherActiveTail() == succ1->second));
Chris@16 1651 closePartialSimplePolygon(currentX, succ1->second, succ->second);
Chris@16 1652 tailPair = createActiveTailsAsPair<Unit>(currentX, succ1->first,
Chris@16 1653 true, NULL, fractureHoles_);
Chris@16 1654
Chris@16 1655 //just update the succ1 with new ActiveTail<Unit>*//
Chris@16 1656 succ1->second = tailPair.second;
Chris@16 1657 ActiveTail<Unit>::joinChains(tailPair.first, pred->second, true,
Chris@16 1658 outputPolygons_);
Chris@16 1659 }else if(bsize+2 < vertexThreshold){
Chris@16 1660 //cut-off the upper piece () join ()//
Chris@16 1661 pred1 = pred; ++pred1;
Chris@16 1662 assert(pred1 != tailMap_.end() &&
Chris@16 1663 ((pred1->second)->getOtherActiveTail() == pred->second));
Chris@16 1664 closePartialSimplePolygon(currentX, pred->second, pred1->second);
Chris@16 1665
Chris@16 1666 //just update the pred1 with ActiveTail<Unit>* = pfig//
Chris@16 1667 pred1->second = pfig;
Chris@16 1668 pfig->pushCoordinate(currentX);
Chris@16 1669 pfig->pushCoordinate(pred1->first);
Chris@16 1670 }else{
Chris@16 1671 //cut both and create an left edge between (pred->first, succ1)//
Chris@16 1672 succ1 = succ; --succ1;
Chris@16 1673 pred1 = pred; ++pred1;
Chris@16 1674 assert(pred1 != tailMap_.end() && succ1 != tailMap_.end());
Chris@16 1675 assert((pred1->second)->getOtherActiveTail() == pred->second);
Chris@16 1676 assert((succ1->second)->getOtherActiveTail() == succ->second);
Chris@16 1677
Chris@16 1678 closePartialSimplePolygon(currentX, succ1->second, succ->second);
Chris@16 1679 closePartialSimplePolygon(currentX, pred->second, pred1->second);
Chris@16 1680
Chris@16 1681 tailPair = createActiveTailsAsPair<Unit>(currentX, succ1->first,
Chris@16 1682 true, NULL, fractureHoles_);
Chris@16 1683 succ1->second = tailPair.second;
Chris@16 1684 pred1->second = tailPair.first;
Chris@16 1685 (tailPair.first)->pushCoordinate(pred1->first);
Chris@16 1686 }
Chris@16 1687 }else{
Chris@16 1688 //just join them with closing//
Chris@16 1689 pfig->pushCoordinate(currentX);
Chris@16 1690 ActiveTail<Unit>::joinChains(pfig, ppfig, true, outputPolygons_);
Chris@16 1691 }
Chris@16 1692 hint = pred; ++hint;
Chris@16 1693 tailMap_.erase(succ); tailMap_.erase(pred);
Chris@16 1694 }else if(succ == tailMap_.end() && pred != tailMap_.end()){ //CASE-2//
Chris@16 1695 //succ is missing in the map, first insert it into the map//
Chris@16 1696 tailPair = createActiveTailsAsPair<Unit>(currentX, begin, true, NULL,
Chris@16 1697 fractureHoles_);
Chris@16 1698 hint = pred; ++hint;
Chris@16 1699 hint = tailMap_.insert(hint, std::make_pair(begin, tailPair.second));
Chris@16 1700
Chris@16 1701 pfig = pred->second;
Chris@16 1702 pfig_size = pfig->getPolyLineSize() + 2;
Chris@16 1703 if(pfig_size >= vertexThreshold){
Chris@16 1704 //cut-off piece from [pred, pred1] , add [begin, pred1]//
Chris@16 1705 pred1 = pred; ++pred1;
Chris@16 1706 assert((pred1 != tailMap_.end()) &&
Chris@16 1707 ((pred1->second)->getOtherActiveTail() == pred->second));
Chris@16 1708 closePartialSimplePolygon(currentX, pred->second, pred1->second);
Chris@16 1709
Chris@16 1710 //update: we need left edge between (begin, pred1->first)//
Chris@16 1711 pred1->second = tailPair.first;
Chris@16 1712 (tailPair.first)->pushCoordinate(pred1->first);
Chris@16 1713 }else{
Chris@16 1714 //just join//
Chris@16 1715 ActiveTail<Unit>::joinChains(tailPair.first, pfig,
Chris@16 1716 true, outputPolygons_);
Chris@16 1717 }
Chris@16 1718 tailMap_.erase(pred);
Chris@16 1719 }else if(succ != tailMap_.end() && pred == tailMap_.end()){ //CASE-3//
Chris@16 1720 //pred is missing in the map, first insert it into the map//
Chris@16 1721 hint = succ; ++hint;
Chris@16 1722 hint = tailMap_.insert(hint, std::make_pair(end, (ActiveTail<Unit> *) NULL));
Chris@16 1723 pfig = succ->second;
Chris@16 1724 pfig_size = pfig->getPolyLineSize() + 2;
Chris@16 1725 if(pfig_size >= vertexThreshold){
Chris@16 1726 //this figure needs cutting here//
Chris@16 1727 succ1 = succ; --succ1;
Chris@16 1728 assert((succ1 != tailMap_.end()) &&
Chris@16 1729 (succ1->second == pfig->getOtherActiveTail()));
Chris@16 1730 ppfig = succ1->second;
Chris@16 1731 closePartialSimplePolygon(currentX, ppfig, pfig);
Chris@16 1732
Chris@16 1733 //update: we need a left edge between (succ1->first, end)//
Chris@16 1734 tailPair = createActiveTailsAsPair<Unit>(currentX, succ1->first,
Chris@16 1735 true, NULL, fractureHoles_);
Chris@16 1736 succ1->second = tailPair.second;
Chris@16 1737 hint->second = tailPair.first;
Chris@16 1738 (tailPair.first)->pushCoordinate(end);
Chris@16 1739 }else{
Chris@16 1740 //no cutting needed//
Chris@16 1741 hint->second = pfig;
Chris@16 1742 pfig->pushCoordinate(currentX);
Chris@16 1743 pfig->pushCoordinate(end);
Chris@16 1744 }
Chris@16 1745 tailMap_.erase(succ);
Chris@16 1746 }else{
Chris@16 1747 //insert both pred and succ//
Chris@16 1748 insertNewLeftEdgeIntoTailMap(currentX, begin, end, hint);
Chris@16 1749 }
Chris@16 1750 }
Chris@16 1751 }
Chris@16 1752
Chris@16 1753 template<bool orientT, typename Unit, typename polygon_concept_type>
Chris@16 1754 inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
Chris@16 1755 updatePartialSimplePolygonsWithRightEdges(Unit currentX,
Chris@16 1756 const std::vector<interval_data<Unit> > &rightEdges, size_t vertexThreshold)
Chris@16 1757 {
Chris@16 1758
Chris@16 1759 typename std::map<Unit, ActiveTail<Unit>* >::iterator succ, pred, hint;
Chris@16 1760 std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair;
Chris@16 1761 Unit begin, end;
Chris@16 1762 size_t i = 0;
Chris@16 1763 //If rightEdges is non-empty Then tailMap_ is non-empty //
Chris@16 1764 assert(rightEdges.empty() || !tailMap_.empty() );
Chris@16 1765
Chris@16 1766 while( i < rightEdges.size() ){
Chris@16 1767 //find the interval in the tailMap which contains this interval//
Chris@16 1768 pred = tailMap_.lower_bound(rightEdges[i].get(HIGH));
Chris@16 1769 assert(pred != tailMap_.end());
Chris@16 1770 succ = pred; --succ;
Chris@16 1771 assert(pred != succ);
Chris@16 1772 end = pred->first; begin = succ->first;
Chris@16 1773
Chris@16 1774 //we now have a [begin, end] //
Chris@16 1775 bool found_solid_opening = false;
Chris@16 1776 bool erase_succ = true, erase_pred = true;
Chris@16 1777 Unit solid_opening_begin = 0;
Chris@16 1778 Unit solid_opening_end = 0;
Chris@16 1779 size_t j = i+1;
Chris@16 1780 ActiveTail<Unit> *pfig = succ->second;
Chris@16 1781 ActiveTail<Unit> *ppfig = pred->second;
Chris@16 1782 size_t partial_fig_size = pfig->getPolyLineSize();
Chris@16 1783 //Invariant://
Chris@16 1784 assert(succ->second && (pfig)->getOtherActiveTail() == ppfig);
Chris@16 1785
Chris@16 1786 hint = succ;
Chris@16 1787 Unit key = rightEdges[i].get(LOW);
Chris@16 1788 if(begin != key){
Chris@16 1789 found_solid_opening = true;
Chris@16 1790 solid_opening_begin = begin; solid_opening_end = key;
Chris@16 1791 }
Chris@16 1792
Chris@16 1793 while(j < rightEdges.size() && rightEdges[j].get(HIGH) <= end){
Chris@16 1794 if(rightEdges[j-1].get(HIGH) != rightEdges[j].get(LOW)){
Chris@16 1795 if(!found_solid_opening){
Chris@16 1796 found_solid_opening = true;
Chris@16 1797 solid_opening_begin = rightEdges[j-1].get(HIGH);
Chris@16 1798 solid_opening_end = rightEdges[j].get(LOW);
Chris@16 1799 }else{
Chris@16 1800 ++hint;
Chris@16 1801 insertNewLeftEdgeIntoTailMap(currentX,
Chris@16 1802 rightEdges[j-1].get(HIGH), rightEdges[j].get(LOW), hint);
Chris@16 1803 }
Chris@16 1804 }
Chris@16 1805 j++;
Chris@16 1806 }
Chris@16 1807
Chris@16 1808 //trailing edge//
Chris@16 1809 if(end != rightEdges[j-1].get(HIGH)){
Chris@16 1810 if(!found_solid_opening){
Chris@16 1811 found_solid_opening = true;
Chris@16 1812 solid_opening_begin = rightEdges[j-1].get(HIGH); solid_opening_end = end;
Chris@16 1813 }else{
Chris@16 1814 // a solid opening has been found already, we need to insert a new left
Chris@16 1815 // between [rightEdges[j-1].get(HIGH), end]
Chris@16 1816 Unit lbegin = rightEdges[j-1].get(HIGH);
Chris@16 1817 tailPair = createActiveTailsAsPair<Unit>(currentX, lbegin, true, NULL,
Chris@16 1818 fractureHoles_);
Chris@16 1819 hint = tailMap_.insert(pred, std::make_pair(lbegin, tailPair.second));
Chris@16 1820 pred->second = tailPair.first;
Chris@16 1821 (tailPair.first)->pushCoordinate(end);
Chris@16 1822 erase_pred = false;
Chris@16 1823 }
Chris@16 1824 }
Chris@16 1825
Chris@16 1826 size_t vertex_delta = ((begin != solid_opening_begin) &&
Chris@16 1827 (end != solid_opening_end)) ? 4 : 2;
Chris@16 1828
Chris@16 1829 if(!found_solid_opening){
Chris@16 1830 //just close the figure, TODO: call closePartialPolygon//
Chris@16 1831 pfig->pushCoordinate(currentX);
Chris@16 1832 ActiveTail<Unit>::joinChains(pfig, ppfig, false, outputPolygons_);
Chris@16 1833 hint = pred; ++hint;
Chris@16 1834 }else if(partial_fig_size+vertex_delta >= vertexThreshold){
Chris@16 1835 //close the figure and add a pseudo left-edge//
Chris@16 1836 closePartialSimplePolygon(currentX, pfig, ppfig);
Chris@16 1837 assert(begin != solid_opening_begin || end != solid_opening_end);
Chris@16 1838
Chris@16 1839 if(begin != solid_opening_begin && end != solid_opening_end){
Chris@16 1840 insertNewLeftEdgeIntoTailMap(currentX, solid_opening_begin,
Chris@16 1841 solid_opening_end, hint);
Chris@16 1842 }else if(begin == solid_opening_begin){
Chris@16 1843 //we just need to update the succ in the tailMap_//
Chris@16 1844 tailPair = createActiveTailsAsPair<Unit>(currentX, solid_opening_begin,
Chris@16 1845 true, NULL, fractureHoles_);
Chris@16 1846 succ->second = tailPair.second;
Chris@16 1847 hint = succ; ++hint;
Chris@16 1848 hint = tailMap_.insert(pred, std::make_pair(solid_opening_end,
Chris@16 1849 tailPair.first));
Chris@16 1850 (tailPair.first)->pushCoordinate(solid_opening_end);
Chris@16 1851 erase_succ = false;
Chris@16 1852 }else{
Chris@16 1853 //we just need to update the pred in the tailMap_//
Chris@16 1854 tailPair = createActiveTailsAsPair<Unit>(currentX, solid_opening_begin,
Chris@16 1855 true, NULL, fractureHoles_);
Chris@16 1856 hint = tailMap_.insert(pred, std::make_pair(solid_opening_begin,
Chris@16 1857 tailPair.second));
Chris@16 1858 pred->second = tailPair.first;
Chris@16 1859 (tailPair.first)->pushCoordinate(solid_opening_end);
Chris@16 1860 erase_pred = false;
Chris@16 1861 }
Chris@16 1862 }else{
Chris@16 1863 //continue the figure (by adding at-most two new vertices)//
Chris@16 1864 if(begin != solid_opening_begin){
Chris@16 1865 pfig->pushCoordinate(currentX);
Chris@16 1866 pfig->pushCoordinate(solid_opening_begin);
Chris@16 1867 //insert solid_opening_begin//
Chris@16 1868 hint = succ; ++hint;
Chris@16 1869 hint = tailMap_.insert(hint, std::make_pair(solid_opening_begin, pfig));
Chris@16 1870 }else{
Chris@16 1871 erase_succ = false;
Chris@16 1872 }
Chris@16 1873
Chris@16 1874 if(end != solid_opening_end){
Chris@16 1875 std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair =
Chris@16 1876 createActiveTailsAsPair<Unit>(currentX, solid_opening_end, false,
Chris@16 1877 NULL, fractureHoles_);
Chris@16 1878 hint = pred; ++hint;
Chris@16 1879 hint = tailMap_.insert(hint, std::make_pair(solid_opening_end,
Chris@16 1880 tailPair.second));
Chris@16 1881 ActiveTail<Unit>::joinChains(tailPair.first, ppfig, false,
Chris@16 1882 outputPolygons_);
Chris@16 1883 }else{
Chris@16 1884 erase_pred = false;
Chris@16 1885 }
Chris@16 1886 }
Chris@16 1887
Chris@16 1888 //Remove the pred and succ if necessary//
Chris@16 1889 if(erase_succ){
Chris@16 1890 tailMap_.erase(succ);
Chris@16 1891 }
Chris@16 1892 if(erase_pred){
Chris@16 1893 tailMap_.erase(pred);
Chris@16 1894 }
Chris@16 1895 i = j;
Chris@16 1896 }
Chris@16 1897 }
Chris@16 1898
Chris@16 1899 // Maintains the following invariant:
Chris@16 1900 // a. All the partial polygons formed at any state can be closed
Chris@16 1901 // by a single edge.
Chris@16 1902 template<bool orientT, typename Unit, typename polygon_concept_type>
Chris@16 1903 inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
Chris@16 1904 maintainPartialSimplePolygonInvariant(iterator& beginOutput,
Chris@16 1905 iterator& endOutput, Unit currentX, const std::vector<interval_data<Unit> >& l,
Chris@16 1906 const std::vector<interval_data<Unit> >& r, size_t vertexThreshold) {
Chris@16 1907
Chris@16 1908 clearOutput_();
Chris@16 1909 if(!l.empty()){
Chris@16 1910 updatePartialSimplePolygonsWithLeftEdges(currentX, l, vertexThreshold);
Chris@16 1911 }
Chris@16 1912
Chris@16 1913 if(!r.empty()){
Chris@16 1914 updatePartialSimplePolygonsWithRightEdges(currentX, r, vertexThreshold);
Chris@16 1915 }
Chris@16 1916 beginOutput = outputPolygons_.begin();
Chris@16 1917 endOutput = outputPolygons_.end();
Chris@16 1918
Chris@16 1919 }
Chris@16 1920
Chris@16 1921 //Process edges connects vertical input edges (right or left edges of figures) to horizontal edges stored as member
Chris@16 1922 //data of the scanline object. It also creates now horizontal edges as needed to construct figures from edge data.
Chris@16 1923 //
Chris@16 1924 //There are only 12 geometric end cases where the scanline intersects a horizontal edge and even fewer unique
Chris@16 1925 //actions to take:
Chris@16 1926 // 1. Solid on both sides of the vertical partition after the current position and space on both sides before
Chris@16 1927 // ###|###
Chris@16 1928 // ###|###
Chris@16 1929 // |
Chris@16 1930 // |
Chris@16 1931 // This case does not need to be handled because there is no vertical edge at the current x coordinate.
Chris@16 1932 //
Chris@16 1933 // 2. Solid on both sides of the vertical partition before the current position and space on both sides after
Chris@16 1934 // |
Chris@16 1935 // |
Chris@16 1936 // ###|###
Chris@16 1937 // ###|###
Chris@16 1938 // This case does not need to be handled because there is no vertical edge at the current x coordinate.
Chris@16 1939 //
Chris@16 1940 // 3. Solid on the left of the vertical partition after the current position and space elsewhere
Chris@16 1941 // ###|
Chris@16 1942 // ###|
Chris@16 1943 // |
Chris@16 1944 // |
Chris@16 1945 // The horizontal edge from the left is found and turns upward because of the vertical right edge to become
Chris@16 1946 // the currently active vertical edge.
Chris@16 1947 //
Chris@16 1948 // 4. Solid on the left of the vertical partion before the current position and space elsewhere
Chris@16 1949 // |
Chris@16 1950 // |
Chris@16 1951 // ###|
Chris@16 1952 // ###|
Chris@16 1953 // The horizontal edge from the left is found and joined to the currently active vertical edge.
Chris@16 1954 //
Chris@16 1955 // 5. Solid to the right above and below and solid to the left above current position.
Chris@16 1956 // ###|###
Chris@16 1957 // ###|###
Chris@16 1958 // |###
Chris@16 1959 // |###
Chris@16 1960 // The horizontal edge from the left is found and joined to the currently active vertical edge,
Chris@16 1961 // potentially closing a hole.
Chris@16 1962 //
Chris@16 1963 // 6. Solid on the left of the vertical partion before the current position and solid to the right above and below
Chris@16 1964 // |###
Chris@16 1965 // |###
Chris@16 1966 // ###|###
Chris@16 1967 // ###|###
Chris@16 1968 // The horizontal edge from the left is found and turns upward because of the vertical right edge to become
Chris@16 1969 // the currently active vertical edge.
Chris@16 1970 //
Chris@16 1971 // 7. Solid on the right of the vertical partition after the current position and space elsewhere
Chris@16 1972 // |###
Chris@16 1973 // |###
Chris@16 1974 // |
Chris@16 1975 // |
Chris@16 1976 // Create two new ActiveTails, one is added to the horizontal edges and the other becomes the vertical currentTail
Chris@16 1977 //
Chris@16 1978 // 8. Solid on the right of the vertical partion before the current position and space elsewhere
Chris@16 1979 // |
Chris@16 1980 // |
Chris@16 1981 // |###
Chris@16 1982 // |###
Chris@16 1983 // The currentTail vertical edge turns right and is added to the horizontal edges data
Chris@16 1984 //
Chris@16 1985 // 9. Solid to the right above and solid to the left above and below current position.
Chris@16 1986 // ###|###
Chris@16 1987 // ###|###
Chris@16 1988 // ###|
Chris@16 1989 // ###|
Chris@16 1990 // The currentTail vertical edge turns right and is added to the horizontal edges data
Chris@16 1991 //
Chris@16 1992 // 10. Solid on the left of the vertical partion above and below the current position and solid to the right below
Chris@16 1993 // ###|
Chris@16 1994 // ###|
Chris@16 1995 // ###|###
Chris@16 1996 // ###|###
Chris@16 1997 // Create two new ActiveTails, one is added to the horizontal edges data and the other becomes the vertical currentTail
Chris@16 1998 //
Chris@16 1999 // 11. Solid to the right above and solid to the left below current position.
Chris@16 2000 // |###
Chris@16 2001 // |###
Chris@16 2002 // ###|
Chris@16 2003 // ###|
Chris@16 2004 // The currentTail vertical edge joins the horizontal edge from the left (may close a polygon)
Chris@16 2005 // Create two new ActiveTails, one is added to the horizontal edges data and the other becomes the vertical currentTail
Chris@16 2006 //
Chris@16 2007 // 12. Solid on the left of the vertical partion above the current position and solid to the right below
Chris@16 2008 // ###|
Chris@16 2009 // ###|
Chris@16 2010 // |###
Chris@16 2011 // |###
Chris@16 2012 // The currentTail vertical edge turns right and is added to the horizontal edges data.
Chris@16 2013 // The horizontal edge from the left turns upward and becomes the currentTail vertical edge
Chris@16 2014 //
Chris@16 2015 template <bool orientT, typename Unit, typename polygon_concept_type>
Chris@16 2016 inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
Chris@16 2017 processEdges(iterator& beginOutput, iterator& endOutput,
Chris@16 2018 Unit currentX, std::vector<interval_data<Unit> >& leftEdges,
Chris@16 2019 std::vector<interval_data<Unit> >& rightEdges,
Chris@16 2020 size_t vertexThreshold) {
Chris@16 2021 clearOutput_();
Chris@16 2022 typename std::map<Unit, ActiveTail<Unit>*>::iterator nextMapItr;
Chris@16 2023 //foreach edge
Chris@16 2024 unsigned int leftIndex = 0;
Chris@16 2025 unsigned int rightIndex = 0;
Chris@16 2026 bool bottomAlreadyProcessed = false;
Chris@16 2027 ActiveTail<Unit>* currentTail = 0;
Chris@16 2028 const Unit UnitMax = (std::numeric_limits<Unit>::max)();
Chris@16 2029
Chris@16 2030 if(vertexThreshold < (std::numeric_limits<size_t>::max)()){
Chris@16 2031 maintainPartialSimplePolygonInvariant(beginOutput, endOutput, currentX,
Chris@16 2032 leftEdges, rightEdges, vertexThreshold);
Chris@16 2033 return;
Chris@16 2034 }
Chris@16 2035
Chris@16 2036 nextMapItr = tailMap_.begin();
Chris@16 2037 while(leftIndex < leftEdges.size() || rightIndex < rightEdges.size()) {
Chris@16 2038 interval_data<Unit> edges[2] = {interval_data<Unit> (UnitMax, UnitMax),
Chris@16 2039 interval_data<Unit> (UnitMax, UnitMax)};
Chris@16 2040 bool haveNextEdge = true;
Chris@16 2041 if(leftIndex < leftEdges.size())
Chris@16 2042 edges[0] = leftEdges[leftIndex];
Chris@16 2043 else
Chris@16 2044 haveNextEdge = false;
Chris@16 2045 if(rightIndex < rightEdges.size())
Chris@16 2046 edges[1] = rightEdges[rightIndex];
Chris@16 2047 else
Chris@16 2048 haveNextEdge = false;
Chris@16 2049 bool trailingEdge = edges[1].get(LOW) < edges[0].get(LOW);
Chris@16 2050 interval_data<Unit> & edge = edges[trailingEdge];
Chris@16 2051 interval_data<Unit> & nextEdge = edges[!trailingEdge];
Chris@16 2052 //process this edge
Chris@16 2053 if(!bottomAlreadyProcessed) {
Chris@16 2054 //assert currentTail = 0
Chris@16 2055
Chris@16 2056 //process the bottom end of this edge
Chris@16 2057 typename std::map<Unit, ActiveTail<Unit>*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(LOW));
Chris@16 2058 if(thisMapItr != tailMap_.end()) {
Chris@16 2059 //there is an edge in the map at the low end of this edge
Chris@16 2060 //it needs to turn upward and become the current tail
Chris@16 2061 ActiveTail<Unit>* tail = thisMapItr->second;
Chris@16 2062 if(currentTail) {
Chris@16 2063 //stitch currentTail into this tail
Chris@16 2064 currentTail = tail->addHole(currentTail, fractureHoles_);
Chris@16 2065 if(!fractureHoles_)
Chris@16 2066 currentTail->pushCoordinate(currentX);
Chris@16 2067 } else {
Chris@16 2068 currentTail = tail;
Chris@16 2069 currentTail->pushCoordinate(currentX);
Chris@16 2070 }
Chris@16 2071 //assert currentTail->getOrient() == VERTICAL
Chris@16 2072 nextMapItr = thisMapItr; //set nextMapItr to the next position after this one
Chris@16 2073 ++nextMapItr;
Chris@16 2074 //remove thisMapItr from the map
Chris@16 2075 tailMap_.erase(thisMapItr);
Chris@16 2076 } else {
Chris@16 2077 //there is no edge in the map at the low end of this edge
Chris@16 2078 //we need to create one and another one to be the current vertical tail
Chris@16 2079 //if this is a trailing edge then there is space to the right of the vertical edge
Chris@16 2080 //so pass the inverse of trailingEdge to indicate solid to the right
Chris@16 2081 std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair =
Chris@16 2082 createActiveTailsAsPair(currentX, edge.get(LOW), !trailingEdge, currentTail, fractureHoles_);
Chris@16 2083 currentTail = tailPair.first;
Chris@16 2084 tailMap_.insert(nextMapItr, std::pair<Unit, ActiveTail<Unit>*>(edge.get(LOW), tailPair.second));
Chris@16 2085 // leave nextMapItr unchanged
Chris@16 2086 }
Chris@16 2087
Chris@16 2088 }
Chris@16 2089 if(haveNextEdge && edge.get(HIGH) == nextEdge.get(LOW)) {
Chris@16 2090 //the top of this edge is equal to the bottom of the next edge, process them both
Chris@16 2091 bottomAlreadyProcessed = true;
Chris@16 2092 typename std::map<Unit, ActiveTail<Unit>*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(HIGH));
Chris@16 2093 if(thisMapItr == tailMap_.end()) //assert this should never happen
Chris@16 2094 return;
Chris@16 2095 if(trailingEdge) {
Chris@16 2096 //geometry at this position
Chris@16 2097 // |##
Chris@16 2098 // |##
Chris@16 2099 // -----
Chris@16 2100 // ##|
Chris@16 2101 // ##|
Chris@16 2102 //current tail should join thisMapItr tail
Chris@16 2103 ActiveTail<Unit>* tail = thisMapItr->second;
Chris@16 2104 //pass false because they are being joined because space is to the right and it will close a solid figure
Chris@16 2105 ActiveTail<Unit>::joinChains(currentTail, tail, false, outputPolygons_);
Chris@16 2106 //two new tails are created, the vertical becomes current tail, the horizontal becomes thisMapItr tail
Chris@16 2107 //pass true becuase they are created at the lower left corner of some solid
Chris@16 2108 //pass null because there is no hole pointer possible
Chris@16 2109 std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair =
Chris@16 2110 createActiveTailsAsPair<Unit>(currentX, edge.get(HIGH), true, 0, fractureHoles_);
Chris@16 2111 currentTail = tailPair.first;
Chris@16 2112 thisMapItr->second = tailPair.second;
Chris@16 2113 } else {
Chris@16 2114 //geometry at this position
Chris@16 2115 // ##|
Chris@16 2116 // ##|
Chris@16 2117 // -----
Chris@16 2118 // |##
Chris@16 2119 // |##
Chris@16 2120 //current tail should turn right
Chris@16 2121 currentTail->pushCoordinate(edge.get(HIGH));
Chris@16 2122 //thisMapItr tail should turn up
Chris@16 2123 thisMapItr->second->pushCoordinate(currentX);
Chris@16 2124 //thisMapItr tail becomes current tail and current tail becomes thisMapItr tail
Chris@16 2125 std::swap(currentTail, thisMapItr->second);
Chris@16 2126 }
Chris@16 2127 nextMapItr = thisMapItr; //set nextMapItr to the next position after this one
Chris@16 2128 ++nextMapItr;
Chris@16 2129 } else {
Chris@16 2130 //there is a gap between the top of this edge and the bottom of the next, process the top of this edge
Chris@16 2131 bottomAlreadyProcessed = false;
Chris@16 2132 //process the top of this edge
Chris@16 2133 typename std::map<Unit, ActiveTail<Unit>*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(HIGH));
Chris@16 2134 if(thisMapItr != tailMap_.end()) {
Chris@16 2135 //thisMapItr is pointing to a horizontal edge in the map at the top of this vertical edge
Chris@16 2136 //we need to join them and potentially close a figure
Chris@16 2137 //assert currentTail != 0
Chris@16 2138 ActiveTail<Unit>* tail = thisMapItr->second;
Chris@16 2139 //pass the opositve of trailing edge to mean that they are joined because of solid to the right
Chris@16 2140 currentTail = ActiveTail<Unit>::joinChains(currentTail, tail, !trailingEdge, outputPolygons_);
Chris@16 2141 nextMapItr = thisMapItr; //set nextMapItr to the next position after this one
Chris@16 2142 ++nextMapItr;
Chris@16 2143 if(currentTail) { //figure is not closed//
Chris@16 2144 Unit nextItrY = UnitMax;
Chris@16 2145 if(nextMapItr != tailMap_.end()) {
Chris@16 2146 nextItrY = nextMapItr->first;
Chris@16 2147 }
Chris@16 2148 //for it to be a hole this must have been a left edge
Chris@16 2149 Unit leftY = UnitMax;
Chris@16 2150 if(leftIndex + 1 < leftEdges.size())
Chris@16 2151 leftY = leftEdges[leftIndex+1].get(LOW);
Chris@16 2152 Unit rightY = nextEdge.get(LOW);
Chris@16 2153 if(!haveNextEdge || (nextItrY < leftY && nextItrY < rightY)) {
Chris@16 2154 //we need to add it to the next edge above it in the map
Chris@16 2155 tail = nextMapItr->second;
Chris@16 2156 tail = tail->addHole(currentTail, fractureHoles_);
Chris@16 2157 if(fractureHoles_) {
Chris@16 2158 //some small additional work stitching in the filament
Chris@16 2159 tail->pushCoordinate(nextItrY);
Chris@16 2160 nextMapItr->second = tail;
Chris@16 2161 }
Chris@16 2162 //set current tail to null
Chris@16 2163 currentTail = 0;
Chris@16 2164 }
Chris@16 2165 }
Chris@16 2166 //delete thisMapItr from the map
Chris@16 2167 tailMap_.erase(thisMapItr);
Chris@16 2168 } else {
Chris@16 2169 //currentTail must turn right and be added into the map
Chris@16 2170 currentTail->pushCoordinate(edge.get(HIGH));
Chris@16 2171 //assert currentTail->getOrient() == HORIZONTAL
Chris@16 2172 tailMap_.insert(nextMapItr, std::pair<Unit, ActiveTail<Unit>*>(edge.get(HIGH), currentTail));
Chris@16 2173 //set currentTail to null
Chris@16 2174 currentTail = 0;
Chris@16 2175 //leave nextMapItr unchanged, it is still next
Chris@16 2176 }
Chris@16 2177 }
Chris@16 2178
Chris@16 2179 //increment index
Chris@16 2180 leftIndex += !trailingEdge;
Chris@16 2181 rightIndex += trailingEdge;
Chris@16 2182 } //end while
Chris@16 2183 beginOutput = outputPolygons_.begin();
Chris@16 2184 endOutput = outputPolygons_.end();
Chris@16 2185 } //end function
Chris@16 2186
Chris@16 2187 template<bool orientT, typename Unit, typename polygon_concept_type>
Chris@16 2188 inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::clearOutput_() {
Chris@16 2189 for(std::size_t i = 0; i < outputPolygons_.size(); ++i) {
Chris@16 2190 ActiveTail<Unit>* at1 = outputPolygons_[i].yield();
Chris@16 2191 const std::list<ActiveTail<Unit>*>& holes = at1->getHoles();
Chris@16 2192 for(typename std::list<ActiveTail<Unit>*>::const_iterator litr = holes.begin(); litr != holes.end(); ++litr) {
Chris@16 2193 //delete the hole
Chris@16 2194 (*litr)->destroyContents();
Chris@16 2195 destroyActiveTail((*litr)->getOtherActiveTail());
Chris@16 2196 destroyActiveTail((*litr));
Chris@16 2197 }
Chris@16 2198 //delete the polygon
Chris@16 2199 at1->destroyContents();
Chris@16 2200 //at2 contents are the same as at1, so it should not destroy them
Chris@16 2201 destroyActiveTail((at1)->getOtherActiveTail());
Chris@16 2202 destroyActiveTail(at1);
Chris@16 2203 }
Chris@16 2204 outputPolygons_.clear();
Chris@16 2205 }
Chris@16 2206
Chris@16 2207 } //polygon_formation namespace
Chris@16 2208
Chris@16 2209 template <bool orientT, typename Unit>
Chris@16 2210 struct geometry_concept<polygon_formation::PolyLinePolygonWithHolesData<orientT, Unit> > {
Chris@16 2211 typedef polygon_90_with_holes_concept type;
Chris@16 2212 };
Chris@16 2213
Chris@16 2214 template <bool orientT, typename Unit>
Chris@16 2215 struct geometry_concept<polygon_formation::PolyLineHoleData<orientT, Unit> > {
Chris@16 2216 typedef polygon_90_concept type;
Chris@16 2217 };
Chris@16 2218
Chris@16 2219 //public API to access polygon formation algorithm
Chris@16 2220 template <typename output_container, typename iterator_type, typename concept_type>
Chris@16 2221 unsigned int get_polygons(output_container& container,
Chris@16 2222 iterator_type begin, iterator_type end, orientation_2d orient,
Chris@16 2223 bool fracture_holes, concept_type,
Chris@16 2224 size_t sliceThreshold = (std::numeric_limits<size_t>::max)() ) {
Chris@16 2225 typedef typename output_container::value_type polygon_type;
Chris@16 2226 typedef typename std::iterator_traits<iterator_type>::value_type::first_type coordinate_type;
Chris@16 2227 polygon_type poly;
Chris@16 2228 unsigned int countPolygons = 0;
Chris@16 2229 typedef typename geometry_concept<polygon_type>::type polygon_concept_type;
Chris@16 2230 polygon_formation::ScanLineToPolygonItrs<true, coordinate_type, polygon_concept_type> scanlineToPolygonItrsV(fracture_holes);
Chris@16 2231 polygon_formation::ScanLineToPolygonItrs<false, coordinate_type, polygon_concept_type> scanlineToPolygonItrsH(fracture_holes);
Chris@16 2232 std::vector<interval_data<coordinate_type> > leftEdges;
Chris@16 2233 std::vector<interval_data<coordinate_type> > rightEdges;
Chris@16 2234 coordinate_type prevPos = (std::numeric_limits<coordinate_type>::max)();
Chris@16 2235 coordinate_type prevY = (std::numeric_limits<coordinate_type>::max)();
Chris@16 2236 int count = 0;
Chris@16 2237 for(iterator_type itr = begin;
Chris@16 2238 itr != end; ++ itr) {
Chris@16 2239 coordinate_type pos = (*itr).first;
Chris@16 2240 if(pos != prevPos) {
Chris@16 2241 if(orient == VERTICAL) {
Chris@16 2242 typename polygon_formation::ScanLineToPolygonItrs<true, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd;
Chris@16 2243 scanlineToPolygonItrsV.processEdges(itrPoly, itrPolyEnd, prevPos,
Chris@16 2244 leftEdges, rightEdges, sliceThreshold);
Chris@16 2245 for( ; itrPoly != itrPolyEnd; ++ itrPoly) {
Chris@16 2246 ++countPolygons;
Chris@16 2247 assign(poly, *itrPoly);
Chris@16 2248 container.insert(container.end(), poly);
Chris@16 2249 }
Chris@16 2250 } else {
Chris@16 2251 typename polygon_formation::ScanLineToPolygonItrs<false, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd;
Chris@16 2252 scanlineToPolygonItrsH.processEdges(itrPoly, itrPolyEnd, prevPos,
Chris@16 2253 leftEdges, rightEdges, sliceThreshold);
Chris@16 2254 for( ; itrPoly != itrPolyEnd; ++ itrPoly) {
Chris@16 2255 ++countPolygons;
Chris@16 2256 assign(poly, *itrPoly);
Chris@16 2257 container.insert(container.end(), poly);
Chris@16 2258 }
Chris@16 2259 }
Chris@16 2260 leftEdges.clear();
Chris@16 2261 rightEdges.clear();
Chris@16 2262 prevPos = pos;
Chris@16 2263 prevY = (*itr).second.first;
Chris@16 2264 count = (*itr).second.second;
Chris@16 2265 continue;
Chris@16 2266 }
Chris@16 2267 coordinate_type y = (*itr).second.first;
Chris@16 2268 if(count != 0 && y != prevY) {
Chris@16 2269 std::pair<interval_data<coordinate_type>, int> element(interval_data<coordinate_type>(prevY, y), count);
Chris@16 2270 if(element.second == 1) {
Chris@16 2271 if(leftEdges.size() && leftEdges.back().high() == element.first.low()) {
Chris@16 2272 encompass(leftEdges.back(), element.first);
Chris@16 2273 } else {
Chris@16 2274 leftEdges.push_back(element.first);
Chris@16 2275 }
Chris@16 2276 } else {
Chris@16 2277 if(rightEdges.size() && rightEdges.back().high() == element.first.low()) {
Chris@16 2278 encompass(rightEdges.back(), element.first);
Chris@16 2279 } else {
Chris@16 2280 rightEdges.push_back(element.first);
Chris@16 2281 }
Chris@16 2282 }
Chris@16 2283
Chris@16 2284 }
Chris@16 2285 prevY = y;
Chris@16 2286 count += (*itr).second.second;
Chris@16 2287 }
Chris@16 2288 if(orient == VERTICAL) {
Chris@16 2289 typename polygon_formation::ScanLineToPolygonItrs<true, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd;
Chris@16 2290 scanlineToPolygonItrsV.processEdges(itrPoly, itrPolyEnd, prevPos, leftEdges, rightEdges, sliceThreshold);
Chris@16 2291 for( ; itrPoly != itrPolyEnd; ++ itrPoly) {
Chris@16 2292 ++countPolygons;
Chris@16 2293 assign(poly, *itrPoly);
Chris@16 2294 container.insert(container.end(), poly);
Chris@16 2295 }
Chris@16 2296 } else {
Chris@16 2297 typename polygon_formation::ScanLineToPolygonItrs<false, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd;
Chris@16 2298 scanlineToPolygonItrsH.processEdges(itrPoly, itrPolyEnd, prevPos, leftEdges, rightEdges, sliceThreshold);
Chris@16 2299
Chris@16 2300 for( ; itrPoly != itrPolyEnd; ++ itrPoly) {
Chris@16 2301 ++countPolygons;
Chris@16 2302 assign(poly, *itrPoly);
Chris@16 2303 container.insert(container.end(), poly);
Chris@16 2304 }
Chris@16 2305 }
Chris@16 2306 return countPolygons;
Chris@16 2307 }
Chris@16 2308
Chris@16 2309 }
Chris@16 2310 }
Chris@16 2311 #endif