clipper.cpp 135 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662
  1. /*******************************************************************************
  2. * *
  3. * Author : Angus Johnson *
  4. * Version : 6.4.2 *
  5. * Date : 27 February 2017 *
  6. * Website : http://www.angusj.com *
  7. * Copyright : Angus Johnson 2010-2017 *
  8. * *
  9. * License: *
  10. * Use, modification & distribution is subject to Boost Software License Ver 1. *
  11. * http://www.boost.org/LICENSE_1_0.txt *
  12. * *
  13. * Attributions: *
  14. * The code in this library is an extension of Bala Vatti's clipping algorithm: *
  15. * "A generic solution to polygon clipping" *
  16. * Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. *
  17. * http://portal.acm.org/citation.cfm?id=129906 *
  18. * *
  19. * Computer graphics and geometric modeling: implementation and algorithms *
  20. * By Max K. Agoston *
  21. * Springer; 1 edition (January 4, 2005) *
  22. * http://books.google.com/books?q=vatti+clipping+agoston *
  23. * *
  24. * See also: *
  25. * "Polygon Offsetting by Computing Winding Numbers" *
  26. * Paper no. DETC2005-85513 pp. 565-575 *
  27. * ASME 2005 International Design Engineering Technical Conferences *
  28. * and Computers and Information in Engineering Conference (IDETC/CIE2005) *
  29. * September 24-28, 2005 , Long Beach, California, USA *
  30. * http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
  31. * *
  32. *******************************************************************************/
  33. /*******************************************************************************
  34. * *
  35. * This is a translation of the Delphi Clipper library and the naming style *
  36. * used has retained a Delphi flavour. *
  37. * *
  38. *******************************************************************************/
  39. #include "clipper.hpp"
  40. #include <cmath>
  41. #include <vector>
  42. #include <algorithm>
  43. #include <stdexcept>
  44. #include <cstring>
  45. #include <cstdlib>
  46. #include <ostream>
  47. #include <functional>
  48. //Explicitly disables exceptions handling for target platform
  49. //#define CLIPPER_NOEXCEPTION
  50. #define CLIPPER_THROW(exception) std::abort()
  51. #define CLIPPER_TRY if(true)
  52. #define CLIPPER_CATCH(exception) if(false)
  53. #if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
  54. #ifndef CLIPPER_NOEXCEPTION
  55. #undef CLIPPER_THROW
  56. #define CLIPPER_THROW(exception) throw exception
  57. #undef CLIPPER_TRY
  58. #define CLIPPER_TRY try
  59. #undef CLIPPER_CATCH
  60. #define CLIPPER_CATCH(exception) catch(exception)
  61. #endif
  62. #endif
  63. //Optionally allows to override exception macros
  64. #if defined(CLIPPER_THROW_USER)
  65. #undef CLIPPER_THROW
  66. #define CLIPPER_THROW CLIPPER_THROW_USER
  67. #endif
  68. #if defined(CLIPPER_TRY_USER)
  69. #undef CLIPPER_TRY
  70. #define CLIPPER_TRY CLIPPER_TRY_USER
  71. #endif
  72. #if defined(CLIPPER_CATCH_USER)
  73. #undef CLIPPER_CATCH
  74. #define CLIPPER_CATCH CLIPPER_CATCH_USER
  75. #endif
  76. namespace ClipperLib {
  77. static double const pi = 3.141592653589793238;
  78. static double const two_pi = pi *2;
  79. static double const def_arc_tolerance = 0.25;
  80. enum Direction { dRightToLeft, dLeftToRight };
  81. static int const Unassigned = -1; //edge not currently 'owning' a solution
  82. static int const Skip = -2; //edge that would otherwise close a path
  83. #define HORIZONTAL (-1.0E+40)
  84. #define TOLERANCE (1.0e-20)
  85. #define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE))
  86. struct TEdge {
  87. IntPoint Bot;
  88. IntPoint Curr; //current (updated for every new scanbeam)
  89. IntPoint Top;
  90. double Dx;
  91. PolyType PolyTyp;
  92. EdgeSide Side; //side only refers to current side of solution poly
  93. int WindDelta; //1 or -1 depending on winding direction
  94. int WindCnt;
  95. int WindCnt2; //winding count of the opposite polytype
  96. int OutIdx;
  97. TEdge *Next;
  98. TEdge *Prev;
  99. TEdge *NextInLML;
  100. TEdge *NextInAEL;
  101. TEdge *PrevInAEL;
  102. TEdge *NextInSEL;
  103. TEdge *PrevInSEL;
  104. };
  105. struct IntersectNode {
  106. TEdge *Edge1;
  107. TEdge *Edge2;
  108. IntPoint Pt;
  109. };
  110. struct LocalMinimum {
  111. cInt Y;
  112. TEdge *LeftBound;
  113. TEdge *RightBound;
  114. };
  115. struct OutPt;
  116. //OutRec: contains a path in the clipping solution. Edges in the AEL will
  117. //carry a pointer to an OutRec when they are part of the clipping solution.
  118. struct OutRec {
  119. int Idx;
  120. bool IsHole;
  121. bool IsOpen;
  122. OutRec *FirstLeft; //see comments in clipper.pas
  123. PolyNode *PolyNd;
  124. OutPt *Pts;
  125. OutPt *BottomPt;
  126. };
  127. struct OutPt {
  128. int Idx;
  129. IntPoint Pt;
  130. OutPt *Next;
  131. OutPt *Prev;
  132. };
  133. struct Join {
  134. OutPt *OutPt1;
  135. OutPt *OutPt2;
  136. IntPoint OffPt;
  137. };
  138. struct LocMinSorter
  139. {
  140. inline bool operator()(const LocalMinimum& locMin1, const LocalMinimum& locMin2)
  141. {
  142. return locMin2.Y < locMin1.Y;
  143. }
  144. };
  145. //------------------------------------------------------------------------------
  146. //------------------------------------------------------------------------------
  147. inline cInt Round(double val)
  148. {
  149. if ((val < 0)) return static_cast<cInt>(val - 0.5);
  150. else return static_cast<cInt>(val + 0.5);
  151. }
  152. //------------------------------------------------------------------------------
  153. inline cInt Abs(cInt val)
  154. {
  155. return val < 0 ? -val : val;
  156. }
  157. //------------------------------------------------------------------------------
  158. // PolyTree methods ...
  159. //------------------------------------------------------------------------------
  160. void PolyTree::Clear()
  161. {
  162. for (PolyNodes::size_type i = 0; i < AllNodes.size(); ++i)
  163. delete AllNodes[i];
  164. AllNodes.resize(0);
  165. Childs.resize(0);
  166. }
  167. //------------------------------------------------------------------------------
  168. PolyNode* PolyTree::GetFirst() const
  169. {
  170. if (!Childs.empty())
  171. return Childs[0];
  172. else
  173. return 0;
  174. }
  175. //------------------------------------------------------------------------------
  176. int PolyTree::Total() const
  177. {
  178. int result = (int)AllNodes.size();
  179. //with negative offsets, ignore the hidden outer polygon ...
  180. if (result > 0 && Childs[0] != AllNodes[0]) result--;
  181. return result;
  182. }
  183. //------------------------------------------------------------------------------
  184. // PolyNode methods ...
  185. //------------------------------------------------------------------------------
  186. PolyNode::PolyNode(): Parent(0), Index(0), m_IsOpen(false)
  187. {
  188. }
  189. //------------------------------------------------------------------------------
  190. int PolyNode::ChildCount() const
  191. {
  192. return (int)Childs.size();
  193. }
  194. //------------------------------------------------------------------------------
  195. void PolyNode::AddChild(PolyNode& child)
  196. {
  197. unsigned cnt = (unsigned)Childs.size();
  198. Childs.push_back(&child);
  199. child.Parent = this;
  200. child.Index = cnt;
  201. }
  202. //------------------------------------------------------------------------------
  203. PolyNode* PolyNode::GetNext() const
  204. {
  205. if (!Childs.empty())
  206. return Childs[0];
  207. else
  208. return GetNextSiblingUp();
  209. }
  210. //------------------------------------------------------------------------------
  211. PolyNode* PolyNode::GetNextSiblingUp() const
  212. {
  213. if (!Parent) //protects against PolyTree.GetNextSiblingUp()
  214. return 0;
  215. else if (Index == Parent->Childs.size() - 1)
  216. return Parent->GetNextSiblingUp();
  217. else
  218. return Parent->Childs[Index + 1];
  219. }
  220. //------------------------------------------------------------------------------
  221. bool PolyNode::IsHole() const
  222. {
  223. bool result = true;
  224. PolyNode* node = Parent;
  225. while (node)
  226. {
  227. result = !result;
  228. node = node->Parent;
  229. }
  230. return result;
  231. }
  232. //------------------------------------------------------------------------------
  233. bool PolyNode::IsOpen() const
  234. {
  235. return m_IsOpen;
  236. }
  237. //------------------------------------------------------------------------------
  238. #ifndef use_int32
  239. //------------------------------------------------------------------------------
  240. // Int128 class (enables safe math on signed 64bit integers)
  241. // eg Int128 val1((long64)9223372036854775807); //ie 2^63 -1
  242. // Int128 val2((long64)9223372036854775807);
  243. // Int128 val3 = val1 * val2;
  244. // val3.AsString => "85070591730234615847396907784232501249" (8.5e+37)
  245. //------------------------------------------------------------------------------
  246. class Int128
  247. {
  248. public:
  249. ulong64 lo;
  250. long64 hi;
  251. Int128(long64 _lo = 0)
  252. {
  253. lo = (ulong64)_lo;
  254. if (_lo < 0) hi = -1; else hi = 0;
  255. }
  256. Int128(const Int128 &val): lo(val.lo), hi(val.hi){}
  257. Int128(const long64& _hi, const ulong64& _lo): lo(_lo), hi(_hi){}
  258. Int128& operator = (const long64 &val)
  259. {
  260. lo = (ulong64)val;
  261. if (val < 0) hi = -1; else hi = 0;
  262. return *this;
  263. }
  264. bool operator == (const Int128 &val) const
  265. {return (hi == val.hi && lo == val.lo);}
  266. bool operator != (const Int128 &val) const
  267. { return !(*this == val);}
  268. bool operator > (const Int128 &val) const
  269. {
  270. if (hi != val.hi)
  271. return hi > val.hi;
  272. else
  273. return lo > val.lo;
  274. }
  275. bool operator < (const Int128 &val) const
  276. {
  277. if (hi != val.hi)
  278. return hi < val.hi;
  279. else
  280. return lo < val.lo;
  281. }
  282. bool operator >= (const Int128 &val) const
  283. { return !(*this < val);}
  284. bool operator <= (const Int128 &val) const
  285. { return !(*this > val);}
  286. Int128& operator += (const Int128 &rhs)
  287. {
  288. hi += rhs.hi;
  289. lo += rhs.lo;
  290. if (lo < rhs.lo) hi++;
  291. return *this;
  292. }
  293. Int128 operator + (const Int128 &rhs) const
  294. {
  295. Int128 result(*this);
  296. result+= rhs;
  297. return result;
  298. }
  299. Int128& operator -= (const Int128 &rhs)
  300. {
  301. *this += -rhs;
  302. return *this;
  303. }
  304. Int128 operator - (const Int128 &rhs) const
  305. {
  306. Int128 result(*this);
  307. result -= rhs;
  308. return result;
  309. }
  310. Int128 operator-() const //unary negation
  311. {
  312. if (lo == 0)
  313. return Int128(-hi, 0);
  314. else
  315. return Int128(~hi, ~lo + 1);
  316. }
  317. operator double() const
  318. {
  319. const double shift64 = 18446744073709551616.0; //2^64
  320. if (hi < 0)
  321. {
  322. if (lo == 0) return (double)hi * shift64;
  323. else return -(double)(~lo + ~hi * shift64);
  324. }
  325. else
  326. return (double)(lo + hi * shift64);
  327. }
  328. };
  329. //------------------------------------------------------------------------------
  330. Int128 Int128Mul (long64 lhs, long64 rhs)
  331. {
  332. bool negate = (lhs < 0) != (rhs < 0);
  333. if (lhs < 0) lhs = -lhs;
  334. ulong64 int1Hi = ulong64(lhs) >> 32;
  335. ulong64 int1Lo = ulong64(lhs & 0xFFFFFFFF);
  336. if (rhs < 0) rhs = -rhs;
  337. ulong64 int2Hi = ulong64(rhs) >> 32;
  338. ulong64 int2Lo = ulong64(rhs & 0xFFFFFFFF);
  339. //nb: see comments in clipper.pas
  340. ulong64 a = int1Hi * int2Hi;
  341. ulong64 b = int1Lo * int2Lo;
  342. ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi;
  343. Int128 tmp;
  344. tmp.hi = long64(a + (c >> 32));
  345. tmp.lo = long64(c << 32);
  346. tmp.lo += long64(b);
  347. if (tmp.lo < b) tmp.hi++;
  348. if (negate) tmp = -tmp;
  349. return tmp;
  350. };
  351. #endif
  352. //------------------------------------------------------------------------------
  353. // Miscellaneous global functions
  354. //------------------------------------------------------------------------------
  355. bool Orientation(const Path &poly)
  356. {
  357. return Area(poly) >= 0;
  358. }
  359. //------------------------------------------------------------------------------
  360. double Area(const Path &poly)
  361. {
  362. int size = (int)poly.size();
  363. if (size < 3) return 0;
  364. double a = 0;
  365. for (int i = 0, j = size -1; i < size; ++i)
  366. {
  367. a += ((double)poly[j].X + poly[i].X) * ((double)poly[j].Y - poly[i].Y);
  368. j = i;
  369. }
  370. return -a * 0.5;
  371. }
  372. //------------------------------------------------------------------------------
  373. double Area(const OutPt *op)
  374. {
  375. const OutPt *startOp = op;
  376. if (!op) return 0;
  377. double a = 0;
  378. do {
  379. a += (double)(op->Prev->Pt.X + op->Pt.X) * (double)(op->Prev->Pt.Y - op->Pt.Y);
  380. op = op->Next;
  381. } while (op != startOp);
  382. return a * 0.5;
  383. }
  384. //------------------------------------------------------------------------------
  385. double Area(const OutRec &outRec)
  386. {
  387. return Area(outRec.Pts);
  388. }
  389. //------------------------------------------------------------------------------
  390. bool PointIsVertex(const IntPoint &Pt, OutPt *pp)
  391. {
  392. OutPt *pp2 = pp;
  393. do
  394. {
  395. if (pp2->Pt == Pt) return true;
  396. pp2 = pp2->Next;
  397. }
  398. while (pp2 != pp);
  399. return false;
  400. }
  401. //------------------------------------------------------------------------------
  402. //See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos
  403. //http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf
  404. int PointInPolygon(const IntPoint &pt, const Path &path)
  405. {
  406. //returns 0 if false, +1 if true, -1 if pt ON polygon boundary
  407. int result = 0;
  408. size_t cnt = path.size();
  409. if (cnt < 3) return 0;
  410. IntPoint ip = path[0];
  411. for(size_t i = 1; i <= cnt; ++i)
  412. {
  413. IntPoint ipNext = (i == cnt ? path[0] : path[i]);
  414. if (ipNext.Y == pt.Y)
  415. {
  416. if ((ipNext.X == pt.X) || (ip.Y == pt.Y &&
  417. ((ipNext.X > pt.X) == (ip.X < pt.X)))) return -1;
  418. }
  419. if ((ip.Y < pt.Y) != (ipNext.Y < pt.Y))
  420. {
  421. if (ip.X >= pt.X)
  422. {
  423. if (ipNext.X > pt.X) result = 1 - result;
  424. else
  425. {
  426. double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) -
  427. (double)(ipNext.X - pt.X) * (ip.Y - pt.Y);
  428. if (!d) return -1;
  429. if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result;
  430. }
  431. } else
  432. {
  433. if (ipNext.X > pt.X)
  434. {
  435. double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) -
  436. (double)(ipNext.X - pt.X) * (ip.Y - pt.Y);
  437. if (!d) return -1;
  438. if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result;
  439. }
  440. }
  441. }
  442. ip = ipNext;
  443. }
  444. return result;
  445. }
  446. //------------------------------------------------------------------------------
  447. int PointInPolygon (const IntPoint &pt, OutPt *op)
  448. {
  449. //returns 0 if false, +1 if true, -1 if pt ON polygon boundary
  450. int result = 0;
  451. OutPt* startOp = op;
  452. for(;;)
  453. {
  454. if (op->Next->Pt.Y == pt.Y)
  455. {
  456. if ((op->Next->Pt.X == pt.X) || (op->Pt.Y == pt.Y &&
  457. ((op->Next->Pt.X > pt.X) == (op->Pt.X < pt.X)))) return -1;
  458. }
  459. if ((op->Pt.Y < pt.Y) != (op->Next->Pt.Y < pt.Y))
  460. {
  461. if (op->Pt.X >= pt.X)
  462. {
  463. if (op->Next->Pt.X > pt.X) result = 1 - result;
  464. else
  465. {
  466. double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) -
  467. (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y);
  468. if (!d) return -1;
  469. if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result;
  470. }
  471. } else
  472. {
  473. if (op->Next->Pt.X > pt.X)
  474. {
  475. double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) -
  476. (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y);
  477. if (!d) return -1;
  478. if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result;
  479. }
  480. }
  481. }
  482. op = op->Next;
  483. if (startOp == op) break;
  484. }
  485. return result;
  486. }
  487. //------------------------------------------------------------------------------
  488. bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2)
  489. {
  490. OutPt* op = OutPt1;
  491. do
  492. {
  493. //nb: PointInPolygon returns 0 if false, +1 if true, -1 if pt on polygon
  494. int res = PointInPolygon(op->Pt, OutPt2);
  495. if (res >= 0) return res > 0;
  496. op = op->Next;
  497. }
  498. while (op != OutPt1);
  499. return true;
  500. }
  501. //----------------------------------------------------------------------
  502. bool SlopesEqual(const TEdge &e1, const TEdge &e2, bool UseFullInt64Range)
  503. {
  504. #ifndef use_int32
  505. if (UseFullInt64Range)
  506. return Int128Mul(e1.Top.Y - e1.Bot.Y, e2.Top.X - e2.Bot.X) ==
  507. Int128Mul(e1.Top.X - e1.Bot.X, e2.Top.Y - e2.Bot.Y);
  508. else
  509. #endif
  510. return (e1.Top.Y - e1.Bot.Y) * (e2.Top.X - e2.Bot.X) ==
  511. (e1.Top.X - e1.Bot.X) * (e2.Top.Y - e2.Bot.Y);
  512. }
  513. //------------------------------------------------------------------------------
  514. bool SlopesEqual(const IntPoint pt1, const IntPoint pt2,
  515. const IntPoint pt3, bool UseFullInt64Range)
  516. {
  517. #ifndef use_int32
  518. if (UseFullInt64Range)
  519. return Int128Mul(pt1.Y-pt2.Y, pt2.X-pt3.X) == Int128Mul(pt1.X-pt2.X, pt2.Y-pt3.Y);
  520. else
  521. #endif
  522. return (pt1.Y-pt2.Y)*(pt2.X-pt3.X) == (pt1.X-pt2.X)*(pt2.Y-pt3.Y);
  523. }
  524. //------------------------------------------------------------------------------
  525. bool SlopesEqual(const IntPoint pt1, const IntPoint pt2,
  526. const IntPoint pt3, const IntPoint pt4, bool UseFullInt64Range)
  527. {
  528. #ifndef use_int32
  529. if (UseFullInt64Range)
  530. return Int128Mul(pt1.Y-pt2.Y, pt3.X-pt4.X) == Int128Mul(pt1.X-pt2.X, pt3.Y-pt4.Y);
  531. else
  532. #endif
  533. return (pt1.Y-pt2.Y)*(pt3.X-pt4.X) == (pt1.X-pt2.X)*(pt3.Y-pt4.Y);
  534. }
  535. //------------------------------------------------------------------------------
  536. inline bool IsHorizontal(TEdge &e)
  537. {
  538. return e.Dx == HORIZONTAL;
  539. }
  540. //------------------------------------------------------------------------------
  541. inline double GetDx(const IntPoint pt1, const IntPoint pt2)
  542. {
  543. return (pt1.Y == pt2.Y) ?
  544. HORIZONTAL : (double)(pt2.X - pt1.X) / (pt2.Y - pt1.Y);
  545. }
  546. //---------------------------------------------------------------------------
  547. inline void SetDx(TEdge &e)
  548. {
  549. cInt dy = (e.Top.Y - e.Bot.Y);
  550. if (dy == 0) e.Dx = HORIZONTAL;
  551. else e.Dx = (double)(e.Top.X - e.Bot.X) / dy;
  552. }
  553. //---------------------------------------------------------------------------
  554. inline void SwapSides(TEdge &Edge1, TEdge &Edge2)
  555. {
  556. EdgeSide Side = Edge1.Side;
  557. Edge1.Side = Edge2.Side;
  558. Edge2.Side = Side;
  559. }
  560. //------------------------------------------------------------------------------
  561. inline void SwapPolyIndexes(TEdge &Edge1, TEdge &Edge2)
  562. {
  563. int OutIdx = Edge1.OutIdx;
  564. Edge1.OutIdx = Edge2.OutIdx;
  565. Edge2.OutIdx = OutIdx;
  566. }
  567. //------------------------------------------------------------------------------
  568. inline cInt TopX(TEdge &edge, const cInt currentY)
  569. {
  570. return ( currentY == edge.Top.Y ) ?
  571. edge.Top.X : edge.Bot.X + Round(edge.Dx *(currentY - edge.Bot.Y));
  572. }
  573. //------------------------------------------------------------------------------
  574. void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip)
  575. {
  576. #ifdef use_xyz
  577. ip.Z = 0;
  578. #endif
  579. double b1, b2;
  580. if (Edge1.Dx == Edge2.Dx)
  581. {
  582. ip.Y = Edge1.Curr.Y;
  583. ip.X = TopX(Edge1, ip.Y);
  584. return;
  585. }
  586. else if (Edge1.Dx == 0)
  587. {
  588. ip.X = Edge1.Bot.X;
  589. if (IsHorizontal(Edge2))
  590. ip.Y = Edge2.Bot.Y;
  591. else
  592. {
  593. b2 = Edge2.Bot.Y - (Edge2.Bot.X / Edge2.Dx);
  594. ip.Y = Round(ip.X / Edge2.Dx + b2);
  595. }
  596. }
  597. else if (Edge2.Dx == 0)
  598. {
  599. ip.X = Edge2.Bot.X;
  600. if (IsHorizontal(Edge1))
  601. ip.Y = Edge1.Bot.Y;
  602. else
  603. {
  604. b1 = Edge1.Bot.Y - (Edge1.Bot.X / Edge1.Dx);
  605. ip.Y = Round(ip.X / Edge1.Dx + b1);
  606. }
  607. }
  608. else
  609. {
  610. b1 = Edge1.Bot.X - Edge1.Bot.Y * Edge1.Dx;
  611. b2 = Edge2.Bot.X - Edge2.Bot.Y * Edge2.Dx;
  612. double q = (b2-b1) / (Edge1.Dx - Edge2.Dx);
  613. ip.Y = Round(q);
  614. if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx))
  615. ip.X = Round(Edge1.Dx * q + b1);
  616. else
  617. ip.X = Round(Edge2.Dx * q + b2);
  618. }
  619. if (ip.Y < Edge1.Top.Y || ip.Y < Edge2.Top.Y)
  620. {
  621. if (Edge1.Top.Y > Edge2.Top.Y)
  622. ip.Y = Edge1.Top.Y;
  623. else
  624. ip.Y = Edge2.Top.Y;
  625. if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx))
  626. ip.X = TopX(Edge1, ip.Y);
  627. else
  628. ip.X = TopX(Edge2, ip.Y);
  629. }
  630. //finally, don't allow 'ip' to be BELOW curr.Y (ie bottom of scanbeam) ...
  631. if (ip.Y > Edge1.Curr.Y)
  632. {
  633. ip.Y = Edge1.Curr.Y;
  634. //use the more vertical edge to derive X ...
  635. if (std::fabs(Edge1.Dx) > std::fabs(Edge2.Dx))
  636. ip.X = TopX(Edge2, ip.Y); else
  637. ip.X = TopX(Edge1, ip.Y);
  638. }
  639. }
  640. //------------------------------------------------------------------------------
  641. void ReversePolyPtLinks(OutPt *pp)
  642. {
  643. if (!pp) return;
  644. OutPt *pp1, *pp2;
  645. pp1 = pp;
  646. do {
  647. pp2 = pp1->Next;
  648. pp1->Next = pp1->Prev;
  649. pp1->Prev = pp2;
  650. pp1 = pp2;
  651. } while( pp1 != pp );
  652. }
  653. //------------------------------------------------------------------------------
  654. void DisposeOutPts(OutPt*& pp)
  655. {
  656. if (pp == 0) return;
  657. pp->Prev->Next = 0;
  658. while( pp )
  659. {
  660. OutPt *tmpPp = pp;
  661. pp = pp->Next;
  662. delete tmpPp;
  663. }
  664. }
  665. //------------------------------------------------------------------------------
  666. inline void InitEdge(TEdge* e, TEdge* eNext, TEdge* ePrev, const IntPoint& Pt)
  667. {
  668. std::memset(e, 0, sizeof(TEdge));
  669. e->Next = eNext;
  670. e->Prev = ePrev;
  671. e->Curr = Pt;
  672. e->OutIdx = Unassigned;
  673. }
  674. //------------------------------------------------------------------------------
  675. void InitEdge2(TEdge& e, PolyType Pt)
  676. {
  677. if (e.Curr.Y >= e.Next->Curr.Y)
  678. {
  679. e.Bot = e.Curr;
  680. e.Top = e.Next->Curr;
  681. } else
  682. {
  683. e.Top = e.Curr;
  684. e.Bot = e.Next->Curr;
  685. }
  686. SetDx(e);
  687. e.PolyTyp = Pt;
  688. }
  689. //------------------------------------------------------------------------------
  690. TEdge* RemoveEdge(TEdge* e)
  691. {
  692. //removes e from double_linked_list (but without removing from memory)
  693. e->Prev->Next = e->Next;
  694. e->Next->Prev = e->Prev;
  695. TEdge* result = e->Next;
  696. e->Prev = 0; //flag as removed (see ClipperBase.Clear)
  697. return result;
  698. }
  699. //------------------------------------------------------------------------------
  700. inline void ReverseHorizontal(TEdge &e)
  701. {
  702. //swap horizontal edges' Top and Bottom x's so they follow the natural
  703. //progression of the bounds - ie so their xbots will align with the
  704. //adjoining lower edge. [Helpful in the ProcessHorizontal() method.]
  705. std::swap(e.Top.X, e.Bot.X);
  706. #ifdef use_xyz
  707. std::swap(e.Top.Z, e.Bot.Z);
  708. #endif
  709. }
  710. //------------------------------------------------------------------------------
  711. void SwapPoints(IntPoint &pt1, IntPoint &pt2)
  712. {
  713. IntPoint tmp = pt1;
  714. pt1 = pt2;
  715. pt2 = tmp;
  716. }
  717. //------------------------------------------------------------------------------
  718. bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a,
  719. IntPoint pt2b, IntPoint &pt1, IntPoint &pt2)
  720. {
  721. //precondition: segments are Collinear.
  722. if (Abs(pt1a.X - pt1b.X) > Abs(pt1a.Y - pt1b.Y))
  723. {
  724. if (pt1a.X > pt1b.X) SwapPoints(pt1a, pt1b);
  725. if (pt2a.X > pt2b.X) SwapPoints(pt2a, pt2b);
  726. if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a;
  727. if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b;
  728. return pt1.X < pt2.X;
  729. } else
  730. {
  731. if (pt1a.Y < pt1b.Y) SwapPoints(pt1a, pt1b);
  732. if (pt2a.Y < pt2b.Y) SwapPoints(pt2a, pt2b);
  733. if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a;
  734. if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b;
  735. return pt1.Y > pt2.Y;
  736. }
  737. }
  738. //------------------------------------------------------------------------------
  739. bool FirstIsBottomPt(const OutPt* btmPt1, const OutPt* btmPt2)
  740. {
  741. OutPt *p = btmPt1->Prev;
  742. while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) p = p->Prev;
  743. double dx1p = std::fabs(GetDx(btmPt1->Pt, p->Pt));
  744. p = btmPt1->Next;
  745. while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) p = p->Next;
  746. double dx1n = std::fabs(GetDx(btmPt1->Pt, p->Pt));
  747. p = btmPt2->Prev;
  748. while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) p = p->Prev;
  749. double dx2p = std::fabs(GetDx(btmPt2->Pt, p->Pt));
  750. p = btmPt2->Next;
  751. while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) p = p->Next;
  752. double dx2n = std::fabs(GetDx(btmPt2->Pt, p->Pt));
  753. if (std::max(dx1p, dx1n) == std::max(dx2p, dx2n) &&
  754. std::min(dx1p, dx1n) == std::min(dx2p, dx2n))
  755. return Area(btmPt1) > 0; //if otherwise identical use orientation
  756. else
  757. return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n);
  758. }
  759. //------------------------------------------------------------------------------
  760. OutPt* GetBottomPt(OutPt *pp)
  761. {
  762. OutPt* dups = 0;
  763. OutPt* p = pp->Next;
  764. while (p != pp)
  765. {
  766. if (p->Pt.Y > pp->Pt.Y)
  767. {
  768. pp = p;
  769. dups = 0;
  770. }
  771. else if (p->Pt.Y == pp->Pt.Y && p->Pt.X <= pp->Pt.X)
  772. {
  773. if (p->Pt.X < pp->Pt.X)
  774. {
  775. dups = 0;
  776. pp = p;
  777. } else
  778. {
  779. if (p->Next != pp && p->Prev != pp) dups = p;
  780. }
  781. }
  782. p = p->Next;
  783. }
  784. if (dups)
  785. {
  786. //there appears to be at least 2 vertices at BottomPt so ...
  787. while (dups != p)
  788. {
  789. if (!FirstIsBottomPt(p, dups)) pp = dups;
  790. dups = dups->Next;
  791. while (dups->Pt != pp->Pt) dups = dups->Next;
  792. }
  793. }
  794. return pp;
  795. }
  796. //------------------------------------------------------------------------------
  797. bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1,
  798. const IntPoint pt2, const IntPoint pt3)
  799. {
  800. if ((pt1 == pt3) || (pt1 == pt2) || (pt3 == pt2))
  801. return false;
  802. else if (pt1.X != pt3.X)
  803. return (pt2.X > pt1.X) == (pt2.X < pt3.X);
  804. else
  805. return (pt2.Y > pt1.Y) == (pt2.Y < pt3.Y);
  806. }
  807. //------------------------------------------------------------------------------
  808. bool HorzSegmentsOverlap(cInt seg1a, cInt seg1b, cInt seg2a, cInt seg2b)
  809. {
  810. if (seg1a > seg1b) std::swap(seg1a, seg1b);
  811. if (seg2a > seg2b) std::swap(seg2a, seg2b);
  812. return (seg1a < seg2b) && (seg2a < seg1b);
  813. }
  814. //------------------------------------------------------------------------------
  815. // ClipperBase class methods ...
  816. //------------------------------------------------------------------------------
  817. ClipperBase::ClipperBase() //constructor
  818. {
  819. m_CurrentLM = m_MinimaList.begin(); //begin() == end() here
  820. m_UseFullRange = false;
  821. }
  822. //------------------------------------------------------------------------------
  823. ClipperBase::~ClipperBase() //destructor
  824. {
  825. Clear();
  826. }
  827. //------------------------------------------------------------------------------
  828. void RangeTest(const IntPoint& Pt, bool& useFullRange)
  829. {
  830. if (useFullRange)
  831. {
  832. if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange)
  833. CLIPPER_THROW(clipperException("Coordinate outside allowed range"));
  834. }
  835. else if (Pt.X > loRange|| Pt.Y > loRange || -Pt.X > loRange || -Pt.Y > loRange)
  836. {
  837. useFullRange = true;
  838. RangeTest(Pt, useFullRange);
  839. }
  840. }
  841. //------------------------------------------------------------------------------
  842. TEdge* FindNextLocMin(TEdge* E)
  843. {
  844. for (;;)
  845. {
  846. while (E->Bot != E->Prev->Bot || E->Curr == E->Top) E = E->Next;
  847. if (!IsHorizontal(*E) && !IsHorizontal(*E->Prev)) break;
  848. while (IsHorizontal(*E->Prev)) E = E->Prev;
  849. TEdge* E2 = E;
  850. while (IsHorizontal(*E)) E = E->Next;
  851. if (E->Top.Y == E->Prev->Bot.Y) continue; //ie just an intermediate horz.
  852. if (E2->Prev->Bot.X < E->Bot.X) E = E2;
  853. break;
  854. }
  855. return E;
  856. }
  857. //------------------------------------------------------------------------------
  858. TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward)
  859. {
  860. TEdge *Result = E;
  861. TEdge *Horz = 0;
  862. if (E->OutIdx == Skip)
  863. {
  864. //if edges still remain in the current bound beyond the skip edge then
  865. //create another LocMin and call ProcessBound once more
  866. if (NextIsForward)
  867. {
  868. while (E->Top.Y == E->Next->Bot.Y) E = E->Next;
  869. //don't include top horizontals when parsing a bound a second time,
  870. //they will be contained in the opposite bound ...
  871. while (E != Result && IsHorizontal(*E)) E = E->Prev;
  872. }
  873. else
  874. {
  875. while (E->Top.Y == E->Prev->Bot.Y) E = E->Prev;
  876. while (E != Result && IsHorizontal(*E)) E = E->Next;
  877. }
  878. if (E == Result)
  879. {
  880. if (NextIsForward) Result = E->Next;
  881. else Result = E->Prev;
  882. }
  883. else
  884. {
  885. //there are more edges in the bound beyond result starting with E
  886. if (NextIsForward)
  887. E = Result->Next;
  888. else
  889. E = Result->Prev;
  890. MinimaList::value_type locMin;
  891. locMin.Y = E->Bot.Y;
  892. locMin.LeftBound = 0;
  893. locMin.RightBound = E;
  894. E->WindDelta = 0;
  895. Result = ProcessBound(E, NextIsForward);
  896. m_MinimaList.push_back(locMin);
  897. }
  898. return Result;
  899. }
  900. TEdge *EStart;
  901. if (IsHorizontal(*E))
  902. {
  903. //We need to be careful with open paths because this may not be a
  904. //true local minima (ie E may be following a skip edge).
  905. //Also, consecutive horz. edges may start heading left before going right.
  906. if (NextIsForward)
  907. EStart = E->Prev;
  908. else
  909. EStart = E->Next;
  910. if (IsHorizontal(*EStart)) //ie an adjoining horizontal skip edge
  911. {
  912. if (EStart->Bot.X != E->Bot.X && EStart->Top.X != E->Bot.X)
  913. ReverseHorizontal(*E);
  914. }
  915. else if (EStart->Bot.X != E->Bot.X)
  916. ReverseHorizontal(*E);
  917. }
  918. EStart = E;
  919. if (NextIsForward)
  920. {
  921. while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip)
  922. Result = Result->Next;
  923. if (IsHorizontal(*Result) && Result->Next->OutIdx != Skip)
  924. {
  925. //nb: at the top of a bound, horizontals are added to the bound
  926. //only when the preceding edge attaches to the horizontal's left vertex
  927. //unless a Skip edge is encountered when that becomes the top divide
  928. Horz = Result;
  929. while (IsHorizontal(*Horz->Prev)) Horz = Horz->Prev;
  930. if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev;
  931. }
  932. while (E != Result)
  933. {
  934. E->NextInLML = E->Next;
  935. if (IsHorizontal(*E) && E != EStart &&
  936. E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E);
  937. E = E->Next;
  938. }
  939. if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X)
  940. ReverseHorizontal(*E);
  941. Result = Result->Next; //move to the edge just beyond current bound
  942. } else
  943. {
  944. while (Result->Top.Y == Result->Prev->Bot.Y && Result->Prev->OutIdx != Skip)
  945. Result = Result->Prev;
  946. if (IsHorizontal(*Result) && Result->Prev->OutIdx != Skip)
  947. {
  948. Horz = Result;
  949. while (IsHorizontal(*Horz->Next)) Horz = Horz->Next;
  950. if (Horz->Next->Top.X == Result->Prev->Top.X ||
  951. Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next;
  952. }
  953. while (E != Result)
  954. {
  955. E->NextInLML = E->Prev;
  956. if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X)
  957. ReverseHorizontal(*E);
  958. E = E->Prev;
  959. }
  960. if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X)
  961. ReverseHorizontal(*E);
  962. Result = Result->Prev; //move to the edge just beyond current bound
  963. }
  964. return Result;
  965. }
  966. //------------------------------------------------------------------------------
  967. bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
  968. {
  969. #ifdef use_lines
  970. if (!Closed && PolyTyp == ptClip)
  971. CLIPPER_THROW(clipperException("AddPath: Open paths must be subject."));
  972. #else
  973. if (!Closed)
  974. CLIPPER_THROW(clipperException("AddPath: Open paths have been disabled."));
  975. #endif
  976. int highI = (int)pg.size() -1;
  977. if (Closed) while (highI > 0 && (pg[highI] == pg[0])) --highI;
  978. while (highI > 0 && (pg[highI] == pg[highI -1])) --highI;
  979. if ((Closed && highI < 2) || (!Closed && highI < 1)) return false;
  980. //create a new edge array ...
  981. TEdge *edges = new TEdge [highI +1];
  982. bool IsFlat = true;
  983. //1. Basic (first) edge initialization ...
  984. CLIPPER_TRY
  985. {
  986. edges[1].Curr = pg[1];
  987. RangeTest(pg[0], m_UseFullRange);
  988. RangeTest(pg[highI], m_UseFullRange);
  989. InitEdge(&edges[0], &edges[1], &edges[highI], pg[0]);
  990. InitEdge(&edges[highI], &edges[0], &edges[highI-1], pg[highI]);
  991. for (int i = highI - 1; i >= 1; --i)
  992. {
  993. RangeTest(pg[i], m_UseFullRange);
  994. InitEdge(&edges[i], &edges[i+1], &edges[i-1], pg[i]);
  995. }
  996. }
  997. CLIPPER_CATCH(...)
  998. {
  999. delete [] edges;
  1000. CLIPPER_THROW(); //range test fails
  1001. }
  1002. TEdge *eStart = &edges[0];
  1003. //2. Remove duplicate vertices, and (when closed) collinear edges ...
  1004. TEdge *E = eStart, *eLoopStop = eStart;
  1005. for (;;)
  1006. {
  1007. //nb: allows matching start and end points when not Closed ...
  1008. if (E->Curr == E->Next->Curr && (Closed || E->Next != eStart))
  1009. {
  1010. if (E == E->Next) break;
  1011. if (E == eStart) eStart = E->Next;
  1012. E = RemoveEdge(E);
  1013. eLoopStop = E;
  1014. continue;
  1015. }
  1016. if (E->Prev == E->Next)
  1017. break; //only two vertices
  1018. else if (Closed &&
  1019. SlopesEqual(E->Prev->Curr, E->Curr, E->Next->Curr, m_UseFullRange) &&
  1020. (!m_PreserveCollinear ||
  1021. !Pt2IsBetweenPt1AndPt3(E->Prev->Curr, E->Curr, E->Next->Curr)))
  1022. {
  1023. //Collinear edges are allowed for open paths but in closed paths
  1024. //the default is to merge adjacent collinear edges into a single edge.
  1025. //However, if the PreserveCollinear property is enabled, only overlapping
  1026. //collinear edges (ie spikes) will be removed from closed paths.
  1027. if (E == eStart) eStart = E->Next;
  1028. E = RemoveEdge(E);
  1029. E = E->Prev;
  1030. eLoopStop = E;
  1031. continue;
  1032. }
  1033. E = E->Next;
  1034. if ((E == eLoopStop) || (!Closed && E->Next == eStart)) break;
  1035. }
  1036. if ((!Closed && (E == E->Next)) || (Closed && (E->Prev == E->Next)))
  1037. {
  1038. delete [] edges;
  1039. return false;
  1040. }
  1041. if (!Closed)
  1042. {
  1043. m_HasOpenPaths = true;
  1044. eStart->Prev->OutIdx = Skip;
  1045. }
  1046. //3. Do second stage of edge initialization ...
  1047. E = eStart;
  1048. do
  1049. {
  1050. InitEdge2(*E, PolyTyp);
  1051. E = E->Next;
  1052. if (IsFlat && E->Curr.Y != eStart->Curr.Y) IsFlat = false;
  1053. }
  1054. while (E != eStart);
  1055. //4. Finally, add edge bounds to LocalMinima list ...
  1056. //Totally flat paths must be handled differently when adding them
  1057. //to LocalMinima list to avoid endless loops etc ...
  1058. if (IsFlat)
  1059. {
  1060. if (Closed)
  1061. {
  1062. delete [] edges;
  1063. return false;
  1064. }
  1065. E->Prev->OutIdx = Skip;
  1066. MinimaList::value_type locMin;
  1067. locMin.Y = E->Bot.Y;
  1068. locMin.LeftBound = 0;
  1069. locMin.RightBound = E;
  1070. locMin.RightBound->Side = esRight;
  1071. locMin.RightBound->WindDelta = 0;
  1072. for (;;)
  1073. {
  1074. if (E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E);
  1075. if (E->Next->OutIdx == Skip) break;
  1076. E->NextInLML = E->Next;
  1077. E = E->Next;
  1078. }
  1079. m_MinimaList.push_back(locMin);
  1080. m_edges.push_back(edges);
  1081. return true;
  1082. }
  1083. m_edges.push_back(edges);
  1084. bool leftBoundIsForward;
  1085. TEdge* EMin = 0;
  1086. //workaround to avoid an endless loop in the while loop below when
  1087. //open paths have matching start and end points ...
  1088. if (E->Prev->Bot == E->Prev->Top) E = E->Next;
  1089. for (;;)
  1090. {
  1091. E = FindNextLocMin(E);
  1092. if (E == EMin) break;
  1093. else if (!EMin) EMin = E;
  1094. //E and E.Prev now share a local minima (left aligned if horizontal).
  1095. //Compare their slopes to find which starts which bound ...
  1096. MinimaList::value_type locMin;
  1097. locMin.Y = E->Bot.Y;
  1098. if (E->Dx < E->Prev->Dx)
  1099. {
  1100. locMin.LeftBound = E->Prev;
  1101. locMin.RightBound = E;
  1102. leftBoundIsForward = false; //Q.nextInLML = Q.prev
  1103. } else
  1104. {
  1105. locMin.LeftBound = E;
  1106. locMin.RightBound = E->Prev;
  1107. leftBoundIsForward = true; //Q.nextInLML = Q.next
  1108. }
  1109. if (!Closed) locMin.LeftBound->WindDelta = 0;
  1110. else if (locMin.LeftBound->Next == locMin.RightBound)
  1111. locMin.LeftBound->WindDelta = -1;
  1112. else locMin.LeftBound->WindDelta = 1;
  1113. locMin.RightBound->WindDelta = -locMin.LeftBound->WindDelta;
  1114. E = ProcessBound(locMin.LeftBound, leftBoundIsForward);
  1115. if (E->OutIdx == Skip) E = ProcessBound(E, leftBoundIsForward);
  1116. TEdge* E2 = ProcessBound(locMin.RightBound, !leftBoundIsForward);
  1117. if (E2->OutIdx == Skip) E2 = ProcessBound(E2, !leftBoundIsForward);
  1118. if (locMin.LeftBound->OutIdx == Skip)
  1119. locMin.LeftBound = 0;
  1120. else if (locMin.RightBound->OutIdx == Skip)
  1121. locMin.RightBound = 0;
  1122. m_MinimaList.push_back(locMin);
  1123. if (!leftBoundIsForward) E = E2;
  1124. }
  1125. return true;
  1126. }
  1127. //------------------------------------------------------------------------------
  1128. bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed)
  1129. {
  1130. bool result = false;
  1131. for (Paths::size_type i = 0; i < ppg.size(); ++i)
  1132. if (AddPath(ppg[i], PolyTyp, Closed)) result = true;
  1133. return result;
  1134. }
  1135. //------------------------------------------------------------------------------
  1136. void ClipperBase::Clear()
  1137. {
  1138. DisposeLocalMinimaList();
  1139. for (EdgeList::size_type i = 0; i < m_edges.size(); ++i)
  1140. {
  1141. TEdge* edges = m_edges[i];
  1142. delete [] edges;
  1143. }
  1144. m_edges.clear();
  1145. m_UseFullRange = false;
  1146. m_HasOpenPaths = false;
  1147. }
  1148. //------------------------------------------------------------------------------
  1149. void ClipperBase::Reset()
  1150. {
  1151. m_CurrentLM = m_MinimaList.begin();
  1152. if (m_CurrentLM == m_MinimaList.end()) return; //ie nothing to process
  1153. std::sort(m_MinimaList.begin(), m_MinimaList.end(), LocMinSorter());
  1154. m_Scanbeam = ScanbeamList(); //clears/resets priority_queue
  1155. //reset all edges ...
  1156. for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm)
  1157. {
  1158. InsertScanbeam(lm->Y);
  1159. TEdge* e = lm->LeftBound;
  1160. if (e)
  1161. {
  1162. e->Curr = e->Bot;
  1163. e->Side = esLeft;
  1164. e->OutIdx = Unassigned;
  1165. }
  1166. e = lm->RightBound;
  1167. if (e)
  1168. {
  1169. e->Curr = e->Bot;
  1170. e->Side = esRight;
  1171. e->OutIdx = Unassigned;
  1172. }
  1173. }
  1174. m_ActiveEdges = 0;
  1175. m_CurrentLM = m_MinimaList.begin();
  1176. }
  1177. //------------------------------------------------------------------------------
  1178. void ClipperBase::DisposeLocalMinimaList()
  1179. {
  1180. m_MinimaList.clear();
  1181. m_CurrentLM = m_MinimaList.begin();
  1182. }
  1183. //------------------------------------------------------------------------------
  1184. bool ClipperBase::PopLocalMinima(cInt Y, const LocalMinimum *&locMin)
  1185. {
  1186. if (m_CurrentLM == m_MinimaList.end() || (*m_CurrentLM).Y != Y) return false;
  1187. locMin = &(*m_CurrentLM);
  1188. ++m_CurrentLM;
  1189. return true;
  1190. }
  1191. //------------------------------------------------------------------------------
  1192. IntRect ClipperBase::GetBounds()
  1193. {
  1194. IntRect result;
  1195. MinimaList::iterator lm = m_MinimaList.begin();
  1196. if (lm == m_MinimaList.end())
  1197. {
  1198. result.left = result.top = result.right = result.bottom = 0;
  1199. return result;
  1200. }
  1201. result.left = lm->LeftBound->Bot.X;
  1202. result.top = lm->LeftBound->Bot.Y;
  1203. result.right = lm->LeftBound->Bot.X;
  1204. result.bottom = lm->LeftBound->Bot.Y;
  1205. while (lm != m_MinimaList.end())
  1206. {
  1207. //todo - needs fixing for open paths
  1208. result.bottom = std::max(result.bottom, lm->LeftBound->Bot.Y);
  1209. TEdge* e = lm->LeftBound;
  1210. for (;;) {
  1211. TEdge* bottomE = e;
  1212. while (e->NextInLML)
  1213. {
  1214. if (e->Bot.X < result.left) result.left = e->Bot.X;
  1215. if (e->Bot.X > result.right) result.right = e->Bot.X;
  1216. e = e->NextInLML;
  1217. }
  1218. result.left = std::min(result.left, e->Bot.X);
  1219. result.right = std::max(result.right, e->Bot.X);
  1220. result.left = std::min(result.left, e->Top.X);
  1221. result.right = std::max(result.right, e->Top.X);
  1222. result.top = std::min(result.top, e->Top.Y);
  1223. if (bottomE == lm->LeftBound) e = lm->RightBound;
  1224. else break;
  1225. }
  1226. ++lm;
  1227. }
  1228. return result;
  1229. }
  1230. //------------------------------------------------------------------------------
  1231. void ClipperBase::InsertScanbeam(const cInt Y)
  1232. {
  1233. m_Scanbeam.push(Y);
  1234. }
  1235. //------------------------------------------------------------------------------
  1236. bool ClipperBase::PopScanbeam(cInt &Y)
  1237. {
  1238. if (m_Scanbeam.empty()) return false;
  1239. Y = m_Scanbeam.top();
  1240. m_Scanbeam.pop();
  1241. while (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) { m_Scanbeam.pop(); } // Pop duplicates.
  1242. return true;
  1243. }
  1244. //------------------------------------------------------------------------------
  1245. void ClipperBase::DisposeAllOutRecs(){
  1246. for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
  1247. DisposeOutRec(i);
  1248. m_PolyOuts.clear();
  1249. }
  1250. //------------------------------------------------------------------------------
  1251. void ClipperBase::DisposeOutRec(PolyOutList::size_type index)
  1252. {
  1253. OutRec *outRec = m_PolyOuts[index];
  1254. if (outRec->Pts) DisposeOutPts(outRec->Pts);
  1255. delete outRec;
  1256. m_PolyOuts[index] = 0;
  1257. }
  1258. //------------------------------------------------------------------------------
  1259. void ClipperBase::DeleteFromAEL(TEdge *e)
  1260. {
  1261. TEdge* AelPrev = e->PrevInAEL;
  1262. TEdge* AelNext = e->NextInAEL;
  1263. if (!AelPrev && !AelNext && (e != m_ActiveEdges)) return; //already deleted
  1264. if (AelPrev) AelPrev->NextInAEL = AelNext;
  1265. else m_ActiveEdges = AelNext;
  1266. if (AelNext) AelNext->PrevInAEL = AelPrev;
  1267. e->NextInAEL = 0;
  1268. e->PrevInAEL = 0;
  1269. }
  1270. //------------------------------------------------------------------------------
  1271. OutRec* ClipperBase::CreateOutRec()
  1272. {
  1273. OutRec* result = new OutRec;
  1274. result->IsHole = false;
  1275. result->IsOpen = false;
  1276. result->FirstLeft = 0;
  1277. result->Pts = 0;
  1278. result->BottomPt = 0;
  1279. result->PolyNd = 0;
  1280. m_PolyOuts.push_back(result);
  1281. result->Idx = (int)m_PolyOuts.size() - 1;
  1282. return result;
  1283. }
  1284. //------------------------------------------------------------------------------
  1285. void ClipperBase::SwapPositionsInAEL(TEdge *Edge1, TEdge *Edge2)
  1286. {
  1287. //check that one or other edge hasn't already been removed from AEL ...
  1288. if (Edge1->NextInAEL == Edge1->PrevInAEL ||
  1289. Edge2->NextInAEL == Edge2->PrevInAEL) return;
  1290. if (Edge1->NextInAEL == Edge2)
  1291. {
  1292. TEdge* Next = Edge2->NextInAEL;
  1293. if (Next) Next->PrevInAEL = Edge1;
  1294. TEdge* Prev = Edge1->PrevInAEL;
  1295. if (Prev) Prev->NextInAEL = Edge2;
  1296. Edge2->PrevInAEL = Prev;
  1297. Edge2->NextInAEL = Edge1;
  1298. Edge1->PrevInAEL = Edge2;
  1299. Edge1->NextInAEL = Next;
  1300. }
  1301. else if (Edge2->NextInAEL == Edge1)
  1302. {
  1303. TEdge* Next = Edge1->NextInAEL;
  1304. if (Next) Next->PrevInAEL = Edge2;
  1305. TEdge* Prev = Edge2->PrevInAEL;
  1306. if (Prev) Prev->NextInAEL = Edge1;
  1307. Edge1->PrevInAEL = Prev;
  1308. Edge1->NextInAEL = Edge2;
  1309. Edge2->PrevInAEL = Edge1;
  1310. Edge2->NextInAEL = Next;
  1311. }
  1312. else
  1313. {
  1314. TEdge* Next = Edge1->NextInAEL;
  1315. TEdge* Prev = Edge1->PrevInAEL;
  1316. Edge1->NextInAEL = Edge2->NextInAEL;
  1317. if (Edge1->NextInAEL) Edge1->NextInAEL->PrevInAEL = Edge1;
  1318. Edge1->PrevInAEL = Edge2->PrevInAEL;
  1319. if (Edge1->PrevInAEL) Edge1->PrevInAEL->NextInAEL = Edge1;
  1320. Edge2->NextInAEL = Next;
  1321. if (Edge2->NextInAEL) Edge2->NextInAEL->PrevInAEL = Edge2;
  1322. Edge2->PrevInAEL = Prev;
  1323. if (Edge2->PrevInAEL) Edge2->PrevInAEL->NextInAEL = Edge2;
  1324. }
  1325. if (!Edge1->PrevInAEL) m_ActiveEdges = Edge1;
  1326. else if (!Edge2->PrevInAEL) m_ActiveEdges = Edge2;
  1327. }
  1328. //------------------------------------------------------------------------------
  1329. void ClipperBase::UpdateEdgeIntoAEL(TEdge *&e)
  1330. {
  1331. if (!e->NextInLML)
  1332. CLIPPER_THROW(clipperException("UpdateEdgeIntoAEL: invalid call"));
  1333. e->NextInLML->OutIdx = e->OutIdx;
  1334. TEdge* AelPrev = e->PrevInAEL;
  1335. TEdge* AelNext = e->NextInAEL;
  1336. if (AelPrev) AelPrev->NextInAEL = e->NextInLML;
  1337. else m_ActiveEdges = e->NextInLML;
  1338. if (AelNext) AelNext->PrevInAEL = e->NextInLML;
  1339. e->NextInLML->Side = e->Side;
  1340. e->NextInLML->WindDelta = e->WindDelta;
  1341. e->NextInLML->WindCnt = e->WindCnt;
  1342. e->NextInLML->WindCnt2 = e->WindCnt2;
  1343. e = e->NextInLML;
  1344. e->Curr = e->Bot;
  1345. e->PrevInAEL = AelPrev;
  1346. e->NextInAEL = AelNext;
  1347. if (!IsHorizontal(*e)) InsertScanbeam(e->Top.Y);
  1348. }
  1349. //------------------------------------------------------------------------------
  1350. bool ClipperBase::LocalMinimaPending()
  1351. {
  1352. return (m_CurrentLM != m_MinimaList.end());
  1353. }
  1354. //------------------------------------------------------------------------------
  1355. // TClipper methods ...
  1356. //------------------------------------------------------------------------------
  1357. Clipper::Clipper(int initOptions) : ClipperBase() //constructor
  1358. {
  1359. m_ExecuteLocked = false;
  1360. m_UseFullRange = false;
  1361. m_ReverseOutput = ((initOptions & ioReverseSolution) != 0);
  1362. m_StrictSimple = ((initOptions & ioStrictlySimple) != 0);
  1363. m_PreserveCollinear = ((initOptions & ioPreserveCollinear) != 0);
  1364. m_HasOpenPaths = false;
  1365. #ifdef use_xyz
  1366. m_ZFill = 0;
  1367. #endif
  1368. }
  1369. //------------------------------------------------------------------------------
  1370. #ifdef use_xyz
  1371. void Clipper::ZFillFunction(ZFillCallback zFillFunc)
  1372. {
  1373. m_ZFill = zFillFunc;
  1374. }
  1375. //------------------------------------------------------------------------------
  1376. #endif
  1377. bool Clipper::Execute(ClipType clipType, Paths &solution, PolyFillType fillType)
  1378. {
  1379. return Execute(clipType, solution, fillType, fillType);
  1380. }
  1381. //------------------------------------------------------------------------------
  1382. bool Clipper::Execute(ClipType clipType, PolyTree &polytree, PolyFillType fillType)
  1383. {
  1384. return Execute(clipType, polytree, fillType, fillType);
  1385. }
  1386. //------------------------------------------------------------------------------
  1387. bool Clipper::Execute(ClipType clipType, Paths &solution,
  1388. PolyFillType subjFillType, PolyFillType clipFillType)
  1389. {
  1390. if( m_ExecuteLocked ) return false;
  1391. if (m_HasOpenPaths)
  1392. CLIPPER_THROW(clipperException("Error: PolyTree struct is needed for open path clipping."));
  1393. m_ExecuteLocked = true;
  1394. solution.resize(0);
  1395. m_SubjFillType = subjFillType;
  1396. m_ClipFillType = clipFillType;
  1397. m_ClipType = clipType;
  1398. m_UsingPolyTree = false;
  1399. bool succeeded = ExecuteInternal();
  1400. if (succeeded) BuildResult(solution);
  1401. DisposeAllOutRecs();
  1402. m_ExecuteLocked = false;
  1403. return succeeded;
  1404. }
  1405. //------------------------------------------------------------------------------
  1406. bool Clipper::Execute(ClipType clipType, PolyTree& polytree,
  1407. PolyFillType subjFillType, PolyFillType clipFillType)
  1408. {
  1409. if( m_ExecuteLocked ) return false;
  1410. m_ExecuteLocked = true;
  1411. m_SubjFillType = subjFillType;
  1412. m_ClipFillType = clipFillType;
  1413. m_ClipType = clipType;
  1414. m_UsingPolyTree = true;
  1415. bool succeeded = ExecuteInternal();
  1416. if (succeeded) BuildResult2(polytree);
  1417. DisposeAllOutRecs();
  1418. m_ExecuteLocked = false;
  1419. return succeeded;
  1420. }
  1421. //------------------------------------------------------------------------------
  1422. void Clipper::FixHoleLinkage(OutRec &outrec)
  1423. {
  1424. //skip OutRecs that (a) contain outermost polygons or
  1425. //(b) already have the correct owner/child linkage ...
  1426. if (!outrec.FirstLeft ||
  1427. (outrec.IsHole != outrec.FirstLeft->IsHole &&
  1428. outrec.FirstLeft->Pts)) return;
  1429. OutRec* orfl = outrec.FirstLeft;
  1430. while (orfl && ((orfl->IsHole == outrec.IsHole) || !orfl->Pts))
  1431. orfl = orfl->FirstLeft;
  1432. outrec.FirstLeft = orfl;
  1433. }
  1434. //------------------------------------------------------------------------------
  1435. bool Clipper::ExecuteInternal()
  1436. {
  1437. bool succeeded = true;
  1438. CLIPPER_TRY {
  1439. Reset();
  1440. m_Maxima = MaximaList();
  1441. m_SortedEdges = 0;
  1442. succeeded = true;
  1443. cInt botY, topY;
  1444. if (!PopScanbeam(botY)) return false;
  1445. InsertLocalMinimaIntoAEL(botY);
  1446. while (PopScanbeam(topY) || LocalMinimaPending())
  1447. {
  1448. ProcessHorizontals();
  1449. ClearGhostJoins();
  1450. if (!ProcessIntersections(topY))
  1451. {
  1452. succeeded = false;
  1453. break;
  1454. }
  1455. ProcessEdgesAtTopOfScanbeam(topY);
  1456. botY = topY;
  1457. InsertLocalMinimaIntoAEL(botY);
  1458. }
  1459. }
  1460. CLIPPER_CATCH(...)
  1461. {
  1462. succeeded = false;
  1463. }
  1464. if (succeeded)
  1465. {
  1466. //fix orientations ...
  1467. for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
  1468. {
  1469. OutRec *outRec = m_PolyOuts[i];
  1470. if (!outRec->Pts || outRec->IsOpen) continue;
  1471. if ((outRec->IsHole ^ m_ReverseOutput) == (Area(*outRec) > 0))
  1472. ReversePolyPtLinks(outRec->Pts);
  1473. }
  1474. if (!m_Joins.empty()) JoinCommonEdges();
  1475. //unfortunately FixupOutPolygon() must be done after JoinCommonEdges()
  1476. for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
  1477. {
  1478. OutRec *outRec = m_PolyOuts[i];
  1479. if (!outRec->Pts) continue;
  1480. if (outRec->IsOpen)
  1481. FixupOutPolyline(*outRec);
  1482. else
  1483. FixupOutPolygon(*outRec);
  1484. }
  1485. if (m_StrictSimple) DoSimplePolygons();
  1486. }
  1487. ClearJoins();
  1488. ClearGhostJoins();
  1489. return succeeded;
  1490. }
  1491. //------------------------------------------------------------------------------
  1492. void Clipper::SetWindingCount(TEdge &edge)
  1493. {
  1494. TEdge *e = edge.PrevInAEL;
  1495. //find the edge of the same polytype that immediately preceeds 'edge' in AEL
  1496. while (e && ((e->PolyTyp != edge.PolyTyp) || (e->WindDelta == 0))) e = e->PrevInAEL;
  1497. if (!e)
  1498. {
  1499. if (edge.WindDelta == 0)
  1500. {
  1501. PolyFillType pft = (edge.PolyTyp == ptSubject ? m_SubjFillType : m_ClipFillType);
  1502. edge.WindCnt = (pft == pftNegative ? -1 : 1);
  1503. }
  1504. else
  1505. edge.WindCnt = edge.WindDelta;
  1506. edge.WindCnt2 = 0;
  1507. e = m_ActiveEdges; //ie get ready to calc WindCnt2
  1508. }
  1509. else if (edge.WindDelta == 0 && m_ClipType != ctUnion)
  1510. {
  1511. edge.WindCnt = 1;
  1512. edge.WindCnt2 = e->WindCnt2;
  1513. e = e->NextInAEL; //ie get ready to calc WindCnt2
  1514. }
  1515. else if (IsEvenOddFillType(edge))
  1516. {
  1517. //EvenOdd filling ...
  1518. if (edge.WindDelta == 0)
  1519. {
  1520. //are we inside a subj polygon ...
  1521. bool Inside = true;
  1522. TEdge *e2 = e->PrevInAEL;
  1523. while (e2)
  1524. {
  1525. if (e2->PolyTyp == e->PolyTyp && e2->WindDelta != 0)
  1526. Inside = !Inside;
  1527. e2 = e2->PrevInAEL;
  1528. }
  1529. edge.WindCnt = (Inside ? 0 : 1);
  1530. }
  1531. else
  1532. {
  1533. edge.WindCnt = edge.WindDelta;
  1534. }
  1535. edge.WindCnt2 = e->WindCnt2;
  1536. e = e->NextInAEL; //ie get ready to calc WindCnt2
  1537. }
  1538. else
  1539. {
  1540. //nonZero, Positive or Negative filling ...
  1541. if (e->WindCnt * e->WindDelta < 0)
  1542. {
  1543. //prev edge is 'decreasing' WindCount (WC) toward zero
  1544. //so we're outside the previous polygon ...
  1545. if (Abs(e->WindCnt) > 1)
  1546. {
  1547. //outside prev poly but still inside another.
  1548. //when reversing direction of prev poly use the same WC
  1549. if (e->WindDelta * edge.WindDelta < 0) edge.WindCnt = e->WindCnt;
  1550. //otherwise continue to 'decrease' WC ...
  1551. else edge.WindCnt = e->WindCnt + edge.WindDelta;
  1552. }
  1553. else
  1554. //now outside all polys of same polytype so set own WC ...
  1555. edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta);
  1556. } else
  1557. {
  1558. //prev edge is 'increasing' WindCount (WC) away from zero
  1559. //so we're inside the previous polygon ...
  1560. if (edge.WindDelta == 0)
  1561. edge.WindCnt = (e->WindCnt < 0 ? e->WindCnt - 1 : e->WindCnt + 1);
  1562. //if wind direction is reversing prev then use same WC
  1563. else if (e->WindDelta * edge.WindDelta < 0) edge.WindCnt = e->WindCnt;
  1564. //otherwise add to WC ...
  1565. else edge.WindCnt = e->WindCnt + edge.WindDelta;
  1566. }
  1567. edge.WindCnt2 = e->WindCnt2;
  1568. e = e->NextInAEL; //ie get ready to calc WindCnt2
  1569. }
  1570. //update WindCnt2 ...
  1571. if (IsEvenOddAltFillType(edge))
  1572. {
  1573. //EvenOdd filling ...
  1574. while (e != &edge)
  1575. {
  1576. if (e->WindDelta != 0)
  1577. edge.WindCnt2 = (edge.WindCnt2 == 0 ? 1 : 0);
  1578. e = e->NextInAEL;
  1579. }
  1580. } else
  1581. {
  1582. //nonZero, Positive or Negative filling ...
  1583. while ( e != &edge )
  1584. {
  1585. edge.WindCnt2 += e->WindDelta;
  1586. e = e->NextInAEL;
  1587. }
  1588. }
  1589. }
  1590. //------------------------------------------------------------------------------
  1591. bool Clipper::IsEvenOddFillType(const TEdge& edge) const
  1592. {
  1593. if (edge.PolyTyp == ptSubject)
  1594. return m_SubjFillType == pftEvenOdd; else
  1595. return m_ClipFillType == pftEvenOdd;
  1596. }
  1597. //------------------------------------------------------------------------------
  1598. bool Clipper::IsEvenOddAltFillType(const TEdge& edge) const
  1599. {
  1600. if (edge.PolyTyp == ptSubject)
  1601. return m_ClipFillType == pftEvenOdd; else
  1602. return m_SubjFillType == pftEvenOdd;
  1603. }
  1604. //------------------------------------------------------------------------------
  1605. bool Clipper::IsContributing(const TEdge& edge) const
  1606. {
  1607. PolyFillType pft, pft2;
  1608. if (edge.PolyTyp == ptSubject)
  1609. {
  1610. pft = m_SubjFillType;
  1611. pft2 = m_ClipFillType;
  1612. } else
  1613. {
  1614. pft = m_ClipFillType;
  1615. pft2 = m_SubjFillType;
  1616. }
  1617. switch(pft)
  1618. {
  1619. case pftEvenOdd:
  1620. //return false if a subj line has been flagged as inside a subj polygon
  1621. if (edge.WindDelta == 0 && edge.WindCnt != 1) return false;
  1622. break;
  1623. case pftNonZero:
  1624. if (Abs(edge.WindCnt) != 1) return false;
  1625. break;
  1626. case pftPositive:
  1627. if (edge.WindCnt != 1) return false;
  1628. break;
  1629. default: //pftNegative
  1630. if (edge.WindCnt != -1) return false;
  1631. }
  1632. switch(m_ClipType)
  1633. {
  1634. case ctIntersection:
  1635. switch(pft2)
  1636. {
  1637. case pftEvenOdd:
  1638. case pftNonZero:
  1639. return (edge.WindCnt2 != 0);
  1640. case pftPositive:
  1641. return (edge.WindCnt2 > 0);
  1642. default:
  1643. return (edge.WindCnt2 < 0);
  1644. }
  1645. break;
  1646. case ctUnion:
  1647. switch(pft2)
  1648. {
  1649. case pftEvenOdd:
  1650. case pftNonZero:
  1651. return (edge.WindCnt2 == 0);
  1652. case pftPositive:
  1653. return (edge.WindCnt2 <= 0);
  1654. default:
  1655. return (edge.WindCnt2 >= 0);
  1656. }
  1657. break;
  1658. case ctDifference:
  1659. if (edge.PolyTyp == ptSubject)
  1660. switch(pft2)
  1661. {
  1662. case pftEvenOdd:
  1663. case pftNonZero:
  1664. return (edge.WindCnt2 == 0);
  1665. case pftPositive:
  1666. return (edge.WindCnt2 <= 0);
  1667. default:
  1668. return (edge.WindCnt2 >= 0);
  1669. }
  1670. else
  1671. switch(pft2)
  1672. {
  1673. case pftEvenOdd:
  1674. case pftNonZero:
  1675. return (edge.WindCnt2 != 0);
  1676. case pftPositive:
  1677. return (edge.WindCnt2 > 0);
  1678. default:
  1679. return (edge.WindCnt2 < 0);
  1680. }
  1681. break;
  1682. case ctXor:
  1683. if (edge.WindDelta == 0) //XOr always contributing unless open
  1684. switch(pft2)
  1685. {
  1686. case pftEvenOdd:
  1687. case pftNonZero:
  1688. return (edge.WindCnt2 == 0);
  1689. case pftPositive:
  1690. return (edge.WindCnt2 <= 0);
  1691. default:
  1692. return (edge.WindCnt2 >= 0);
  1693. }
  1694. else
  1695. return true;
  1696. break;
  1697. default:
  1698. return true;
  1699. }
  1700. }
  1701. //------------------------------------------------------------------------------
  1702. OutPt* Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt)
  1703. {
  1704. OutPt* result;
  1705. TEdge *e, *prevE;
  1706. if (IsHorizontal(*e2) || ( e1->Dx > e2->Dx ))
  1707. {
  1708. result = AddOutPt(e1, Pt);
  1709. e2->OutIdx = e1->OutIdx;
  1710. e1->Side = esLeft;
  1711. e2->Side = esRight;
  1712. e = e1;
  1713. if (e->PrevInAEL == e2)
  1714. prevE = e2->PrevInAEL;
  1715. else
  1716. prevE = e->PrevInAEL;
  1717. } else
  1718. {
  1719. result = AddOutPt(e2, Pt);
  1720. e1->OutIdx = e2->OutIdx;
  1721. e1->Side = esRight;
  1722. e2->Side = esLeft;
  1723. e = e2;
  1724. if (e->PrevInAEL == e1)
  1725. prevE = e1->PrevInAEL;
  1726. else
  1727. prevE = e->PrevInAEL;
  1728. }
  1729. if (prevE && prevE->OutIdx >= 0 && prevE->Top.Y < Pt.Y && e->Top.Y < Pt.Y)
  1730. {
  1731. cInt xPrev = TopX(*prevE, Pt.Y);
  1732. cInt xE = TopX(*e, Pt.Y);
  1733. if (xPrev == xE && (e->WindDelta != 0) && (prevE->WindDelta != 0) &&
  1734. SlopesEqual(IntPoint(xPrev, Pt.Y), prevE->Top, IntPoint(xE, Pt.Y), e->Top, m_UseFullRange))
  1735. {
  1736. OutPt* outPt = AddOutPt(prevE, Pt);
  1737. AddJoin(result, outPt, e->Top);
  1738. }
  1739. }
  1740. return result;
  1741. }
  1742. //------------------------------------------------------------------------------
  1743. void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt)
  1744. {
  1745. AddOutPt( e1, Pt );
  1746. if (e2->WindDelta == 0) AddOutPt(e2, Pt);
  1747. if( e1->OutIdx == e2->OutIdx )
  1748. {
  1749. e1->OutIdx = Unassigned;
  1750. e2->OutIdx = Unassigned;
  1751. }
  1752. else if (e1->OutIdx < e2->OutIdx)
  1753. AppendPolygon(e1, e2);
  1754. else
  1755. AppendPolygon(e2, e1);
  1756. }
  1757. //------------------------------------------------------------------------------
  1758. void Clipper::AddEdgeToSEL(TEdge *edge)
  1759. {
  1760. //SEL pointers in PEdge are reused to build a list of horizontal edges.
  1761. //However, we don't need to worry about order with horizontal edge processing.
  1762. if( !m_SortedEdges )
  1763. {
  1764. m_SortedEdges = edge;
  1765. edge->PrevInSEL = 0;
  1766. edge->NextInSEL = 0;
  1767. }
  1768. else
  1769. {
  1770. edge->NextInSEL = m_SortedEdges;
  1771. edge->PrevInSEL = 0;
  1772. m_SortedEdges->PrevInSEL = edge;
  1773. m_SortedEdges = edge;
  1774. }
  1775. }
  1776. //------------------------------------------------------------------------------
  1777. bool Clipper::PopEdgeFromSEL(TEdge *&edge)
  1778. {
  1779. if (!m_SortedEdges) return false;
  1780. edge = m_SortedEdges;
  1781. DeleteFromSEL(m_SortedEdges);
  1782. return true;
  1783. }
  1784. //------------------------------------------------------------------------------
  1785. void Clipper::CopyAELToSEL()
  1786. {
  1787. TEdge* e = m_ActiveEdges;
  1788. m_SortedEdges = e;
  1789. while ( e )
  1790. {
  1791. e->PrevInSEL = e->PrevInAEL;
  1792. e->NextInSEL = e->NextInAEL;
  1793. e = e->NextInAEL;
  1794. }
  1795. }
  1796. //------------------------------------------------------------------------------
  1797. void Clipper::AddJoin(OutPt *op1, OutPt *op2, const IntPoint OffPt)
  1798. {
  1799. Join* j = new Join;
  1800. j->OutPt1 = op1;
  1801. j->OutPt2 = op2;
  1802. j->OffPt = OffPt;
  1803. m_Joins.push_back(j);
  1804. }
  1805. //------------------------------------------------------------------------------
  1806. void Clipper::ClearJoins()
  1807. {
  1808. for (JoinList::size_type i = 0; i < m_Joins.size(); i++)
  1809. delete m_Joins[i];
  1810. m_Joins.resize(0);
  1811. }
  1812. //------------------------------------------------------------------------------
  1813. void Clipper::ClearGhostJoins()
  1814. {
  1815. for (JoinList::size_type i = 0; i < m_GhostJoins.size(); i++)
  1816. delete m_GhostJoins[i];
  1817. m_GhostJoins.resize(0);
  1818. }
  1819. //------------------------------------------------------------------------------
  1820. void Clipper::AddGhostJoin(OutPt *op, const IntPoint OffPt)
  1821. {
  1822. Join* j = new Join;
  1823. j->OutPt1 = op;
  1824. j->OutPt2 = 0;
  1825. j->OffPt = OffPt;
  1826. m_GhostJoins.push_back(j);
  1827. }
  1828. //------------------------------------------------------------------------------
  1829. void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
  1830. {
  1831. const LocalMinimum *lm;
  1832. while (PopLocalMinima(botY, lm))
  1833. {
  1834. TEdge* lb = lm->LeftBound;
  1835. TEdge* rb = lm->RightBound;
  1836. OutPt *Op1 = 0;
  1837. if (!lb)
  1838. {
  1839. //nb: don't insert LB into either AEL or SEL
  1840. InsertEdgeIntoAEL(rb, 0);
  1841. SetWindingCount(*rb);
  1842. if (IsContributing(*rb))
  1843. Op1 = AddOutPt(rb, rb->Bot);
  1844. }
  1845. else if (!rb)
  1846. {
  1847. InsertEdgeIntoAEL(lb, 0);
  1848. SetWindingCount(*lb);
  1849. if (IsContributing(*lb))
  1850. Op1 = AddOutPt(lb, lb->Bot);
  1851. InsertScanbeam(lb->Top.Y);
  1852. }
  1853. else
  1854. {
  1855. InsertEdgeIntoAEL(lb, 0);
  1856. InsertEdgeIntoAEL(rb, lb);
  1857. SetWindingCount( *lb );
  1858. rb->WindCnt = lb->WindCnt;
  1859. rb->WindCnt2 = lb->WindCnt2;
  1860. if (IsContributing(*lb))
  1861. Op1 = AddLocalMinPoly(lb, rb, lb->Bot);
  1862. InsertScanbeam(lb->Top.Y);
  1863. }
  1864. if (rb)
  1865. {
  1866. if (IsHorizontal(*rb))
  1867. {
  1868. AddEdgeToSEL(rb);
  1869. if (rb->NextInLML)
  1870. InsertScanbeam(rb->NextInLML->Top.Y);
  1871. }
  1872. else InsertScanbeam( rb->Top.Y );
  1873. }
  1874. if (!lb || !rb) continue;
  1875. //if any output polygons share an edge, they'll need joining later ...
  1876. if (Op1 && IsHorizontal(*rb) &&
  1877. m_GhostJoins.size() > 0 && (rb->WindDelta != 0))
  1878. {
  1879. for (JoinList::size_type i = 0; i < m_GhostJoins.size(); ++i)
  1880. {
  1881. Join* jr = m_GhostJoins[i];
  1882. //if the horizontal Rb and a 'ghost' horizontal overlap, then convert
  1883. //the 'ghost' join to a real join ready for later ...
  1884. if (HorzSegmentsOverlap(jr->OutPt1->Pt.X, jr->OffPt.X, rb->Bot.X, rb->Top.X))
  1885. AddJoin(jr->OutPt1, Op1, jr->OffPt);
  1886. }
  1887. }
  1888. if (lb->OutIdx >= 0 && lb->PrevInAEL &&
  1889. lb->PrevInAEL->Curr.X == lb->Bot.X &&
  1890. lb->PrevInAEL->OutIdx >= 0 &&
  1891. SlopesEqual(lb->PrevInAEL->Bot, lb->PrevInAEL->Top, lb->Curr, lb->Top, m_UseFullRange) &&
  1892. (lb->WindDelta != 0) && (lb->PrevInAEL->WindDelta != 0))
  1893. {
  1894. OutPt *Op2 = AddOutPt(lb->PrevInAEL, lb->Bot);
  1895. AddJoin(Op1, Op2, lb->Top);
  1896. }
  1897. if(lb->NextInAEL != rb)
  1898. {
  1899. if (rb->OutIdx >= 0 && rb->PrevInAEL->OutIdx >= 0 &&
  1900. SlopesEqual(rb->PrevInAEL->Curr, rb->PrevInAEL->Top, rb->Curr, rb->Top, m_UseFullRange) &&
  1901. (rb->WindDelta != 0) && (rb->PrevInAEL->WindDelta != 0))
  1902. {
  1903. OutPt *Op2 = AddOutPt(rb->PrevInAEL, rb->Bot);
  1904. AddJoin(Op1, Op2, rb->Top);
  1905. }
  1906. TEdge* e = lb->NextInAEL;
  1907. if (e)
  1908. {
  1909. while( e != rb )
  1910. {
  1911. //nb: For calculating winding counts etc, IntersectEdges() assumes
  1912. //that param1 will be to the Right of param2 ABOVE the intersection ...
  1913. IntersectEdges(rb , e , lb->Curr); //order important here
  1914. e = e->NextInAEL;
  1915. }
  1916. }
  1917. }
  1918. }
  1919. }
  1920. //------------------------------------------------------------------------------
  1921. void Clipper::DeleteFromSEL(TEdge *e)
  1922. {
  1923. TEdge* SelPrev = e->PrevInSEL;
  1924. TEdge* SelNext = e->NextInSEL;
  1925. if( !SelPrev && !SelNext && (e != m_SortedEdges) ) return; //already deleted
  1926. if( SelPrev ) SelPrev->NextInSEL = SelNext;
  1927. else m_SortedEdges = SelNext;
  1928. if( SelNext ) SelNext->PrevInSEL = SelPrev;
  1929. e->NextInSEL = 0;
  1930. e->PrevInSEL = 0;
  1931. }
  1932. //------------------------------------------------------------------------------
  1933. #ifdef use_xyz
  1934. void Clipper::SetZ(IntPoint& pt, TEdge& e1, TEdge& e2)
  1935. {
  1936. if (pt.Z != 0 || !m_ZFill) return;
  1937. else if (pt == e1.Bot) pt.Z = e1.Bot.Z;
  1938. else if (pt == e1.Top) pt.Z = e1.Top.Z;
  1939. else if (pt == e2.Bot) pt.Z = e2.Bot.Z;
  1940. else if (pt == e2.Top) pt.Z = e2.Top.Z;
  1941. else (*m_ZFill)(e1.Bot, e1.Top, e2.Bot, e2.Top, pt);
  1942. }
  1943. //------------------------------------------------------------------------------
  1944. #endif
  1945. void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &Pt)
  1946. {
  1947. bool e1Contributing = ( e1->OutIdx >= 0 );
  1948. bool e2Contributing = ( e2->OutIdx >= 0 );
  1949. #ifdef use_xyz
  1950. SetZ(Pt, *e1, *e2);
  1951. #endif
  1952. #ifdef use_lines
  1953. //if either edge is on an OPEN path ...
  1954. if (e1->WindDelta == 0 || e2->WindDelta == 0)
  1955. {
  1956. //ignore subject-subject open path intersections UNLESS they
  1957. //are both open paths, AND they are both 'contributing maximas' ...
  1958. if (e1->WindDelta == 0 && e2->WindDelta == 0) return;
  1959. //if intersecting a subj line with a subj poly ...
  1960. else if (e1->PolyTyp == e2->PolyTyp &&
  1961. e1->WindDelta != e2->WindDelta && m_ClipType == ctUnion)
  1962. {
  1963. if (e1->WindDelta == 0)
  1964. {
  1965. if (e2Contributing)
  1966. {
  1967. AddOutPt(e1, Pt);
  1968. if (e1Contributing) e1->OutIdx = Unassigned;
  1969. }
  1970. }
  1971. else
  1972. {
  1973. if (e1Contributing)
  1974. {
  1975. AddOutPt(e2, Pt);
  1976. if (e2Contributing) e2->OutIdx = Unassigned;
  1977. }
  1978. }
  1979. }
  1980. else if (e1->PolyTyp != e2->PolyTyp)
  1981. {
  1982. //toggle subj open path OutIdx on/off when Abs(clip.WndCnt) == 1 ...
  1983. if ((e1->WindDelta == 0) && abs(e2->WindCnt) == 1 &&
  1984. (m_ClipType != ctUnion || e2->WindCnt2 == 0))
  1985. {
  1986. AddOutPt(e1, Pt);
  1987. if (e1Contributing) e1->OutIdx = Unassigned;
  1988. }
  1989. else if ((e2->WindDelta == 0) && (abs(e1->WindCnt) == 1) &&
  1990. (m_ClipType != ctUnion || e1->WindCnt2 == 0))
  1991. {
  1992. AddOutPt(e2, Pt);
  1993. if (e2Contributing) e2->OutIdx = Unassigned;
  1994. }
  1995. }
  1996. return;
  1997. }
  1998. #endif
  1999. //update winding counts...
  2000. //assumes that e1 will be to the Right of e2 ABOVE the intersection
  2001. if ( e1->PolyTyp == e2->PolyTyp )
  2002. {
  2003. if ( IsEvenOddFillType( *e1) )
  2004. {
  2005. int oldE1WindCnt = e1->WindCnt;
  2006. e1->WindCnt = e2->WindCnt;
  2007. e2->WindCnt = oldE1WindCnt;
  2008. } else
  2009. {
  2010. if (e1->WindCnt + e2->WindDelta == 0 ) e1->WindCnt = -e1->WindCnt;
  2011. else e1->WindCnt += e2->WindDelta;
  2012. if ( e2->WindCnt - e1->WindDelta == 0 ) e2->WindCnt = -e2->WindCnt;
  2013. else e2->WindCnt -= e1->WindDelta;
  2014. }
  2015. } else
  2016. {
  2017. if (!IsEvenOddFillType(*e2)) e1->WindCnt2 += e2->WindDelta;
  2018. else e1->WindCnt2 = ( e1->WindCnt2 == 0 ) ? 1 : 0;
  2019. if (!IsEvenOddFillType(*e1)) e2->WindCnt2 -= e1->WindDelta;
  2020. else e2->WindCnt2 = ( e2->WindCnt2 == 0 ) ? 1 : 0;
  2021. }
  2022. PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2;
  2023. if (e1->PolyTyp == ptSubject)
  2024. {
  2025. e1FillType = m_SubjFillType;
  2026. e1FillType2 = m_ClipFillType;
  2027. } else
  2028. {
  2029. e1FillType = m_ClipFillType;
  2030. e1FillType2 = m_SubjFillType;
  2031. }
  2032. if (e2->PolyTyp == ptSubject)
  2033. {
  2034. e2FillType = m_SubjFillType;
  2035. e2FillType2 = m_ClipFillType;
  2036. } else
  2037. {
  2038. e2FillType = m_ClipFillType;
  2039. e2FillType2 = m_SubjFillType;
  2040. }
  2041. cInt e1Wc, e2Wc;
  2042. switch (e1FillType)
  2043. {
  2044. case pftPositive: e1Wc = e1->WindCnt; break;
  2045. case pftNegative: e1Wc = -e1->WindCnt; break;
  2046. default: e1Wc = Abs(e1->WindCnt);
  2047. }
  2048. switch(e2FillType)
  2049. {
  2050. case pftPositive: e2Wc = e2->WindCnt; break;
  2051. case pftNegative: e2Wc = -e2->WindCnt; break;
  2052. default: e2Wc = Abs(e2->WindCnt);
  2053. }
  2054. if ( e1Contributing && e2Contributing )
  2055. {
  2056. if ((e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) ||
  2057. (e1->PolyTyp != e2->PolyTyp && m_ClipType != ctXor) )
  2058. {
  2059. AddLocalMaxPoly(e1, e2, Pt);
  2060. }
  2061. else
  2062. {
  2063. AddOutPt(e1, Pt);
  2064. AddOutPt(e2, Pt);
  2065. SwapSides( *e1 , *e2 );
  2066. SwapPolyIndexes( *e1 , *e2 );
  2067. }
  2068. }
  2069. else if ( e1Contributing )
  2070. {
  2071. if (e2Wc == 0 || e2Wc == 1)
  2072. {
  2073. AddOutPt(e1, Pt);
  2074. SwapSides(*e1, *e2);
  2075. SwapPolyIndexes(*e1, *e2);
  2076. }
  2077. }
  2078. else if ( e2Contributing )
  2079. {
  2080. if (e1Wc == 0 || e1Wc == 1)
  2081. {
  2082. AddOutPt(e2, Pt);
  2083. SwapSides(*e1, *e2);
  2084. SwapPolyIndexes(*e1, *e2);
  2085. }
  2086. }
  2087. else if ( (e1Wc == 0 || e1Wc == 1) && (e2Wc == 0 || e2Wc == 1))
  2088. {
  2089. //neither edge is currently contributing ...
  2090. cInt e1Wc2, e2Wc2;
  2091. switch (e1FillType2)
  2092. {
  2093. case pftPositive: e1Wc2 = e1->WindCnt2; break;
  2094. case pftNegative : e1Wc2 = -e1->WindCnt2; break;
  2095. default: e1Wc2 = Abs(e1->WindCnt2);
  2096. }
  2097. switch (e2FillType2)
  2098. {
  2099. case pftPositive: e2Wc2 = e2->WindCnt2; break;
  2100. case pftNegative: e2Wc2 = -e2->WindCnt2; break;
  2101. default: e2Wc2 = Abs(e2->WindCnt2);
  2102. }
  2103. if (e1->PolyTyp != e2->PolyTyp)
  2104. {
  2105. AddLocalMinPoly(e1, e2, Pt);
  2106. }
  2107. else if (e1Wc == 1 && e2Wc == 1)
  2108. switch( m_ClipType ) {
  2109. case ctIntersection:
  2110. if (e1Wc2 > 0 && e2Wc2 > 0)
  2111. AddLocalMinPoly(e1, e2, Pt);
  2112. break;
  2113. case ctUnion:
  2114. if ( e1Wc2 <= 0 && e2Wc2 <= 0 )
  2115. AddLocalMinPoly(e1, e2, Pt);
  2116. break;
  2117. case ctDifference:
  2118. if (((e1->PolyTyp == ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) ||
  2119. ((e1->PolyTyp == ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0)))
  2120. AddLocalMinPoly(e1, e2, Pt);
  2121. break;
  2122. case ctXor:
  2123. AddLocalMinPoly(e1, e2, Pt);
  2124. }
  2125. else
  2126. SwapSides( *e1, *e2 );
  2127. }
  2128. }
  2129. //------------------------------------------------------------------------------
  2130. void Clipper::SetHoleState(TEdge *e, OutRec *outrec)
  2131. {
  2132. TEdge *e2 = e->PrevInAEL;
  2133. TEdge *eTmp = 0;
  2134. while (e2)
  2135. {
  2136. if (e2->OutIdx >= 0 && e2->WindDelta != 0)
  2137. {
  2138. if (!eTmp) eTmp = e2;
  2139. else if (eTmp->OutIdx == e2->OutIdx) eTmp = 0;
  2140. }
  2141. e2 = e2->PrevInAEL;
  2142. }
  2143. if (!eTmp)
  2144. {
  2145. outrec->FirstLeft = 0;
  2146. outrec->IsHole = false;
  2147. }
  2148. else
  2149. {
  2150. outrec->FirstLeft = m_PolyOuts[eTmp->OutIdx];
  2151. outrec->IsHole = !outrec->FirstLeft->IsHole;
  2152. }
  2153. }
  2154. //------------------------------------------------------------------------------
  2155. OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2)
  2156. {
  2157. //work out which polygon fragment has the correct hole state ...
  2158. if (!outRec1->BottomPt)
  2159. outRec1->BottomPt = GetBottomPt(outRec1->Pts);
  2160. if (!outRec2->BottomPt)
  2161. outRec2->BottomPt = GetBottomPt(outRec2->Pts);
  2162. OutPt *OutPt1 = outRec1->BottomPt;
  2163. OutPt *OutPt2 = outRec2->BottomPt;
  2164. if (OutPt1->Pt.Y > OutPt2->Pt.Y) return outRec1;
  2165. else if (OutPt1->Pt.Y < OutPt2->Pt.Y) return outRec2;
  2166. else if (OutPt1->Pt.X < OutPt2->Pt.X) return outRec1;
  2167. else if (OutPt1->Pt.X > OutPt2->Pt.X) return outRec2;
  2168. else if (OutPt1->Next == OutPt1) return outRec2;
  2169. else if (OutPt2->Next == OutPt2) return outRec1;
  2170. else if (FirstIsBottomPt(OutPt1, OutPt2)) return outRec1;
  2171. else return outRec2;
  2172. }
  2173. //------------------------------------------------------------------------------
  2174. bool OutRec1RightOfOutRec2(OutRec* outRec1, OutRec* outRec2)
  2175. {
  2176. do
  2177. {
  2178. outRec1 = outRec1->FirstLeft;
  2179. if (outRec1 == outRec2) return true;
  2180. } while (outRec1);
  2181. return false;
  2182. }
  2183. //------------------------------------------------------------------------------
  2184. OutRec* Clipper::GetOutRec(int Idx)
  2185. {
  2186. OutRec* outrec = m_PolyOuts[Idx];
  2187. while (outrec != m_PolyOuts[outrec->Idx])
  2188. outrec = m_PolyOuts[outrec->Idx];
  2189. return outrec;
  2190. }
  2191. //------------------------------------------------------------------------------
  2192. void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
  2193. {
  2194. //get the start and ends of both output polygons ...
  2195. OutRec *outRec1 = m_PolyOuts[e1->OutIdx];
  2196. OutRec *outRec2 = m_PolyOuts[e2->OutIdx];
  2197. OutRec *holeStateRec;
  2198. if (OutRec1RightOfOutRec2(outRec1, outRec2))
  2199. holeStateRec = outRec2;
  2200. else if (OutRec1RightOfOutRec2(outRec2, outRec1))
  2201. holeStateRec = outRec1;
  2202. else
  2203. holeStateRec = GetLowermostRec(outRec1, outRec2);
  2204. //get the start and ends of both output polygons and
  2205. //join e2 poly onto e1 poly and delete pointers to e2 ...
  2206. OutPt* p1_lft = outRec1->Pts;
  2207. OutPt* p1_rt = p1_lft->Prev;
  2208. OutPt* p2_lft = outRec2->Pts;
  2209. OutPt* p2_rt = p2_lft->Prev;
  2210. //join e2 poly onto e1 poly and delete pointers to e2 ...
  2211. if( e1->Side == esLeft )
  2212. {
  2213. if( e2->Side == esLeft )
  2214. {
  2215. //z y x a b c
  2216. ReversePolyPtLinks(p2_lft);
  2217. p2_lft->Next = p1_lft;
  2218. p1_lft->Prev = p2_lft;
  2219. p1_rt->Next = p2_rt;
  2220. p2_rt->Prev = p1_rt;
  2221. outRec1->Pts = p2_rt;
  2222. } else
  2223. {
  2224. //x y z a b c
  2225. p2_rt->Next = p1_lft;
  2226. p1_lft->Prev = p2_rt;
  2227. p2_lft->Prev = p1_rt;
  2228. p1_rt->Next = p2_lft;
  2229. outRec1->Pts = p2_lft;
  2230. }
  2231. } else
  2232. {
  2233. if( e2->Side == esRight )
  2234. {
  2235. //a b c z y x
  2236. ReversePolyPtLinks(p2_lft);
  2237. p1_rt->Next = p2_rt;
  2238. p2_rt->Prev = p1_rt;
  2239. p2_lft->Next = p1_lft;
  2240. p1_lft->Prev = p2_lft;
  2241. } else
  2242. {
  2243. //a b c x y z
  2244. p1_rt->Next = p2_lft;
  2245. p2_lft->Prev = p1_rt;
  2246. p1_lft->Prev = p2_rt;
  2247. p2_rt->Next = p1_lft;
  2248. }
  2249. }
  2250. outRec1->BottomPt = 0;
  2251. if (holeStateRec == outRec2)
  2252. {
  2253. if (outRec2->FirstLeft != outRec1)
  2254. outRec1->FirstLeft = outRec2->FirstLeft;
  2255. outRec1->IsHole = outRec2->IsHole;
  2256. }
  2257. outRec2->Pts = 0;
  2258. outRec2->BottomPt = 0;
  2259. outRec2->FirstLeft = outRec1;
  2260. int OKIdx = e1->OutIdx;
  2261. int ObsoleteIdx = e2->OutIdx;
  2262. e1->OutIdx = Unassigned; //nb: safe because we only get here via AddLocalMaxPoly
  2263. e2->OutIdx = Unassigned;
  2264. TEdge* e = m_ActiveEdges;
  2265. while( e )
  2266. {
  2267. if( e->OutIdx == ObsoleteIdx )
  2268. {
  2269. e->OutIdx = OKIdx;
  2270. e->Side = e1->Side;
  2271. break;
  2272. }
  2273. e = e->NextInAEL;
  2274. }
  2275. outRec2->Idx = outRec1->Idx;
  2276. }
  2277. //------------------------------------------------------------------------------
  2278. OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
  2279. {
  2280. if( e->OutIdx < 0 )
  2281. {
  2282. OutRec *outRec = CreateOutRec();
  2283. outRec->IsOpen = (e->WindDelta == 0);
  2284. OutPt* newOp = new OutPt;
  2285. outRec->Pts = newOp;
  2286. newOp->Idx = outRec->Idx;
  2287. newOp->Pt = pt;
  2288. newOp->Next = newOp;
  2289. newOp->Prev = newOp;
  2290. if (!outRec->IsOpen)
  2291. SetHoleState(e, outRec);
  2292. e->OutIdx = outRec->Idx;
  2293. return newOp;
  2294. } else
  2295. {
  2296. OutRec *outRec = m_PolyOuts[e->OutIdx];
  2297. //OutRec.Pts is the 'Left-most' point & OutRec.Pts.Prev is the 'Right-most'
  2298. OutPt* op = outRec->Pts;
  2299. bool ToFront = (e->Side == esLeft);
  2300. if (ToFront && (pt == op->Pt)) return op;
  2301. else if (!ToFront && (pt == op->Prev->Pt)) return op->Prev;
  2302. OutPt* newOp = new OutPt;
  2303. newOp->Idx = outRec->Idx;
  2304. newOp->Pt = pt;
  2305. newOp->Next = op;
  2306. newOp->Prev = op->Prev;
  2307. newOp->Prev->Next = newOp;
  2308. op->Prev = newOp;
  2309. if (ToFront) outRec->Pts = newOp;
  2310. return newOp;
  2311. }
  2312. }
  2313. //------------------------------------------------------------------------------
  2314. OutPt* Clipper::GetLastOutPt(TEdge *e)
  2315. {
  2316. OutRec *outRec = m_PolyOuts[e->OutIdx];
  2317. if (e->Side == esLeft)
  2318. return outRec->Pts;
  2319. else
  2320. return outRec->Pts->Prev;
  2321. }
  2322. //------------------------------------------------------------------------------
  2323. void Clipper::ProcessHorizontals()
  2324. {
  2325. TEdge* horzEdge;
  2326. while (PopEdgeFromSEL(horzEdge))
  2327. ProcessHorizontal(horzEdge);
  2328. }
  2329. //------------------------------------------------------------------------------
  2330. inline bool IsMinima(TEdge *e)
  2331. {
  2332. return e && (e->Prev->NextInLML != e) && (e->Next->NextInLML != e);
  2333. }
  2334. //------------------------------------------------------------------------------
  2335. inline bool IsMaxima(TEdge *e, const cInt Y)
  2336. {
  2337. return e && e->Top.Y == Y && !e->NextInLML;
  2338. }
  2339. //------------------------------------------------------------------------------
  2340. inline bool IsIntermediate(TEdge *e, const cInt Y)
  2341. {
  2342. return e->Top.Y == Y && e->NextInLML;
  2343. }
  2344. //------------------------------------------------------------------------------
  2345. TEdge *GetMaximaPair(TEdge *e)
  2346. {
  2347. if ((e->Next->Top == e->Top) && !e->Next->NextInLML)
  2348. return e->Next;
  2349. else if ((e->Prev->Top == e->Top) && !e->Prev->NextInLML)
  2350. return e->Prev;
  2351. else return 0;
  2352. }
  2353. //------------------------------------------------------------------------------
  2354. TEdge *GetMaximaPairEx(TEdge *e)
  2355. {
  2356. //as GetMaximaPair() but returns 0 if MaxPair isn't in AEL (unless it's horizontal)
  2357. TEdge* result = GetMaximaPair(e);
  2358. if (result && (result->OutIdx == Skip ||
  2359. (result->NextInAEL == result->PrevInAEL && !IsHorizontal(*result)))) return 0;
  2360. return result;
  2361. }
  2362. //------------------------------------------------------------------------------
  2363. void Clipper::SwapPositionsInSEL(TEdge *Edge1, TEdge *Edge2)
  2364. {
  2365. if( !( Edge1->NextInSEL ) && !( Edge1->PrevInSEL ) ) return;
  2366. if( !( Edge2->NextInSEL ) && !( Edge2->PrevInSEL ) ) return;
  2367. if( Edge1->NextInSEL == Edge2 )
  2368. {
  2369. TEdge* Next = Edge2->NextInSEL;
  2370. if( Next ) Next->PrevInSEL = Edge1;
  2371. TEdge* Prev = Edge1->PrevInSEL;
  2372. if( Prev ) Prev->NextInSEL = Edge2;
  2373. Edge2->PrevInSEL = Prev;
  2374. Edge2->NextInSEL = Edge1;
  2375. Edge1->PrevInSEL = Edge2;
  2376. Edge1->NextInSEL = Next;
  2377. }
  2378. else if( Edge2->NextInSEL == Edge1 )
  2379. {
  2380. TEdge* Next = Edge1->NextInSEL;
  2381. if( Next ) Next->PrevInSEL = Edge2;
  2382. TEdge* Prev = Edge2->PrevInSEL;
  2383. if( Prev ) Prev->NextInSEL = Edge1;
  2384. Edge1->PrevInSEL = Prev;
  2385. Edge1->NextInSEL = Edge2;
  2386. Edge2->PrevInSEL = Edge1;
  2387. Edge2->NextInSEL = Next;
  2388. }
  2389. else
  2390. {
  2391. TEdge* Next = Edge1->NextInSEL;
  2392. TEdge* Prev = Edge1->PrevInSEL;
  2393. Edge1->NextInSEL = Edge2->NextInSEL;
  2394. if( Edge1->NextInSEL ) Edge1->NextInSEL->PrevInSEL = Edge1;
  2395. Edge1->PrevInSEL = Edge2->PrevInSEL;
  2396. if( Edge1->PrevInSEL ) Edge1->PrevInSEL->NextInSEL = Edge1;
  2397. Edge2->NextInSEL = Next;
  2398. if( Edge2->NextInSEL ) Edge2->NextInSEL->PrevInSEL = Edge2;
  2399. Edge2->PrevInSEL = Prev;
  2400. if( Edge2->PrevInSEL ) Edge2->PrevInSEL->NextInSEL = Edge2;
  2401. }
  2402. if( !Edge1->PrevInSEL ) m_SortedEdges = Edge1;
  2403. else if( !Edge2->PrevInSEL ) m_SortedEdges = Edge2;
  2404. }
  2405. //------------------------------------------------------------------------------
  2406. TEdge* GetNextInAEL(TEdge *e, Direction dir)
  2407. {
  2408. return dir == dLeftToRight ? e->NextInAEL : e->PrevInAEL;
  2409. }
  2410. //------------------------------------------------------------------------------
  2411. void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt& Right)
  2412. {
  2413. if (HorzEdge.Bot.X < HorzEdge.Top.X)
  2414. {
  2415. Left = HorzEdge.Bot.X;
  2416. Right = HorzEdge.Top.X;
  2417. Dir = dLeftToRight;
  2418. } else
  2419. {
  2420. Left = HorzEdge.Top.X;
  2421. Right = HorzEdge.Bot.X;
  2422. Dir = dRightToLeft;
  2423. }
  2424. }
  2425. //------------------------------------------------------------------------
  2426. /*******************************************************************************
  2427. * Notes: Horizontal edges (HEs) at scanline intersections (ie at the Top or *
  2428. * Bottom of a scanbeam) are processed as if layered. The order in which HEs *
  2429. * are processed doesn't matter. HEs intersect with other HE Bot.Xs only [#] *
  2430. * (or they could intersect with Top.Xs only, ie EITHER Bot.Xs OR Top.Xs), *
  2431. * and with other non-horizontal edges [*]. Once these intersections are *
  2432. * processed, intermediate HEs then 'promote' the Edge above (NextInLML) into *
  2433. * the AEL. These 'promoted' edges may in turn intersect [%] with other HEs. *
  2434. *******************************************************************************/
  2435. void Clipper::ProcessHorizontal(TEdge *horzEdge)
  2436. {
  2437. Direction dir;
  2438. cInt horzLeft, horzRight;
  2439. bool IsOpen = (horzEdge->WindDelta == 0);
  2440. GetHorzDirection(*horzEdge, dir, horzLeft, horzRight);
  2441. TEdge* eLastHorz = horzEdge, *eMaxPair = 0;
  2442. while (eLastHorz->NextInLML && IsHorizontal(*eLastHorz->NextInLML))
  2443. eLastHorz = eLastHorz->NextInLML;
  2444. if (!eLastHorz->NextInLML)
  2445. eMaxPair = GetMaximaPair(eLastHorz);
  2446. MaximaList::const_iterator maxIt;
  2447. MaximaList::const_reverse_iterator maxRit;
  2448. if (m_Maxima.size() > 0)
  2449. {
  2450. //get the first maxima in range (X) ...
  2451. if (dir == dLeftToRight)
  2452. {
  2453. maxIt = m_Maxima.begin();
  2454. while (maxIt != m_Maxima.end() && *maxIt <= horzEdge->Bot.X) maxIt++;
  2455. if (maxIt != m_Maxima.end() && *maxIt >= eLastHorz->Top.X)
  2456. maxIt = m_Maxima.end();
  2457. }
  2458. else
  2459. {
  2460. maxRit = m_Maxima.rbegin();
  2461. while (maxRit != m_Maxima.rend() && *maxRit > horzEdge->Bot.X) maxRit++;
  2462. if (maxRit != m_Maxima.rend() && *maxRit <= eLastHorz->Top.X)
  2463. maxRit = m_Maxima.rend();
  2464. }
  2465. }
  2466. OutPt* op1 = 0;
  2467. for (;;) //loop through consec. horizontal edges
  2468. {
  2469. bool IsLastHorz = (horzEdge == eLastHorz);
  2470. TEdge* e = GetNextInAEL(horzEdge, dir);
  2471. while(e)
  2472. {
  2473. //this code block inserts extra coords into horizontal edges (in output
  2474. //polygons) whereever maxima touch these horizontal edges. This helps
  2475. //'simplifying' polygons (ie if the Simplify property is set).
  2476. if (m_Maxima.size() > 0)
  2477. {
  2478. if (dir == dLeftToRight)
  2479. {
  2480. while (maxIt != m_Maxima.end() && *maxIt < e->Curr.X)
  2481. {
  2482. if (horzEdge->OutIdx >= 0 && !IsOpen)
  2483. AddOutPt(horzEdge, IntPoint(*maxIt, horzEdge->Bot.Y));
  2484. maxIt++;
  2485. }
  2486. }
  2487. else
  2488. {
  2489. while (maxRit != m_Maxima.rend() && *maxRit > e->Curr.X)
  2490. {
  2491. if (horzEdge->OutIdx >= 0 && !IsOpen)
  2492. AddOutPt(horzEdge, IntPoint(*maxRit, horzEdge->Bot.Y));
  2493. maxRit++;
  2494. }
  2495. }
  2496. };
  2497. if ((dir == dLeftToRight && e->Curr.X > horzRight) ||
  2498. (dir == dRightToLeft && e->Curr.X < horzLeft)) break;
  2499. //Also break if we've got to the end of an intermediate horizontal edge ...
  2500. //nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal.
  2501. if (e->Curr.X == horzEdge->Top.X && horzEdge->NextInLML &&
  2502. e->Dx < horzEdge->NextInLML->Dx) break;
  2503. if (horzEdge->OutIdx >= 0 && !IsOpen) //note: may be done multiple times
  2504. {
  2505. #ifdef use_xyz
  2506. if (dir == dLeftToRight) SetZ(e->Curr, *horzEdge, *e);
  2507. else SetZ(e->Curr, *e, *horzEdge);
  2508. #endif
  2509. op1 = AddOutPt(horzEdge, e->Curr);
  2510. TEdge* eNextHorz = m_SortedEdges;
  2511. while (eNextHorz)
  2512. {
  2513. if (eNextHorz->OutIdx >= 0 &&
  2514. HorzSegmentsOverlap(horzEdge->Bot.X,
  2515. horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X))
  2516. {
  2517. OutPt* op2 = GetLastOutPt(eNextHorz);
  2518. AddJoin(op2, op1, eNextHorz->Top);
  2519. }
  2520. eNextHorz = eNextHorz->NextInSEL;
  2521. }
  2522. AddGhostJoin(op1, horzEdge->Bot);
  2523. }
  2524. //OK, so far we're still in range of the horizontal Edge but make sure
  2525. //we're at the last of consec. horizontals when matching with eMaxPair
  2526. if(e == eMaxPair && IsLastHorz)
  2527. {
  2528. if (horzEdge->OutIdx >= 0)
  2529. AddLocalMaxPoly(horzEdge, eMaxPair, horzEdge->Top);
  2530. DeleteFromAEL(horzEdge);
  2531. DeleteFromAEL(eMaxPair);
  2532. return;
  2533. }
  2534. if(dir == dLeftToRight)
  2535. {
  2536. IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y);
  2537. IntersectEdges(horzEdge, e, Pt);
  2538. }
  2539. else
  2540. {
  2541. IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y);
  2542. IntersectEdges( e, horzEdge, Pt);
  2543. }
  2544. TEdge* eNext = GetNextInAEL(e, dir);
  2545. SwapPositionsInAEL( horzEdge, e );
  2546. e = eNext;
  2547. } //end while(e)
  2548. //Break out of loop if HorzEdge.NextInLML is not also horizontal ...
  2549. if (!horzEdge->NextInLML || !IsHorizontal(*horzEdge->NextInLML)) break;
  2550. UpdateEdgeIntoAEL(horzEdge);
  2551. if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Bot);
  2552. GetHorzDirection(*horzEdge, dir, horzLeft, horzRight);
  2553. } //end for (;;)
  2554. if (horzEdge->OutIdx >= 0 && !op1)
  2555. {
  2556. op1 = GetLastOutPt(horzEdge);
  2557. TEdge* eNextHorz = m_SortedEdges;
  2558. while (eNextHorz)
  2559. {
  2560. if (eNextHorz->OutIdx >= 0 &&
  2561. HorzSegmentsOverlap(horzEdge->Bot.X,
  2562. horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X))
  2563. {
  2564. OutPt* op2 = GetLastOutPt(eNextHorz);
  2565. AddJoin(op2, op1, eNextHorz->Top);
  2566. }
  2567. eNextHorz = eNextHorz->NextInSEL;
  2568. }
  2569. AddGhostJoin(op1, horzEdge->Top);
  2570. }
  2571. if (horzEdge->NextInLML)
  2572. {
  2573. if(horzEdge->OutIdx >= 0)
  2574. {
  2575. op1 = AddOutPt( horzEdge, horzEdge->Top);
  2576. UpdateEdgeIntoAEL(horzEdge);
  2577. if (horzEdge->WindDelta == 0) return;
  2578. //nb: HorzEdge is no longer horizontal here
  2579. TEdge* ePrev = horzEdge->PrevInAEL;
  2580. TEdge* eNext = horzEdge->NextInAEL;
  2581. if (ePrev && ePrev->Curr.X == horzEdge->Bot.X &&
  2582. ePrev->Curr.Y == horzEdge->Bot.Y && ePrev->WindDelta != 0 &&
  2583. (ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y &&
  2584. SlopesEqual(*horzEdge, *ePrev, m_UseFullRange)))
  2585. {
  2586. OutPt* op2 = AddOutPt(ePrev, horzEdge->Bot);
  2587. AddJoin(op1, op2, horzEdge->Top);
  2588. }
  2589. else if (eNext && eNext->Curr.X == horzEdge->Bot.X &&
  2590. eNext->Curr.Y == horzEdge->Bot.Y && eNext->WindDelta != 0 &&
  2591. eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y &&
  2592. SlopesEqual(*horzEdge, *eNext, m_UseFullRange))
  2593. {
  2594. OutPt* op2 = AddOutPt(eNext, horzEdge->Bot);
  2595. AddJoin(op1, op2, horzEdge->Top);
  2596. }
  2597. }
  2598. else
  2599. UpdateEdgeIntoAEL(horzEdge);
  2600. }
  2601. else
  2602. {
  2603. if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Top);
  2604. DeleteFromAEL(horzEdge);
  2605. }
  2606. }
  2607. //------------------------------------------------------------------------------
  2608. bool Clipper::ProcessIntersections(const cInt topY)
  2609. {
  2610. if( !m_ActiveEdges ) return true;
  2611. CLIPPER_TRY {
  2612. BuildIntersectList(topY);
  2613. size_t IlSize = m_IntersectList.size();
  2614. if (IlSize == 0) return true;
  2615. if (IlSize == 1 || FixupIntersectionOrder()) ProcessIntersectList();
  2616. else return false;
  2617. }
  2618. CLIPPER_CATCH(...)
  2619. {
  2620. m_SortedEdges = 0;
  2621. DisposeIntersectNodes();
  2622. CLIPPER_THROW(clipperException("ProcessIntersections error"));
  2623. }
  2624. m_SortedEdges = 0;
  2625. return true;
  2626. }
  2627. //------------------------------------------------------------------------------
  2628. void Clipper::DisposeIntersectNodes()
  2629. {
  2630. for (size_t i = 0; i < m_IntersectList.size(); ++i )
  2631. delete m_IntersectList[i];
  2632. m_IntersectList.clear();
  2633. }
  2634. //------------------------------------------------------------------------------
  2635. void Clipper::BuildIntersectList(const cInt topY)
  2636. {
  2637. if ( !m_ActiveEdges ) return;
  2638. //prepare for sorting ...
  2639. TEdge* e = m_ActiveEdges;
  2640. m_SortedEdges = e;
  2641. while( e )
  2642. {
  2643. e->PrevInSEL = e->PrevInAEL;
  2644. e->NextInSEL = e->NextInAEL;
  2645. e->Curr.X = TopX( *e, topY );
  2646. e = e->NextInAEL;
  2647. }
  2648. //bubblesort ...
  2649. bool isModified;
  2650. do
  2651. {
  2652. isModified = false;
  2653. e = m_SortedEdges;
  2654. while( e->NextInSEL )
  2655. {
  2656. TEdge *eNext = e->NextInSEL;
  2657. IntPoint Pt;
  2658. if(e->Curr.X > eNext->Curr.X)
  2659. {
  2660. IntersectPoint(*e, *eNext, Pt);
  2661. if (Pt.Y < topY) Pt = IntPoint(TopX(*e, topY), topY);
  2662. IntersectNode * newNode = new IntersectNode;
  2663. newNode->Edge1 = e;
  2664. newNode->Edge2 = eNext;
  2665. newNode->Pt = Pt;
  2666. m_IntersectList.push_back(newNode);
  2667. SwapPositionsInSEL(e, eNext);
  2668. isModified = true;
  2669. }
  2670. else
  2671. e = eNext;
  2672. }
  2673. if( e->PrevInSEL ) e->PrevInSEL->NextInSEL = 0;
  2674. else break;
  2675. }
  2676. while ( isModified );
  2677. m_SortedEdges = 0; //important
  2678. }
  2679. //------------------------------------------------------------------------------
  2680. void Clipper::ProcessIntersectList()
  2681. {
  2682. for (size_t i = 0; i < m_IntersectList.size(); ++i)
  2683. {
  2684. IntersectNode* iNode = m_IntersectList[i];
  2685. {
  2686. IntersectEdges( iNode->Edge1, iNode->Edge2, iNode->Pt);
  2687. SwapPositionsInAEL( iNode->Edge1 , iNode->Edge2 );
  2688. }
  2689. delete iNode;
  2690. }
  2691. m_IntersectList.clear();
  2692. }
  2693. //------------------------------------------------------------------------------
  2694. bool IntersectListSort(IntersectNode* node1, IntersectNode* node2)
  2695. {
  2696. return node2->Pt.Y < node1->Pt.Y;
  2697. }
  2698. //------------------------------------------------------------------------------
  2699. inline bool EdgesAdjacent(const IntersectNode &inode)
  2700. {
  2701. return (inode.Edge1->NextInSEL == inode.Edge2) ||
  2702. (inode.Edge1->PrevInSEL == inode.Edge2);
  2703. }
  2704. //------------------------------------------------------------------------------
  2705. bool Clipper::FixupIntersectionOrder()
  2706. {
  2707. //pre-condition: intersections are sorted Bottom-most first.
  2708. //Now it's crucial that intersections are made only between adjacent edges,
  2709. //so to ensure this the order of intersections may need adjusting ...
  2710. CopyAELToSEL();
  2711. std::sort(m_IntersectList.begin(), m_IntersectList.end(), IntersectListSort);
  2712. size_t cnt = m_IntersectList.size();
  2713. for (size_t i = 0; i < cnt; ++i)
  2714. {
  2715. if (!EdgesAdjacent(*m_IntersectList[i]))
  2716. {
  2717. size_t j = i + 1;
  2718. while (j < cnt && !EdgesAdjacent(*m_IntersectList[j])) j++;
  2719. if (j == cnt) return false;
  2720. std::swap(m_IntersectList[i], m_IntersectList[j]);
  2721. }
  2722. SwapPositionsInSEL(m_IntersectList[i]->Edge1, m_IntersectList[i]->Edge2);
  2723. }
  2724. return true;
  2725. }
  2726. //------------------------------------------------------------------------------
  2727. void Clipper::DoMaxima(TEdge *e)
  2728. {
  2729. TEdge* eMaxPair = GetMaximaPairEx(e);
  2730. if (!eMaxPair)
  2731. {
  2732. if (e->OutIdx >= 0)
  2733. AddOutPt(e, e->Top);
  2734. DeleteFromAEL(e);
  2735. return;
  2736. }
  2737. TEdge* eNext = e->NextInAEL;
  2738. while(eNext && eNext != eMaxPair)
  2739. {
  2740. IntersectEdges(e, eNext, e->Top);
  2741. SwapPositionsInAEL(e, eNext);
  2742. eNext = e->NextInAEL;
  2743. }
  2744. if(e->OutIdx == Unassigned && eMaxPair->OutIdx == Unassigned)
  2745. {
  2746. DeleteFromAEL(e);
  2747. DeleteFromAEL(eMaxPair);
  2748. }
  2749. else if( e->OutIdx >= 0 && eMaxPair->OutIdx >= 0 )
  2750. {
  2751. if (e->OutIdx >= 0) AddLocalMaxPoly(e, eMaxPair, e->Top);
  2752. DeleteFromAEL(e);
  2753. DeleteFromAEL(eMaxPair);
  2754. }
  2755. #ifdef use_lines
  2756. else if (e->WindDelta == 0)
  2757. {
  2758. if (e->OutIdx >= 0)
  2759. {
  2760. AddOutPt(e, e->Top);
  2761. e->OutIdx = Unassigned;
  2762. }
  2763. DeleteFromAEL(e);
  2764. if (eMaxPair->OutIdx >= 0)
  2765. {
  2766. AddOutPt(eMaxPair, e->Top);
  2767. eMaxPair->OutIdx = Unassigned;
  2768. }
  2769. DeleteFromAEL(eMaxPair);
  2770. }
  2771. #endif
  2772. else CLIPPER_THROW(clipperException("DoMaxima error"));
  2773. }
  2774. //------------------------------------------------------------------------------
  2775. void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
  2776. {
  2777. TEdge* e = m_ActiveEdges;
  2778. while( e )
  2779. {
  2780. //1. process maxima, treating them as if they're 'bent' horizontal edges,
  2781. // but exclude maxima with horizontal edges. nb: e can't be a horizontal.
  2782. bool IsMaximaEdge = IsMaxima(e, topY);
  2783. if(IsMaximaEdge)
  2784. {
  2785. TEdge* eMaxPair = GetMaximaPairEx(e);
  2786. IsMaximaEdge = (!eMaxPair || !IsHorizontal(*eMaxPair));
  2787. }
  2788. if(IsMaximaEdge)
  2789. {
  2790. if (m_StrictSimple) m_Maxima.push_back(e->Top.X);
  2791. TEdge* ePrev = e->PrevInAEL;
  2792. DoMaxima(e);
  2793. if( !ePrev ) e = m_ActiveEdges;
  2794. else e = ePrev->NextInAEL;
  2795. }
  2796. else
  2797. {
  2798. //2. promote horizontal edges, otherwise update Curr.X and Curr.Y ...
  2799. if (IsIntermediate(e, topY) && IsHorizontal(*e->NextInLML))
  2800. {
  2801. UpdateEdgeIntoAEL(e);
  2802. if (e->OutIdx >= 0)
  2803. AddOutPt(e, e->Bot);
  2804. AddEdgeToSEL(e);
  2805. }
  2806. else
  2807. {
  2808. e->Curr.X = TopX( *e, topY );
  2809. e->Curr.Y = topY;
  2810. #ifdef use_xyz
  2811. e->Curr.Z = topY == e->Top.Y ? e->Top.Z : (topY == e->Bot.Y ? e->Bot.Z : 0);
  2812. #endif
  2813. }
  2814. //When StrictlySimple and 'e' is being touched by another edge, then
  2815. //make sure both edges have a vertex here ...
  2816. if (m_StrictSimple)
  2817. {
  2818. TEdge* ePrev = e->PrevInAEL;
  2819. if ((e->OutIdx >= 0) && (e->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) &&
  2820. (ePrev->Curr.X == e->Curr.X) && (ePrev->WindDelta != 0))
  2821. {
  2822. IntPoint pt = e->Curr;
  2823. #ifdef use_xyz
  2824. SetZ(pt, *ePrev, *e);
  2825. #endif
  2826. OutPt* op = AddOutPt(ePrev, pt);
  2827. OutPt* op2 = AddOutPt(e, pt);
  2828. AddJoin(op, op2, pt); //StrictlySimple (type-3) join
  2829. }
  2830. }
  2831. e = e->NextInAEL;
  2832. }
  2833. }
  2834. //3. Process horizontals at the Top of the scanbeam ...
  2835. m_Maxima.sort();
  2836. ProcessHorizontals();
  2837. m_Maxima.clear();
  2838. //4. Promote intermediate vertices ...
  2839. e = m_ActiveEdges;
  2840. while(e)
  2841. {
  2842. if(IsIntermediate(e, topY))
  2843. {
  2844. OutPt* op = 0;
  2845. if( e->OutIdx >= 0 )
  2846. op = AddOutPt(e, e->Top);
  2847. UpdateEdgeIntoAEL(e);
  2848. //if output polygons share an edge, they'll need joining later ...
  2849. TEdge* ePrev = e->PrevInAEL;
  2850. TEdge* eNext = e->NextInAEL;
  2851. if (ePrev && ePrev->Curr.X == e->Bot.X &&
  2852. ePrev->Curr.Y == e->Bot.Y && op &&
  2853. ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y &&
  2854. SlopesEqual(e->Curr, e->Top, ePrev->Curr, ePrev->Top, m_UseFullRange) &&
  2855. (e->WindDelta != 0) && (ePrev->WindDelta != 0))
  2856. {
  2857. OutPt* op2 = AddOutPt(ePrev, e->Bot);
  2858. AddJoin(op, op2, e->Top);
  2859. }
  2860. else if (eNext && eNext->Curr.X == e->Bot.X &&
  2861. eNext->Curr.Y == e->Bot.Y && op &&
  2862. eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y &&
  2863. SlopesEqual(e->Curr, e->Top, eNext->Curr, eNext->Top, m_UseFullRange) &&
  2864. (e->WindDelta != 0) && (eNext->WindDelta != 0))
  2865. {
  2866. OutPt* op2 = AddOutPt(eNext, e->Bot);
  2867. AddJoin(op, op2, e->Top);
  2868. }
  2869. }
  2870. e = e->NextInAEL;
  2871. }
  2872. }
  2873. //------------------------------------------------------------------------------
  2874. void Clipper::FixupOutPolyline(OutRec &outrec)
  2875. {
  2876. OutPt *pp = outrec.Pts;
  2877. OutPt *lastPP = pp->Prev;
  2878. while (pp != lastPP)
  2879. {
  2880. pp = pp->Next;
  2881. if (pp->Pt == pp->Prev->Pt)
  2882. {
  2883. if (pp == lastPP) lastPP = pp->Prev;
  2884. OutPt *tmpPP = pp->Prev;
  2885. tmpPP->Next = pp->Next;
  2886. pp->Next->Prev = tmpPP;
  2887. delete pp;
  2888. pp = tmpPP;
  2889. }
  2890. }
  2891. if (pp == pp->Prev)
  2892. {
  2893. DisposeOutPts(pp);
  2894. outrec.Pts = 0;
  2895. return;
  2896. }
  2897. }
  2898. //------------------------------------------------------------------------------
  2899. void Clipper::FixupOutPolygon(OutRec &outrec)
  2900. {
  2901. //FixupOutPolygon() - removes duplicate points and simplifies consecutive
  2902. //parallel edges by removing the middle vertex.
  2903. OutPt *lastOK = 0;
  2904. outrec.BottomPt = 0;
  2905. OutPt *pp = outrec.Pts;
  2906. bool preserveCol = m_PreserveCollinear || m_StrictSimple;
  2907. for (;;)
  2908. {
  2909. if (pp->Prev == pp || pp->Prev == pp->Next)
  2910. {
  2911. DisposeOutPts(pp);
  2912. outrec.Pts = 0;
  2913. return;
  2914. }
  2915. //test for duplicate points and collinear edges ...
  2916. if ((pp->Pt == pp->Next->Pt) || (pp->Pt == pp->Prev->Pt) ||
  2917. (SlopesEqual(pp->Prev->Pt, pp->Pt, pp->Next->Pt, m_UseFullRange) &&
  2918. (!preserveCol || !Pt2IsBetweenPt1AndPt3(pp->Prev->Pt, pp->Pt, pp->Next->Pt))))
  2919. {
  2920. lastOK = 0;
  2921. OutPt *tmp = pp;
  2922. pp->Prev->Next = pp->Next;
  2923. pp->Next->Prev = pp->Prev;
  2924. pp = pp->Prev;
  2925. delete tmp;
  2926. }
  2927. else if (pp == lastOK) break;
  2928. else
  2929. {
  2930. if (!lastOK) lastOK = pp;
  2931. pp = pp->Next;
  2932. }
  2933. }
  2934. outrec.Pts = pp;
  2935. }
  2936. //------------------------------------------------------------------------------
  2937. int PointCount(OutPt *Pts)
  2938. {
  2939. if (!Pts) return 0;
  2940. int result = 0;
  2941. OutPt* p = Pts;
  2942. do
  2943. {
  2944. result++;
  2945. p = p->Next;
  2946. }
  2947. while (p != Pts);
  2948. return result;
  2949. }
  2950. //------------------------------------------------------------------------------
  2951. void Clipper::BuildResult(Paths &polys)
  2952. {
  2953. polys.reserve(m_PolyOuts.size());
  2954. for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
  2955. {
  2956. if (!m_PolyOuts[i]->Pts) continue;
  2957. Path pg;
  2958. OutPt* p = m_PolyOuts[i]->Pts->Prev;
  2959. int cnt = PointCount(p);
  2960. if (cnt < 2) continue;
  2961. pg.reserve(cnt);
  2962. for (int i = 0; i < cnt; ++i)
  2963. {
  2964. pg.push_back(p->Pt);
  2965. p = p->Prev;
  2966. }
  2967. polys.push_back(pg);
  2968. }
  2969. }
  2970. //------------------------------------------------------------------------------
  2971. void Clipper::BuildResult2(PolyTree& polytree)
  2972. {
  2973. polytree.Clear();
  2974. polytree.AllNodes.reserve(m_PolyOuts.size());
  2975. //add each output polygon/contour to polytree ...
  2976. for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); i++)
  2977. {
  2978. OutRec* outRec = m_PolyOuts[i];
  2979. int cnt = PointCount(outRec->Pts);
  2980. if ((outRec->IsOpen && cnt < 2) || (!outRec->IsOpen && cnt < 3)) continue;
  2981. FixHoleLinkage(*outRec);
  2982. PolyNode* pn = new PolyNode();
  2983. //nb: polytree takes ownership of all the PolyNodes
  2984. polytree.AllNodes.push_back(pn);
  2985. outRec->PolyNd = pn;
  2986. pn->Parent = 0;
  2987. pn->Index = 0;
  2988. pn->Contour.reserve(cnt);
  2989. OutPt *op = outRec->Pts->Prev;
  2990. for (int j = 0; j < cnt; j++)
  2991. {
  2992. pn->Contour.push_back(op->Pt);
  2993. op = op->Prev;
  2994. }
  2995. }
  2996. //fixup PolyNode links etc ...
  2997. polytree.Childs.reserve(m_PolyOuts.size());
  2998. for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); i++)
  2999. {
  3000. OutRec* outRec = m_PolyOuts[i];
  3001. if (!outRec->PolyNd) continue;
  3002. if (outRec->IsOpen)
  3003. {
  3004. outRec->PolyNd->m_IsOpen = true;
  3005. polytree.AddChild(*outRec->PolyNd);
  3006. }
  3007. else if (outRec->FirstLeft && outRec->FirstLeft->PolyNd)
  3008. outRec->FirstLeft->PolyNd->AddChild(*outRec->PolyNd);
  3009. else
  3010. polytree.AddChild(*outRec->PolyNd);
  3011. }
  3012. }
  3013. //------------------------------------------------------------------------------
  3014. void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2)
  3015. {
  3016. //just swap the contents (because fIntersectNodes is a single-linked-list)
  3017. IntersectNode inode = int1; //gets a copy of Int1
  3018. int1.Edge1 = int2.Edge1;
  3019. int1.Edge2 = int2.Edge2;
  3020. int1.Pt = int2.Pt;
  3021. int2.Edge1 = inode.Edge1;
  3022. int2.Edge2 = inode.Edge2;
  3023. int2.Pt = inode.Pt;
  3024. }
  3025. //------------------------------------------------------------------------------
  3026. inline bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2)
  3027. {
  3028. if (e2.Curr.X == e1.Curr.X)
  3029. {
  3030. if (e2.Top.Y > e1.Top.Y)
  3031. return e2.Top.X < TopX(e1, e2.Top.Y);
  3032. else return e1.Top.X > TopX(e2, e1.Top.Y);
  3033. }
  3034. else return e2.Curr.X < e1.Curr.X;
  3035. }
  3036. //------------------------------------------------------------------------------
  3037. bool GetOverlap(const cInt a1, const cInt a2, const cInt b1, const cInt b2,
  3038. cInt& Left, cInt& Right)
  3039. {
  3040. if (a1 < a2)
  3041. {
  3042. if (b1 < b2) {Left = std::max(a1,b1); Right = std::min(a2,b2);}
  3043. else {Left = std::max(a1,b2); Right = std::min(a2,b1);}
  3044. }
  3045. else
  3046. {
  3047. if (b1 < b2) {Left = std::max(a2,b1); Right = std::min(a1,b2);}
  3048. else {Left = std::max(a2,b2); Right = std::min(a1,b1);}
  3049. }
  3050. return Left < Right;
  3051. }
  3052. //------------------------------------------------------------------------------
  3053. inline void UpdateOutPtIdxs(OutRec& outrec)
  3054. {
  3055. OutPt* op = outrec.Pts;
  3056. do
  3057. {
  3058. op->Idx = outrec.Idx;
  3059. op = op->Prev;
  3060. }
  3061. while(op != outrec.Pts);
  3062. }
  3063. //------------------------------------------------------------------------------
  3064. void Clipper::InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge)
  3065. {
  3066. if(!m_ActiveEdges)
  3067. {
  3068. edge->PrevInAEL = 0;
  3069. edge->NextInAEL = 0;
  3070. m_ActiveEdges = edge;
  3071. }
  3072. else if(!startEdge && E2InsertsBeforeE1(*m_ActiveEdges, *edge))
  3073. {
  3074. edge->PrevInAEL = 0;
  3075. edge->NextInAEL = m_ActiveEdges;
  3076. m_ActiveEdges->PrevInAEL = edge;
  3077. m_ActiveEdges = edge;
  3078. }
  3079. else
  3080. {
  3081. if(!startEdge) startEdge = m_ActiveEdges;
  3082. while(startEdge->NextInAEL &&
  3083. !E2InsertsBeforeE1(*startEdge->NextInAEL , *edge))
  3084. startEdge = startEdge->NextInAEL;
  3085. edge->NextInAEL = startEdge->NextInAEL;
  3086. if(startEdge->NextInAEL) startEdge->NextInAEL->PrevInAEL = edge;
  3087. edge->PrevInAEL = startEdge;
  3088. startEdge->NextInAEL = edge;
  3089. }
  3090. }
  3091. //----------------------------------------------------------------------
  3092. OutPt* DupOutPt(OutPt* outPt, bool InsertAfter)
  3093. {
  3094. OutPt* result = new OutPt;
  3095. result->Pt = outPt->Pt;
  3096. result->Idx = outPt->Idx;
  3097. if (InsertAfter)
  3098. {
  3099. result->Next = outPt->Next;
  3100. result->Prev = outPt;
  3101. outPt->Next->Prev = result;
  3102. outPt->Next = result;
  3103. }
  3104. else
  3105. {
  3106. result->Prev = outPt->Prev;
  3107. result->Next = outPt;
  3108. outPt->Prev->Next = result;
  3109. outPt->Prev = result;
  3110. }
  3111. return result;
  3112. }
  3113. //------------------------------------------------------------------------------
  3114. bool JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b,
  3115. const IntPoint Pt, bool DiscardLeft)
  3116. {
  3117. Direction Dir1 = (op1->Pt.X > op1b->Pt.X ? dRightToLeft : dLeftToRight);
  3118. Direction Dir2 = (op2->Pt.X > op2b->Pt.X ? dRightToLeft : dLeftToRight);
  3119. if (Dir1 == Dir2) return false;
  3120. //When DiscardLeft, we want Op1b to be on the Left of Op1, otherwise we
  3121. //want Op1b to be on the Right. (And likewise with Op2 and Op2b.)
  3122. //So, to facilitate this while inserting Op1b and Op2b ...
  3123. //when DiscardLeft, make sure we're AT or RIGHT of Pt before adding Op1b,
  3124. //otherwise make sure we're AT or LEFT of Pt. (Likewise with Op2b.)
  3125. if (Dir1 == dLeftToRight)
  3126. {
  3127. while (op1->Next->Pt.X <= Pt.X &&
  3128. op1->Next->Pt.X >= op1->Pt.X && op1->Next->Pt.Y == Pt.Y)
  3129. op1 = op1->Next;
  3130. if (DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next;
  3131. op1b = DupOutPt(op1, !DiscardLeft);
  3132. if (op1b->Pt != Pt)
  3133. {
  3134. op1 = op1b;
  3135. op1->Pt = Pt;
  3136. op1b = DupOutPt(op1, !DiscardLeft);
  3137. }
  3138. }
  3139. else
  3140. {
  3141. while (op1->Next->Pt.X >= Pt.X &&
  3142. op1->Next->Pt.X <= op1->Pt.X && op1->Next->Pt.Y == Pt.Y)
  3143. op1 = op1->Next;
  3144. if (!DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next;
  3145. op1b = DupOutPt(op1, DiscardLeft);
  3146. if (op1b->Pt != Pt)
  3147. {
  3148. op1 = op1b;
  3149. op1->Pt = Pt;
  3150. op1b = DupOutPt(op1, DiscardLeft);
  3151. }
  3152. }
  3153. if (Dir2 == dLeftToRight)
  3154. {
  3155. while (op2->Next->Pt.X <= Pt.X &&
  3156. op2->Next->Pt.X >= op2->Pt.X && op2->Next->Pt.Y == Pt.Y)
  3157. op2 = op2->Next;
  3158. if (DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next;
  3159. op2b = DupOutPt(op2, !DiscardLeft);
  3160. if (op2b->Pt != Pt)
  3161. {
  3162. op2 = op2b;
  3163. op2->Pt = Pt;
  3164. op2b = DupOutPt(op2, !DiscardLeft);
  3165. };
  3166. } else
  3167. {
  3168. while (op2->Next->Pt.X >= Pt.X &&
  3169. op2->Next->Pt.X <= op2->Pt.X && op2->Next->Pt.Y == Pt.Y)
  3170. op2 = op2->Next;
  3171. if (!DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next;
  3172. op2b = DupOutPt(op2, DiscardLeft);
  3173. if (op2b->Pt != Pt)
  3174. {
  3175. op2 = op2b;
  3176. op2->Pt = Pt;
  3177. op2b = DupOutPt(op2, DiscardLeft);
  3178. };
  3179. };
  3180. if ((Dir1 == dLeftToRight) == DiscardLeft)
  3181. {
  3182. op1->Prev = op2;
  3183. op2->Next = op1;
  3184. op1b->Next = op2b;
  3185. op2b->Prev = op1b;
  3186. }
  3187. else
  3188. {
  3189. op1->Next = op2;
  3190. op2->Prev = op1;
  3191. op1b->Prev = op2b;
  3192. op2b->Next = op1b;
  3193. }
  3194. return true;
  3195. }
  3196. //------------------------------------------------------------------------------
  3197. bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
  3198. {
  3199. OutPt *op1 = j->OutPt1, *op1b;
  3200. OutPt *op2 = j->OutPt2, *op2b;
  3201. //There are 3 kinds of joins for output polygons ...
  3202. //1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are vertices anywhere
  3203. //along (horizontal) collinear edges (& Join.OffPt is on the same horizontal).
  3204. //2. Non-horizontal joins where Join.OutPt1 & Join.OutPt2 are at the same
  3205. //location at the Bottom of the overlapping segment (& Join.OffPt is above).
  3206. //3. StrictSimple joins where edges touch but are not collinear and where
  3207. //Join.OutPt1, Join.OutPt2 & Join.OffPt all share the same point.
  3208. bool isHorizontal = (j->OutPt1->Pt.Y == j->OffPt.Y);
  3209. if (isHorizontal && (j->OffPt == j->OutPt1->Pt) &&
  3210. (j->OffPt == j->OutPt2->Pt))
  3211. {
  3212. //Strictly Simple join ...
  3213. if (outRec1 != outRec2) return false;
  3214. op1b = j->OutPt1->Next;
  3215. while (op1b != op1 && (op1b->Pt == j->OffPt))
  3216. op1b = op1b->Next;
  3217. bool reverse1 = (op1b->Pt.Y > j->OffPt.Y);
  3218. op2b = j->OutPt2->Next;
  3219. while (op2b != op2 && (op2b->Pt == j->OffPt))
  3220. op2b = op2b->Next;
  3221. bool reverse2 = (op2b->Pt.Y > j->OffPt.Y);
  3222. if (reverse1 == reverse2) return false;
  3223. if (reverse1)
  3224. {
  3225. op1b = DupOutPt(op1, false);
  3226. op2b = DupOutPt(op2, true);
  3227. op1->Prev = op2;
  3228. op2->Next = op1;
  3229. op1b->Next = op2b;
  3230. op2b->Prev = op1b;
  3231. j->OutPt1 = op1;
  3232. j->OutPt2 = op1b;
  3233. return true;
  3234. } else
  3235. {
  3236. op1b = DupOutPt(op1, true);
  3237. op2b = DupOutPt(op2, false);
  3238. op1->Next = op2;
  3239. op2->Prev = op1;
  3240. op1b->Prev = op2b;
  3241. op2b->Next = op1b;
  3242. j->OutPt1 = op1;
  3243. j->OutPt2 = op1b;
  3244. return true;
  3245. }
  3246. }
  3247. else if (isHorizontal)
  3248. {
  3249. //treat horizontal joins differently to non-horizontal joins since with
  3250. //them we're not yet sure where the overlapping is. OutPt1.Pt & OutPt2.Pt
  3251. //may be anywhere along the horizontal edge.
  3252. op1b = op1;
  3253. while (op1->Prev->Pt.Y == op1->Pt.Y && op1->Prev != op1b && op1->Prev != op2)
  3254. op1 = op1->Prev;
  3255. while (op1b->Next->Pt.Y == op1b->Pt.Y && op1b->Next != op1 && op1b->Next != op2)
  3256. op1b = op1b->Next;
  3257. if (op1b->Next == op1 || op1b->Next == op2) return false; //a flat 'polygon'
  3258. op2b = op2;
  3259. while (op2->Prev->Pt.Y == op2->Pt.Y && op2->Prev != op2b && op2->Prev != op1b)
  3260. op2 = op2->Prev;
  3261. while (op2b->Next->Pt.Y == op2b->Pt.Y && op2b->Next != op2 && op2b->Next != op1)
  3262. op2b = op2b->Next;
  3263. if (op2b->Next == op2 || op2b->Next == op1) return false; //a flat 'polygon'
  3264. cInt Left, Right;
  3265. //Op1 --> Op1b & Op2 --> Op2b are the extremites of the horizontal edges
  3266. if (!GetOverlap(op1->Pt.X, op1b->Pt.X, op2->Pt.X, op2b->Pt.X, Left, Right))
  3267. return false;
  3268. //DiscardLeftSide: when overlapping edges are joined, a spike will created
  3269. //which needs to be cleaned up. However, we don't want Op1 or Op2 caught up
  3270. //on the discard Side as either may still be needed for other joins ...
  3271. IntPoint Pt;
  3272. bool DiscardLeftSide;
  3273. if (op1->Pt.X >= Left && op1->Pt.X <= Right)
  3274. {
  3275. Pt = op1->Pt; DiscardLeftSide = (op1->Pt.X > op1b->Pt.X);
  3276. }
  3277. else if (op2->Pt.X >= Left&& op2->Pt.X <= Right)
  3278. {
  3279. Pt = op2->Pt; DiscardLeftSide = (op2->Pt.X > op2b->Pt.X);
  3280. }
  3281. else if (op1b->Pt.X >= Left && op1b->Pt.X <= Right)
  3282. {
  3283. Pt = op1b->Pt; DiscardLeftSide = op1b->Pt.X > op1->Pt.X;
  3284. }
  3285. else
  3286. {
  3287. Pt = op2b->Pt; DiscardLeftSide = (op2b->Pt.X > op2->Pt.X);
  3288. }
  3289. j->OutPt1 = op1; j->OutPt2 = op2;
  3290. return JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide);
  3291. } else
  3292. {
  3293. //nb: For non-horizontal joins ...
  3294. // 1. Jr.OutPt1.Pt.Y == Jr.OutPt2.Pt.Y
  3295. // 2. Jr.OutPt1.Pt > Jr.OffPt.Y
  3296. //make sure the polygons are correctly oriented ...
  3297. op1b = op1->Next;
  3298. while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Next;
  3299. bool Reverse1 = ((op1b->Pt.Y > op1->Pt.Y) ||
  3300. !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange));
  3301. if (Reverse1)
  3302. {
  3303. op1b = op1->Prev;
  3304. while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Prev;
  3305. if ((op1b->Pt.Y > op1->Pt.Y) ||
  3306. !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)) return false;
  3307. };
  3308. op2b = op2->Next;
  3309. while ((op2b->Pt == op2->Pt) && (op2b != op2))op2b = op2b->Next;
  3310. bool Reverse2 = ((op2b->Pt.Y > op2->Pt.Y) ||
  3311. !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange));
  3312. if (Reverse2)
  3313. {
  3314. op2b = op2->Prev;
  3315. while ((op2b->Pt == op2->Pt) && (op2b != op2)) op2b = op2b->Prev;
  3316. if ((op2b->Pt.Y > op2->Pt.Y) ||
  3317. !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)) return false;
  3318. }
  3319. if ((op1b == op1) || (op2b == op2) || (op1b == op2b) ||
  3320. ((outRec1 == outRec2) && (Reverse1 == Reverse2))) return false;
  3321. if (Reverse1)
  3322. {
  3323. op1b = DupOutPt(op1, false);
  3324. op2b = DupOutPt(op2, true);
  3325. op1->Prev = op2;
  3326. op2->Next = op1;
  3327. op1b->Next = op2b;
  3328. op2b->Prev = op1b;
  3329. j->OutPt1 = op1;
  3330. j->OutPt2 = op1b;
  3331. return true;
  3332. } else
  3333. {
  3334. op1b = DupOutPt(op1, true);
  3335. op2b = DupOutPt(op2, false);
  3336. op1->Next = op2;
  3337. op2->Prev = op1;
  3338. op1b->Prev = op2b;
  3339. op2b->Next = op1b;
  3340. j->OutPt1 = op1;
  3341. j->OutPt2 = op1b;
  3342. return true;
  3343. }
  3344. }
  3345. }
  3346. //----------------------------------------------------------------------
  3347. static OutRec* ParseFirstLeft(OutRec* FirstLeft)
  3348. {
  3349. while (FirstLeft && !FirstLeft->Pts)
  3350. FirstLeft = FirstLeft->FirstLeft;
  3351. return FirstLeft;
  3352. }
  3353. //------------------------------------------------------------------------------
  3354. void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec)
  3355. {
  3356. //tests if NewOutRec contains the polygon before reassigning FirstLeft
  3357. for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
  3358. {
  3359. OutRec* outRec = m_PolyOuts[i];
  3360. OutRec* firstLeft = ParseFirstLeft(outRec->FirstLeft);
  3361. if (outRec->Pts && firstLeft == OldOutRec)
  3362. {
  3363. if (Poly2ContainsPoly1(outRec->Pts, NewOutRec->Pts))
  3364. outRec->FirstLeft = NewOutRec;
  3365. }
  3366. }
  3367. }
  3368. //----------------------------------------------------------------------
  3369. void Clipper::FixupFirstLefts2(OutRec* InnerOutRec, OutRec* OuterOutRec)
  3370. {
  3371. //A polygon has split into two such that one is now the inner of the other.
  3372. //It's possible that these polygons now wrap around other polygons, so check
  3373. //every polygon that's also contained by OuterOutRec's FirstLeft container
  3374. //(including 0) to see if they've become inner to the new inner polygon ...
  3375. OutRec* orfl = OuterOutRec->FirstLeft;
  3376. for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
  3377. {
  3378. OutRec* outRec = m_PolyOuts[i];
  3379. if (!outRec->Pts || outRec == OuterOutRec || outRec == InnerOutRec)
  3380. continue;
  3381. OutRec* firstLeft = ParseFirstLeft(outRec->FirstLeft);
  3382. if (firstLeft != orfl && firstLeft != InnerOutRec && firstLeft != OuterOutRec)
  3383. continue;
  3384. if (Poly2ContainsPoly1(outRec->Pts, InnerOutRec->Pts))
  3385. outRec->FirstLeft = InnerOutRec;
  3386. else if (Poly2ContainsPoly1(outRec->Pts, OuterOutRec->Pts))
  3387. outRec->FirstLeft = OuterOutRec;
  3388. else if (outRec->FirstLeft == InnerOutRec || outRec->FirstLeft == OuterOutRec)
  3389. outRec->FirstLeft = orfl;
  3390. }
  3391. }
  3392. //----------------------------------------------------------------------
  3393. void Clipper::FixupFirstLefts3(OutRec* OldOutRec, OutRec* NewOutRec)
  3394. {
  3395. //reassigns FirstLeft WITHOUT testing if NewOutRec contains the polygon
  3396. for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
  3397. {
  3398. OutRec* outRec = m_PolyOuts[i];
  3399. OutRec* firstLeft = ParseFirstLeft(outRec->FirstLeft);
  3400. if (outRec->Pts && firstLeft == OldOutRec)
  3401. outRec->FirstLeft = NewOutRec;
  3402. }
  3403. }
  3404. //----------------------------------------------------------------------
  3405. void Clipper::JoinCommonEdges()
  3406. {
  3407. for (JoinList::size_type i = 0; i < m_Joins.size(); i++)
  3408. {
  3409. Join* join = m_Joins[i];
  3410. OutRec *outRec1 = GetOutRec(join->OutPt1->Idx);
  3411. OutRec *outRec2 = GetOutRec(join->OutPt2->Idx);
  3412. if (!outRec1->Pts || !outRec2->Pts) continue;
  3413. if (outRec1->IsOpen || outRec2->IsOpen) continue;
  3414. //get the polygon fragment with the correct hole state (FirstLeft)
  3415. //before calling JoinPoints() ...
  3416. OutRec *holeStateRec;
  3417. if (outRec1 == outRec2) holeStateRec = outRec1;
  3418. else if (OutRec1RightOfOutRec2(outRec1, outRec2)) holeStateRec = outRec2;
  3419. else if (OutRec1RightOfOutRec2(outRec2, outRec1)) holeStateRec = outRec1;
  3420. else holeStateRec = GetLowermostRec(outRec1, outRec2);
  3421. if (!JoinPoints(join, outRec1, outRec2)) continue;
  3422. if (outRec1 == outRec2)
  3423. {
  3424. //instead of joining two polygons, we've just created a new one by
  3425. //splitting one polygon into two.
  3426. outRec1->Pts = join->OutPt1;
  3427. outRec1->BottomPt = 0;
  3428. outRec2 = CreateOutRec();
  3429. outRec2->Pts = join->OutPt2;
  3430. //update all OutRec2.Pts Idx's ...
  3431. UpdateOutPtIdxs(*outRec2);
  3432. if (Poly2ContainsPoly1(outRec2->Pts, outRec1->Pts))
  3433. {
  3434. //outRec1 contains outRec2 ...
  3435. outRec2->IsHole = !outRec1->IsHole;
  3436. outRec2->FirstLeft = outRec1;
  3437. if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1);
  3438. if ((outRec2->IsHole ^ m_ReverseOutput) == (Area(*outRec2) > 0))
  3439. ReversePolyPtLinks(outRec2->Pts);
  3440. } else if (Poly2ContainsPoly1(outRec1->Pts, outRec2->Pts))
  3441. {
  3442. //outRec2 contains outRec1 ...
  3443. outRec2->IsHole = outRec1->IsHole;
  3444. outRec1->IsHole = !outRec2->IsHole;
  3445. outRec2->FirstLeft = outRec1->FirstLeft;
  3446. outRec1->FirstLeft = outRec2;
  3447. if (m_UsingPolyTree) FixupFirstLefts2(outRec1, outRec2);
  3448. if ((outRec1->IsHole ^ m_ReverseOutput) == (Area(*outRec1) > 0))
  3449. ReversePolyPtLinks(outRec1->Pts);
  3450. }
  3451. else
  3452. {
  3453. //the 2 polygons are completely separate ...
  3454. outRec2->IsHole = outRec1->IsHole;
  3455. outRec2->FirstLeft = outRec1->FirstLeft;
  3456. //fixup FirstLeft pointers that may need reassigning to OutRec2
  3457. if (m_UsingPolyTree) FixupFirstLefts1(outRec1, outRec2);
  3458. }
  3459. } else
  3460. {
  3461. //joined 2 polygons together ...
  3462. outRec2->Pts = 0;
  3463. outRec2->BottomPt = 0;
  3464. outRec2->Idx = outRec1->Idx;
  3465. outRec1->IsHole = holeStateRec->IsHole;
  3466. if (holeStateRec == outRec2)
  3467. outRec1->FirstLeft = outRec2->FirstLeft;
  3468. outRec2->FirstLeft = outRec1;
  3469. if (m_UsingPolyTree) FixupFirstLefts3(outRec2, outRec1);
  3470. }
  3471. }
  3472. }
  3473. //------------------------------------------------------------------------------
  3474. // ClipperOffset support functions ...
  3475. //------------------------------------------------------------------------------
  3476. DoublePoint GetUnitNormal(const IntPoint &pt1, const IntPoint &pt2)
  3477. {
  3478. if(pt2.X == pt1.X && pt2.Y == pt1.Y)
  3479. return DoublePoint(0, 0);
  3480. double Dx = (double)(pt2.X - pt1.X);
  3481. double dy = (double)(pt2.Y - pt1.Y);
  3482. double f = 1 *1.0/ std::sqrt( Dx*Dx + dy*dy );
  3483. Dx *= f;
  3484. dy *= f;
  3485. return DoublePoint(dy, -Dx);
  3486. }
  3487. //------------------------------------------------------------------------------
  3488. // ClipperOffset class
  3489. //------------------------------------------------------------------------------
  3490. ClipperOffset::ClipperOffset(double miterLimit, double arcTolerance)
  3491. {
  3492. this->MiterLimit = miterLimit;
  3493. this->ArcTolerance = arcTolerance;
  3494. m_lowest.X = -1;
  3495. }
  3496. //------------------------------------------------------------------------------
  3497. ClipperOffset::~ClipperOffset()
  3498. {
  3499. Clear();
  3500. }
  3501. //------------------------------------------------------------------------------
  3502. void ClipperOffset::Clear()
  3503. {
  3504. for (int i = 0; i < m_polyNodes.ChildCount(); ++i)
  3505. delete m_polyNodes.Childs[i];
  3506. m_polyNodes.Childs.clear();
  3507. m_lowest.X = -1;
  3508. }
  3509. //------------------------------------------------------------------------------
  3510. void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType)
  3511. {
  3512. int highI = (int)path.size() - 1;
  3513. if (highI < 0) return;
  3514. PolyNode* newNode = new PolyNode();
  3515. newNode->m_jointype = joinType;
  3516. newNode->m_endtype = endType;
  3517. //strip duplicate points from path and also get index to the lowest point ...
  3518. if (endType == etClosedLine || endType == etClosedPolygon)
  3519. while (highI > 0 && path[0] == path[highI]) highI--;
  3520. newNode->Contour.reserve(highI + 1);
  3521. newNode->Contour.push_back(path[0]);
  3522. int j = 0, k = 0;
  3523. for (int i = 1; i <= highI; i++)
  3524. if (newNode->Contour[j] != path[i])
  3525. {
  3526. j++;
  3527. newNode->Contour.push_back(path[i]);
  3528. if (path[i].Y > newNode->Contour[k].Y ||
  3529. (path[i].Y == newNode->Contour[k].Y &&
  3530. path[i].X < newNode->Contour[k].X)) k = j;
  3531. }
  3532. if (endType == etClosedPolygon && j < 2)
  3533. {
  3534. delete newNode;
  3535. return;
  3536. }
  3537. m_polyNodes.AddChild(*newNode);
  3538. //if this path's lowest pt is lower than all the others then update m_lowest
  3539. if (endType != etClosedPolygon) return;
  3540. if (m_lowest.X < 0)
  3541. m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k);
  3542. else
  3543. {
  3544. IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X]->Contour[(int)m_lowest.Y];
  3545. if (newNode->Contour[k].Y > ip.Y ||
  3546. (newNode->Contour[k].Y == ip.Y &&
  3547. newNode->Contour[k].X < ip.X))
  3548. m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k);
  3549. }
  3550. }
  3551. //------------------------------------------------------------------------------
  3552. void ClipperOffset::AddPaths(const Paths& paths, JoinType joinType, EndType endType)
  3553. {
  3554. for (Paths::size_type i = 0; i < paths.size(); ++i)
  3555. AddPath(paths[i], joinType, endType);
  3556. }
  3557. //------------------------------------------------------------------------------
  3558. void ClipperOffset::FixOrientations()
  3559. {
  3560. //fixup orientations of all closed paths if the orientation of the
  3561. //closed path with the lowermost vertex is wrong ...
  3562. if (m_lowest.X >= 0 &&
  3563. !Orientation(m_polyNodes.Childs[(int)m_lowest.X]->Contour))
  3564. {
  3565. for (int i = 0; i < m_polyNodes.ChildCount(); ++i)
  3566. {
  3567. PolyNode& node = *m_polyNodes.Childs[i];
  3568. if (node.m_endtype == etClosedPolygon ||
  3569. (node.m_endtype == etClosedLine && Orientation(node.Contour)))
  3570. ReversePath(node.Contour);
  3571. }
  3572. } else
  3573. {
  3574. for (int i = 0; i < m_polyNodes.ChildCount(); ++i)
  3575. {
  3576. PolyNode& node = *m_polyNodes.Childs[i];
  3577. if (node.m_endtype == etClosedLine && !Orientation(node.Contour))
  3578. ReversePath(node.Contour);
  3579. }
  3580. }
  3581. }
  3582. //------------------------------------------------------------------------------
  3583. void ClipperOffset::Execute(Paths& solution, double delta)
  3584. {
  3585. solution.clear();
  3586. FixOrientations();
  3587. DoOffset(delta);
  3588. //now clean up 'corners' ...
  3589. Clipper clpr;
  3590. clpr.AddPaths(m_destPolys, ptSubject, true);
  3591. if (delta > 0)
  3592. {
  3593. clpr.Execute(ctUnion, solution, pftPositive, pftPositive);
  3594. }
  3595. else
  3596. {
  3597. IntRect r = clpr.GetBounds();
  3598. Path outer(4);
  3599. outer[0] = IntPoint(r.left - 10, r.bottom + 10);
  3600. outer[1] = IntPoint(r.right + 10, r.bottom + 10);
  3601. outer[2] = IntPoint(r.right + 10, r.top - 10);
  3602. outer[3] = IntPoint(r.left - 10, r.top - 10);
  3603. clpr.AddPath(outer, ptSubject, true);
  3604. clpr.ReverseSolution(true);
  3605. clpr.Execute(ctUnion, solution, pftNegative, pftNegative);
  3606. if (solution.size() > 0) solution.erase(solution.begin());
  3607. }
  3608. }
  3609. //------------------------------------------------------------------------------
  3610. void ClipperOffset::Execute(PolyTree& solution, double delta)
  3611. {
  3612. solution.Clear();
  3613. FixOrientations();
  3614. DoOffset(delta);
  3615. //now clean up 'corners' ...
  3616. Clipper clpr;
  3617. clpr.AddPaths(m_destPolys, ptSubject, true);
  3618. if (delta > 0)
  3619. {
  3620. clpr.Execute(ctUnion, solution, pftPositive, pftPositive);
  3621. }
  3622. else
  3623. {
  3624. IntRect r = clpr.GetBounds();
  3625. Path outer(4);
  3626. outer[0] = IntPoint(r.left - 10, r.bottom + 10);
  3627. outer[1] = IntPoint(r.right + 10, r.bottom + 10);
  3628. outer[2] = IntPoint(r.right + 10, r.top - 10);
  3629. outer[3] = IntPoint(r.left - 10, r.top - 10);
  3630. clpr.AddPath(outer, ptSubject, true);
  3631. clpr.ReverseSolution(true);
  3632. clpr.Execute(ctUnion, solution, pftNegative, pftNegative);
  3633. //remove the outer PolyNode rectangle ...
  3634. if (solution.ChildCount() == 1 && solution.Childs[0]->ChildCount() > 0)
  3635. {
  3636. PolyNode* outerNode = solution.Childs[0];
  3637. solution.Childs.reserve(outerNode->ChildCount());
  3638. solution.Childs[0] = outerNode->Childs[0];
  3639. solution.Childs[0]->Parent = outerNode->Parent;
  3640. for (int i = 1; i < outerNode->ChildCount(); ++i)
  3641. solution.AddChild(*outerNode->Childs[i]);
  3642. }
  3643. else
  3644. solution.Clear();
  3645. }
  3646. }
  3647. //------------------------------------------------------------------------------
  3648. void ClipperOffset::DoOffset(double delta)
  3649. {
  3650. m_destPolys.clear();
  3651. m_delta = delta;
  3652. //if Zero offset, just copy any CLOSED polygons to m_p and return ...
  3653. if (NEAR_ZERO(delta))
  3654. {
  3655. m_destPolys.reserve(m_polyNodes.ChildCount());
  3656. for (int i = 0; i < m_polyNodes.ChildCount(); i++)
  3657. {
  3658. PolyNode& node = *m_polyNodes.Childs[i];
  3659. if (node.m_endtype == etClosedPolygon)
  3660. m_destPolys.push_back(node.Contour);
  3661. }
  3662. return;
  3663. }
  3664. //see offset_triginometry3.svg in the documentation folder ...
  3665. if (MiterLimit > 2) m_miterLim = 2/(MiterLimit * MiterLimit);
  3666. else m_miterLim = 0.5;
  3667. double y;
  3668. if (ArcTolerance <= 0.0) y = def_arc_tolerance;
  3669. else if (ArcTolerance > std::fabs(delta) * def_arc_tolerance)
  3670. y = std::fabs(delta) * def_arc_tolerance;
  3671. else y = ArcTolerance;
  3672. //see offset_triginometry2.svg in the documentation folder ...
  3673. double steps = pi / std::acos(1 - y / std::fabs(delta));
  3674. if (steps > std::fabs(delta) * pi)
  3675. steps = std::fabs(delta) * pi; //ie excessive precision check
  3676. m_sin = std::sin(two_pi / steps);
  3677. m_cos = std::cos(two_pi / steps);
  3678. m_StepsPerRad = steps / two_pi;
  3679. if (delta < 0.0) m_sin = -m_sin;
  3680. m_destPolys.reserve(m_polyNodes.ChildCount() * 2);
  3681. for (int i = 0; i < m_polyNodes.ChildCount(); i++)
  3682. {
  3683. PolyNode& node = *m_polyNodes.Childs[i];
  3684. m_srcPoly = node.Contour;
  3685. int len = (int)m_srcPoly.size();
  3686. if (len == 0 || (delta <= 0 && (len < 3 || node.m_endtype != etClosedPolygon)))
  3687. continue;
  3688. m_destPoly.clear();
  3689. if (len == 1)
  3690. {
  3691. if (node.m_jointype == jtRound)
  3692. {
  3693. double X = 1.0, Y = 0.0;
  3694. for (cInt j = 1; j <= steps; j++)
  3695. {
  3696. m_destPoly.push_back(IntPoint(
  3697. Round(m_srcPoly[0].X + X * delta),
  3698. Round(m_srcPoly[0].Y + Y * delta)));
  3699. double X2 = X;
  3700. X = X * m_cos - m_sin * Y;
  3701. Y = X2 * m_sin + Y * m_cos;
  3702. }
  3703. }
  3704. else
  3705. {
  3706. double X = -1.0, Y = -1.0;
  3707. for (int j = 0; j < 4; ++j)
  3708. {
  3709. m_destPoly.push_back(IntPoint(
  3710. Round(m_srcPoly[0].X + X * delta),
  3711. Round(m_srcPoly[0].Y + Y * delta)));
  3712. if (X < 0) X = 1;
  3713. else if (Y < 0) Y = 1;
  3714. else X = -1;
  3715. }
  3716. }
  3717. m_destPolys.push_back(m_destPoly);
  3718. continue;
  3719. }
  3720. //build m_normals ...
  3721. m_normals.clear();
  3722. m_normals.reserve(len);
  3723. for (int j = 0; j < len - 1; ++j)
  3724. m_normals.push_back(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1]));
  3725. if (node.m_endtype == etClosedLine || node.m_endtype == etClosedPolygon)
  3726. m_normals.push_back(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0]));
  3727. else
  3728. m_normals.push_back(DoublePoint(m_normals[len - 2]));
  3729. if (node.m_endtype == etClosedPolygon)
  3730. {
  3731. int k = len - 1;
  3732. for (int j = 0; j < len; ++j)
  3733. OffsetPoint(j, k, node.m_jointype);
  3734. m_destPolys.push_back(m_destPoly);
  3735. }
  3736. else if (node.m_endtype == etClosedLine)
  3737. {
  3738. int k = len - 1;
  3739. for (int j = 0; j < len; ++j)
  3740. OffsetPoint(j, k, node.m_jointype);
  3741. m_destPolys.push_back(m_destPoly);
  3742. m_destPoly.clear();
  3743. //re-build m_normals ...
  3744. DoublePoint n = m_normals[len -1];
  3745. for (int j = len - 1; j > 0; j--)
  3746. m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y);
  3747. m_normals[0] = DoublePoint(-n.X, -n.Y);
  3748. k = 0;
  3749. for (int j = len - 1; j >= 0; j--)
  3750. OffsetPoint(j, k, node.m_jointype);
  3751. m_destPolys.push_back(m_destPoly);
  3752. }
  3753. else
  3754. {
  3755. int k = 0;
  3756. for (int j = 1; j < len - 1; ++j)
  3757. OffsetPoint(j, k, node.m_jointype);
  3758. IntPoint pt1;
  3759. if (node.m_endtype == etOpenButt)
  3760. {
  3761. int j = len - 1;
  3762. pt1 = IntPoint((cInt)Round(m_srcPoly[j].X + m_normals[j].X *
  3763. delta), (cInt)Round(m_srcPoly[j].Y + m_normals[j].Y * delta));
  3764. m_destPoly.push_back(pt1);
  3765. pt1 = IntPoint((cInt)Round(m_srcPoly[j].X - m_normals[j].X *
  3766. delta), (cInt)Round(m_srcPoly[j].Y - m_normals[j].Y * delta));
  3767. m_destPoly.push_back(pt1);
  3768. }
  3769. else
  3770. {
  3771. int j = len - 1;
  3772. k = len - 2;
  3773. m_sinA = 0;
  3774. m_normals[j] = DoublePoint(-m_normals[j].X, -m_normals[j].Y);
  3775. if (node.m_endtype == etOpenSquare)
  3776. DoSquare(j, k);
  3777. else
  3778. DoRound(j, k);
  3779. }
  3780. //re-build m_normals ...
  3781. for (int j = len - 1; j > 0; j--)
  3782. m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y);
  3783. m_normals[0] = DoublePoint(-m_normals[1].X, -m_normals[1].Y);
  3784. k = len - 1;
  3785. for (int j = k - 1; j > 0; --j) OffsetPoint(j, k, node.m_jointype);
  3786. if (node.m_endtype == etOpenButt)
  3787. {
  3788. pt1 = IntPoint((cInt)Round(m_srcPoly[0].X - m_normals[0].X * delta),
  3789. (cInt)Round(m_srcPoly[0].Y - m_normals[0].Y * delta));
  3790. m_destPoly.push_back(pt1);
  3791. pt1 = IntPoint((cInt)Round(m_srcPoly[0].X + m_normals[0].X * delta),
  3792. (cInt)Round(m_srcPoly[0].Y + m_normals[0].Y * delta));
  3793. m_destPoly.push_back(pt1);
  3794. }
  3795. else
  3796. {
  3797. k = 1;
  3798. m_sinA = 0;
  3799. if (node.m_endtype == etOpenSquare)
  3800. DoSquare(0, 1);
  3801. else
  3802. DoRound(0, 1);
  3803. }
  3804. m_destPolys.push_back(m_destPoly);
  3805. }
  3806. }
  3807. }
  3808. //------------------------------------------------------------------------------
  3809. void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype)
  3810. {
  3811. //cross product ...
  3812. m_sinA = (m_normals[k].X * m_normals[j].Y - m_normals[j].X * m_normals[k].Y);
  3813. if (std::fabs(m_sinA * m_delta) < 1.0)
  3814. {
  3815. //dot product ...
  3816. double cosA = (m_normals[k].X * m_normals[j].X + m_normals[j].Y * m_normals[k].Y );
  3817. if (cosA > 0) // angle => 0 degrees
  3818. {
  3819. m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta),
  3820. Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta)));
  3821. return;
  3822. }
  3823. //else angle => 180 degrees
  3824. }
  3825. else if (m_sinA > 1.0) m_sinA = 1.0;
  3826. else if (m_sinA < -1.0) m_sinA = -1.0;
  3827. if (m_sinA * m_delta < 0)
  3828. {
  3829. m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta),
  3830. Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta)));
  3831. m_destPoly.push_back(m_srcPoly[j]);
  3832. m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * m_delta),
  3833. Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta)));
  3834. }
  3835. else
  3836. switch (jointype)
  3837. {
  3838. case jtMiter:
  3839. {
  3840. double r = 1 + (m_normals[j].X * m_normals[k].X +
  3841. m_normals[j].Y * m_normals[k].Y);
  3842. if (r >= m_miterLim) DoMiter(j, k, r); else DoSquare(j, k);
  3843. break;
  3844. }
  3845. case jtSquare: DoSquare(j, k); break;
  3846. case jtRound: DoRound(j, k); break;
  3847. }
  3848. k = j;
  3849. }
  3850. //------------------------------------------------------------------------------
  3851. void ClipperOffset::DoSquare(int j, int k)
  3852. {
  3853. double dx = std::tan(std::atan2(m_sinA,
  3854. m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y) / 4);
  3855. m_destPoly.push_back(IntPoint(
  3856. Round(m_srcPoly[j].X + m_delta * (m_normals[k].X - m_normals[k].Y * dx)),
  3857. Round(m_srcPoly[j].Y + m_delta * (m_normals[k].Y + m_normals[k].X * dx))));
  3858. m_destPoly.push_back(IntPoint(
  3859. Round(m_srcPoly[j].X + m_delta * (m_normals[j].X + m_normals[j].Y * dx)),
  3860. Round(m_srcPoly[j].Y + m_delta * (m_normals[j].Y - m_normals[j].X * dx))));
  3861. }
  3862. //------------------------------------------------------------------------------
  3863. void ClipperOffset::DoMiter(int j, int k, double r)
  3864. {
  3865. double q = m_delta / r;
  3866. m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + (m_normals[k].X + m_normals[j].X) * q),
  3867. Round(m_srcPoly[j].Y + (m_normals[k].Y + m_normals[j].Y) * q)));
  3868. }
  3869. //------------------------------------------------------------------------------
  3870. void ClipperOffset::DoRound(int j, int k)
  3871. {
  3872. double a = std::atan2(m_sinA,
  3873. m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y);
  3874. int steps = std::max((int)Round(m_StepsPerRad * std::fabs(a)), 1);
  3875. double X = m_normals[k].X, Y = m_normals[k].Y, X2;
  3876. for (int i = 0; i < steps; ++i)
  3877. {
  3878. m_destPoly.push_back(IntPoint(
  3879. Round(m_srcPoly[j].X + X * m_delta),
  3880. Round(m_srcPoly[j].Y + Y * m_delta)));
  3881. X2 = X;
  3882. X = X * m_cos - m_sin * Y;
  3883. Y = X2 * m_sin + Y * m_cos;
  3884. }
  3885. m_destPoly.push_back(IntPoint(
  3886. Round(m_srcPoly[j].X + m_normals[j].X * m_delta),
  3887. Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta)));
  3888. }
  3889. //------------------------------------------------------------------------------
  3890. // Miscellaneous public functions
  3891. //------------------------------------------------------------------------------
  3892. void Clipper::DoSimplePolygons()
  3893. {
  3894. PolyOutList::size_type i = 0;
  3895. while (i < m_PolyOuts.size())
  3896. {
  3897. OutRec* outrec = m_PolyOuts[i++];
  3898. OutPt* op = outrec->Pts;
  3899. if (!op || outrec->IsOpen) continue;
  3900. do //for each Pt in Polygon until duplicate found do ...
  3901. {
  3902. OutPt* op2 = op->Next;
  3903. while (op2 != outrec->Pts)
  3904. {
  3905. if ((op->Pt == op2->Pt) && op2->Next != op && op2->Prev != op)
  3906. {
  3907. //split the polygon into two ...
  3908. OutPt* op3 = op->Prev;
  3909. OutPt* op4 = op2->Prev;
  3910. op->Prev = op4;
  3911. op4->Next = op;
  3912. op2->Prev = op3;
  3913. op3->Next = op2;
  3914. outrec->Pts = op;
  3915. OutRec* outrec2 = CreateOutRec();
  3916. outrec2->Pts = op2;
  3917. UpdateOutPtIdxs(*outrec2);
  3918. if (Poly2ContainsPoly1(outrec2->Pts, outrec->Pts))
  3919. {
  3920. //OutRec2 is contained by OutRec1 ...
  3921. outrec2->IsHole = !outrec->IsHole;
  3922. outrec2->FirstLeft = outrec;
  3923. if (m_UsingPolyTree) FixupFirstLefts2(outrec2, outrec);
  3924. }
  3925. else
  3926. if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts))
  3927. {
  3928. //OutRec1 is contained by OutRec2 ...
  3929. outrec2->IsHole = outrec->IsHole;
  3930. outrec->IsHole = !outrec2->IsHole;
  3931. outrec2->FirstLeft = outrec->FirstLeft;
  3932. outrec->FirstLeft = outrec2;
  3933. if (m_UsingPolyTree) FixupFirstLefts2(outrec, outrec2);
  3934. }
  3935. else
  3936. {
  3937. //the 2 polygons are separate ...
  3938. outrec2->IsHole = outrec->IsHole;
  3939. outrec2->FirstLeft = outrec->FirstLeft;
  3940. if (m_UsingPolyTree) FixupFirstLefts1(outrec, outrec2);
  3941. }
  3942. op2 = op; //ie get ready for the Next iteration
  3943. }
  3944. op2 = op2->Next;
  3945. }
  3946. op = op->Next;
  3947. }
  3948. while (op != outrec->Pts);
  3949. }
  3950. }
  3951. //------------------------------------------------------------------------------
  3952. void ReversePath(Path& p)
  3953. {
  3954. std::reverse(p.begin(), p.end());
  3955. }
  3956. //------------------------------------------------------------------------------
  3957. void ReversePaths(Paths& p)
  3958. {
  3959. for (Paths::size_type i = 0; i < p.size(); ++i)
  3960. ReversePath(p[i]);
  3961. }
  3962. //------------------------------------------------------------------------------
  3963. void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType)
  3964. {
  3965. Clipper c;
  3966. c.StrictlySimple(true);
  3967. c.AddPath(in_poly, ptSubject, true);
  3968. c.Execute(ctUnion, out_polys, fillType, fillType);
  3969. }
  3970. //------------------------------------------------------------------------------
  3971. void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType)
  3972. {
  3973. Clipper c;
  3974. c.StrictlySimple(true);
  3975. c.AddPaths(in_polys, ptSubject, true);
  3976. c.Execute(ctUnion, out_polys, fillType, fillType);
  3977. }
  3978. //------------------------------------------------------------------------------
  3979. void SimplifyPolygons(Paths &polys, PolyFillType fillType)
  3980. {
  3981. SimplifyPolygons(polys, polys, fillType);
  3982. }
  3983. //------------------------------------------------------------------------------
  3984. inline double DistanceSqrd(const IntPoint& pt1, const IntPoint& pt2)
  3985. {
  3986. double Dx = ((double)pt1.X - pt2.X);
  3987. double dy = ((double)pt1.Y - pt2.Y);
  3988. return (Dx*Dx + dy*dy);
  3989. }
  3990. //------------------------------------------------------------------------------
  3991. double DistanceFromLineSqrd(
  3992. const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2)
  3993. {
  3994. //The equation of a line in general form (Ax + By + C = 0)
  3995. //given 2 points (x¹,y¹) & (x²,y²) is ...
  3996. //(y¹ - y²)x + (x² - x¹)y + (y² - y¹)x¹ - (x² - x¹)y¹ = 0
  3997. //A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹
  3998. //perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²)
  3999. //see http://en.wikipedia.org/wiki/Perpendicular_distance
  4000. double A = double(ln1.Y - ln2.Y);
  4001. double B = double(ln2.X - ln1.X);
  4002. double C = A * ln1.X + B * ln1.Y;
  4003. C = A * pt.X + B * pt.Y - C;
  4004. return (C * C) / (A * A + B * B);
  4005. }
  4006. //---------------------------------------------------------------------------
  4007. bool SlopesNearCollinear(const IntPoint& pt1,
  4008. const IntPoint& pt2, const IntPoint& pt3, double distSqrd)
  4009. {
  4010. //this function is more accurate when the point that's geometrically
  4011. //between the other 2 points is the one that's tested for distance.
  4012. //ie makes it more likely to pick up 'spikes' ...
  4013. if (Abs(pt1.X - pt2.X) > Abs(pt1.Y - pt2.Y))
  4014. {
  4015. if ((pt1.X > pt2.X) == (pt1.X < pt3.X))
  4016. return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd;
  4017. else if ((pt2.X > pt1.X) == (pt2.X < pt3.X))
  4018. return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd;
  4019. else
  4020. return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd;
  4021. }
  4022. else
  4023. {
  4024. if ((pt1.Y > pt2.Y) == (pt1.Y < pt3.Y))
  4025. return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd;
  4026. else if ((pt2.Y > pt1.Y) == (pt2.Y < pt3.Y))
  4027. return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd;
  4028. else
  4029. return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd;
  4030. }
  4031. }
  4032. //------------------------------------------------------------------------------
  4033. bool PointsAreClose(IntPoint pt1, IntPoint pt2, double distSqrd)
  4034. {
  4035. double Dx = (double)pt1.X - pt2.X;
  4036. double dy = (double)pt1.Y - pt2.Y;
  4037. return ((Dx * Dx) + (dy * dy) <= distSqrd);
  4038. }
  4039. //------------------------------------------------------------------------------
  4040. OutPt* ExcludeOp(OutPt* op)
  4041. {
  4042. OutPt* result = op->Prev;
  4043. result->Next = op->Next;
  4044. op->Next->Prev = result;
  4045. result->Idx = 0;
  4046. return result;
  4047. }
  4048. //------------------------------------------------------------------------------
  4049. void CleanPolygon(const Path& in_poly, Path& out_poly, double distance)
  4050. {
  4051. //distance = proximity in units/pixels below which vertices
  4052. //will be stripped. Default ~= sqrt(2).
  4053. size_t size = in_poly.size();
  4054. if (size == 0)
  4055. {
  4056. out_poly.clear();
  4057. return;
  4058. }
  4059. OutPt* outPts = new OutPt[size];
  4060. for (size_t i = 0; i < size; ++i)
  4061. {
  4062. outPts[i].Pt = in_poly[i];
  4063. outPts[i].Next = &outPts[(i + 1) % size];
  4064. outPts[i].Next->Prev = &outPts[i];
  4065. outPts[i].Idx = 0;
  4066. }
  4067. double distSqrd = distance * distance;
  4068. OutPt* op = &outPts[0];
  4069. while (op->Idx == 0 && op->Next != op->Prev)
  4070. {
  4071. if (PointsAreClose(op->Pt, op->Prev->Pt, distSqrd))
  4072. {
  4073. op = ExcludeOp(op);
  4074. size--;
  4075. }
  4076. else if (PointsAreClose(op->Prev->Pt, op->Next->Pt, distSqrd))
  4077. {
  4078. ExcludeOp(op->Next);
  4079. op = ExcludeOp(op);
  4080. size -= 2;
  4081. }
  4082. else if (SlopesNearCollinear(op->Prev->Pt, op->Pt, op->Next->Pt, distSqrd))
  4083. {
  4084. op = ExcludeOp(op);
  4085. size--;
  4086. }
  4087. else
  4088. {
  4089. op->Idx = 1;
  4090. op = op->Next;
  4091. }
  4092. }
  4093. if (size < 3) size = 0;
  4094. out_poly.resize(size);
  4095. for (size_t i = 0; i < size; ++i)
  4096. {
  4097. out_poly[i] = op->Pt;
  4098. op = op->Next;
  4099. }
  4100. delete [] outPts;
  4101. }
  4102. //------------------------------------------------------------------------------
  4103. void CleanPolygon(Path& poly, double distance)
  4104. {
  4105. CleanPolygon(poly, poly, distance);
  4106. }
  4107. //------------------------------------------------------------------------------
  4108. void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance)
  4109. {
  4110. out_polys.resize(in_polys.size());
  4111. for (Paths::size_type i = 0; i < in_polys.size(); ++i)
  4112. CleanPolygon(in_polys[i], out_polys[i], distance);
  4113. }
  4114. //------------------------------------------------------------------------------
  4115. void CleanPolygons(Paths& polys, double distance)
  4116. {
  4117. CleanPolygons(polys, polys, distance);
  4118. }
  4119. //------------------------------------------------------------------------------
  4120. void Minkowski(const Path& poly, const Path& path,
  4121. Paths& solution, bool isSum, bool isClosed)
  4122. {
  4123. int delta = (isClosed ? 1 : 0);
  4124. size_t polyCnt = poly.size();
  4125. size_t pathCnt = path.size();
  4126. Paths pp;
  4127. pp.reserve(pathCnt);
  4128. if (isSum)
  4129. for (size_t i = 0; i < pathCnt; ++i)
  4130. {
  4131. Path p;
  4132. p.reserve(polyCnt);
  4133. for (size_t j = 0; j < poly.size(); ++j)
  4134. p.push_back(IntPoint(path[i].X + poly[j].X, path[i].Y + poly[j].Y));
  4135. pp.push_back(p);
  4136. }
  4137. else
  4138. for (size_t i = 0; i < pathCnt; ++i)
  4139. {
  4140. Path p;
  4141. p.reserve(polyCnt);
  4142. for (size_t j = 0; j < poly.size(); ++j)
  4143. p.push_back(IntPoint(path[i].X - poly[j].X, path[i].Y - poly[j].Y));
  4144. pp.push_back(p);
  4145. }
  4146. solution.clear();
  4147. solution.reserve((pathCnt + delta) * (polyCnt + 1));
  4148. for (size_t i = 0; i < pathCnt - 1 + delta; ++i)
  4149. for (size_t j = 0; j < polyCnt; ++j)
  4150. {
  4151. Path quad;
  4152. quad.reserve(4);
  4153. quad.push_back(pp[i % pathCnt][j % polyCnt]);
  4154. quad.push_back(pp[(i + 1) % pathCnt][j % polyCnt]);
  4155. quad.push_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]);
  4156. quad.push_back(pp[i % pathCnt][(j + 1) % polyCnt]);
  4157. if (!Orientation(quad)) ReversePath(quad);
  4158. solution.push_back(quad);
  4159. }
  4160. }
  4161. //------------------------------------------------------------------------------
  4162. void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed)
  4163. {
  4164. Minkowski(pattern, path, solution, true, pathIsClosed);
  4165. Clipper c;
  4166. c.AddPaths(solution, ptSubject, true);
  4167. c.Execute(ctUnion, solution, pftNonZero, pftNonZero);
  4168. }
  4169. //------------------------------------------------------------------------------
  4170. void TranslatePath(const Path& input, Path& output, const IntPoint delta)
  4171. {
  4172. //precondition: input != output
  4173. output.resize(input.size());
  4174. for (size_t i = 0; i < input.size(); ++i)
  4175. output[i] = IntPoint(input[i].X + delta.X, input[i].Y + delta.Y);
  4176. }
  4177. //------------------------------------------------------------------------------
  4178. void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed)
  4179. {
  4180. Clipper c;
  4181. for (size_t i = 0; i < paths.size(); ++i)
  4182. {
  4183. Paths tmp;
  4184. Minkowski(pattern, paths[i], tmp, true, pathIsClosed);
  4185. c.AddPaths(tmp, ptSubject, true);
  4186. if (pathIsClosed)
  4187. {
  4188. Path tmp2;
  4189. TranslatePath(paths[i], tmp2, pattern[0]);
  4190. c.AddPath(tmp2, ptClip, true);
  4191. }
  4192. }
  4193. c.Execute(ctUnion, solution, pftNonZero, pftNonZero);
  4194. }
  4195. //------------------------------------------------------------------------------
  4196. void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution)
  4197. {
  4198. Minkowski(poly1, poly2, solution, false, true);
  4199. Clipper c;
  4200. c.AddPaths(solution, ptSubject, true);
  4201. c.Execute(ctUnion, solution, pftNonZero, pftNonZero);
  4202. }
  4203. //------------------------------------------------------------------------------
  4204. enum NodeType {ntAny, ntOpen, ntClosed};
  4205. void AddPolyNodeToPaths(const PolyNode& polynode, NodeType nodetype, Paths& paths)
  4206. {
  4207. bool match = true;
  4208. if (nodetype == ntClosed) match = !polynode.IsOpen();
  4209. else if (nodetype == ntOpen) return;
  4210. if (!polynode.Contour.empty() && match)
  4211. paths.push_back(polynode.Contour);
  4212. for (int i = 0; i < polynode.ChildCount(); ++i)
  4213. AddPolyNodeToPaths(*polynode.Childs[i], nodetype, paths);
  4214. }
  4215. //------------------------------------------------------------------------------
  4216. void PolyTreeToPaths(const PolyTree& polytree, Paths& paths)
  4217. {
  4218. paths.resize(0);
  4219. paths.reserve(polytree.Total());
  4220. AddPolyNodeToPaths(polytree, ntAny, paths);
  4221. }
  4222. //------------------------------------------------------------------------------
  4223. void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths)
  4224. {
  4225. paths.resize(0);
  4226. paths.reserve(polytree.Total());
  4227. AddPolyNodeToPaths(polytree, ntClosed, paths);
  4228. }
  4229. //------------------------------------------------------------------------------
  4230. void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths)
  4231. {
  4232. paths.resize(0);
  4233. paths.reserve(polytree.Total());
  4234. //Open paths are top level only, so ...
  4235. for (int i = 0; i < polytree.ChildCount(); ++i)
  4236. if (polytree.Childs[i]->IsOpen())
  4237. paths.push_back(polytree.Childs[i]->Contour);
  4238. }
  4239. //------------------------------------------------------------------------------
  4240. std::ostream& operator <<(std::ostream &s, const IntPoint &p)
  4241. {
  4242. s << "(" << p.X << "," << p.Y << ")";
  4243. return s;
  4244. }
  4245. //------------------------------------------------------------------------------
  4246. std::ostream& operator <<(std::ostream &s, const Path &p)
  4247. {
  4248. if (p.empty()) return s;
  4249. Path::size_type last = p.size() -1;
  4250. for (Path::size_type i = 0; i < last; i++)
  4251. s << "(" << p[i].X << "," << p[i].Y << "), ";
  4252. s << "(" << p[last].X << "," << p[last].Y << ")\n";
  4253. return s;
  4254. }
  4255. //------------------------------------------------------------------------------
  4256. std::ostream& operator <<(std::ostream &s, const Paths &p)
  4257. {
  4258. for (Paths::size_type i = 0; i < p.size(); i++)
  4259. s << p[i];
  4260. s << "\n";
  4261. return s;
  4262. }
  4263. //------------------------------------------------------------------------------
  4264. } //ClipperLib namespace