polygon_formation.hpp 87 KB

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