clipper.js 199 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629
  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. * Author : Timo *
  36. * Version : 6.4.2.2 *
  37. * Date : 8 September 2017 *
  38. * *
  39. * This is a translation of the C# Clipper library to Javascript. *
  40. * Int128 struct of C# is implemented using JSBN of Tom Wu. *
  41. * Because Javascript lacks support for 64-bit integers, the space *
  42. * is a little more restricted than in C# version. *
  43. * *
  44. * C# version has support for coordinate space: *
  45. * +-4611686018427387903 ( sqrt(2^127 -1)/2 ) *
  46. * while Javascript version has support for space: *
  47. * +-4503599627370495 ( sqrt(2^106 -1)/2 ) *
  48. * *
  49. * Tom Wu's JSBN proved to be the fastest big integer library: *
  50. * http://jsperf.com/big-integer-library-test *
  51. * *
  52. * This class can be made simpler when (if ever) 64-bit integer support comes *
  53. * or floating point Clipper is released. *
  54. * *
  55. *******************************************************************************/
  56. /*******************************************************************************
  57. * *
  58. * Basic JavaScript BN library - subset useful for RSA encryption. *
  59. * http://www-cs-students.stanford.edu/~tjw/jsbn/ *
  60. * Copyright (c) 2005 Tom Wu *
  61. * All Rights Reserved. *
  62. * See "LICENSE" for details: *
  63. * http://www-cs-students.stanford.edu/~tjw/jsbn/LICENSE *
  64. * *
  65. *******************************************************************************/
  66. (function ()
  67. {
  68. "use strict";
  69. var ClipperLib = {};
  70. ClipperLib.version = '6.4.2.2';
  71. //UseLines: Enables open path clipping. Adds a very minor cost to performance.
  72. ClipperLib.use_lines = true;
  73. //ClipperLib.use_xyz: adds a Z member to IntPoint. Adds a minor cost to performance.
  74. ClipperLib.use_xyz = false;
  75. var isNode = false;
  76. if (typeof module !== 'undefined' && module.exports)
  77. {
  78. module.exports = ClipperLib;
  79. isNode = true;
  80. }
  81. else
  82. {
  83. if (typeof define === 'function' && define.amd) {
  84. define(ClipperLib);
  85. }
  86. if (typeof (document) !== "undefined") window.ClipperLib = ClipperLib;
  87. else self['ClipperLib'] = ClipperLib;
  88. }
  89. var navigator_appName;
  90. if (!isNode)
  91. {
  92. var nav = navigator.userAgent.toString().toLowerCase();
  93. navigator_appName = navigator.appName;
  94. }
  95. else
  96. {
  97. var nav = "chrome"; // Node.js uses Chrome's V8 engine
  98. navigator_appName = "Netscape"; // Firefox, Chrome and Safari returns "Netscape", so Node.js should also
  99. }
  100. // Browser test to speedup performance critical functions
  101. var browser = {};
  102. if (nav.indexOf("chrome") != -1 && nav.indexOf("chromium") == -1) browser.chrome = 1;
  103. else browser.chrome = 0;
  104. if (nav.indexOf("chromium") != -1) browser.chromium = 1;
  105. else browser.chromium = 0;
  106. if (nav.indexOf("safari") != -1 && nav.indexOf("chrome") == -1 && nav.indexOf("chromium") == -1) browser.safari = 1;
  107. else browser.safari = 0;
  108. if (nav.indexOf("firefox") != -1) browser.firefox = 1;
  109. else browser.firefox = 0;
  110. if (nav.indexOf("firefox/17") != -1) browser.firefox17 = 1;
  111. else browser.firefox17 = 0;
  112. if (nav.indexOf("firefox/15") != -1) browser.firefox15 = 1;
  113. else browser.firefox15 = 0;
  114. if (nav.indexOf("firefox/3") != -1) browser.firefox3 = 1;
  115. else browser.firefox3 = 0;
  116. if (nav.indexOf("opera") != -1) browser.opera = 1;
  117. else browser.opera = 0;
  118. if (nav.indexOf("msie 10") != -1) browser.msie10 = 1;
  119. else browser.msie10 = 0;
  120. if (nav.indexOf("msie 9") != -1) browser.msie9 = 1;
  121. else browser.msie9 = 0;
  122. if (nav.indexOf("msie 8") != -1) browser.msie8 = 1;
  123. else browser.msie8 = 0;
  124. if (nav.indexOf("msie 7") != -1) browser.msie7 = 1;
  125. else browser.msie7 = 0;
  126. if (nav.indexOf("msie ") != -1) browser.msie = 1;
  127. else browser.msie = 0;
  128. ClipperLib.biginteger_used = null;
  129. // Copyright (c) 2005 Tom Wu
  130. // All Rights Reserved.
  131. // See "LICENSE" for details.
  132. // Basic JavaScript BN library - subset useful for RSA encryption.
  133. // Bits per digit
  134. var dbits;
  135. // JavaScript engine analysis
  136. var canary = 0xdeadbeefcafe;
  137. var j_lm = ((canary & 0xffffff) == 0xefcafe);
  138. // (public) Constructor
  139. /**
  140. * @constructor
  141. */
  142. function BigInteger(a, b, c)
  143. {
  144. // This test variable can be removed,
  145. // but at least for performance tests it is useful piece of knowledge
  146. // This is the only ClipperLib related variable in BigInteger library
  147. ClipperLib.biginteger_used = 1;
  148. if (a != null)
  149. if ("number" == typeof a && "undefined" == typeof (b)) this.fromInt(a); // faster conversion
  150. else if ("number" == typeof a) this.fromNumber(a, b, c);
  151. else if (b == null && "string" != typeof a) this.fromString(a, 256);
  152. else this.fromString(a, b);
  153. }
  154. // return new, unset BigInteger
  155. function nbi()
  156. {
  157. return new BigInteger(null, undefined, undefined);
  158. }
  159. // am: Compute w_j += (x*this_i), propagate carries,
  160. // c is initial carry, returns final carry.
  161. // c < 3*dvalue, x < 2*dvalue, this_i < dvalue
  162. // We need to select the fastest one that works in this environment.
  163. // am1: use a single mult and divide to get the high bits,
  164. // max digit bits should be 26 because
  165. // max internal value = 2*dvalue^2-2*dvalue (< 2^53)
  166. function am1(i, x, w, j, c, n)
  167. {
  168. while (--n >= 0)
  169. {
  170. var v = x * this[i++] + w[j] + c;
  171. c = Math.floor(v / 0x4000000);
  172. w[j++] = v & 0x3ffffff;
  173. }
  174. return c;
  175. }
  176. // am2 avoids a big mult-and-extract completely.
  177. // Max digit bits should be <= 30 because we do bitwise ops
  178. // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
  179. function am2(i, x, w, j, c, n)
  180. {
  181. var xl = x & 0x7fff,
  182. xh = x >> 15;
  183. while (--n >= 0)
  184. {
  185. var l = this[i] & 0x7fff;
  186. var h = this[i++] >> 15;
  187. var m = xh * l + h * xl;
  188. l = xl * l + ((m & 0x7fff) << 15) + w[j] + (c & 0x3fffffff);
  189. c = (l >>> 30) + (m >>> 15) + xh * h + (c >>> 30);
  190. w[j++] = l & 0x3fffffff;
  191. }
  192. return c;
  193. }
  194. // Alternately, set max digit bits to 28 since some
  195. // browsers slow down when dealing with 32-bit numbers.
  196. function am3(i, x, w, j, c, n)
  197. {
  198. var xl = x & 0x3fff,
  199. xh = x >> 14;
  200. while (--n >= 0)
  201. {
  202. var l = this[i] & 0x3fff;
  203. var h = this[i++] >> 14;
  204. var m = xh * l + h * xl;
  205. l = xl * l + ((m & 0x3fff) << 14) + w[j] + c;
  206. c = (l >> 28) + (m >> 14) + xh * h;
  207. w[j++] = l & 0xfffffff;
  208. }
  209. return c;
  210. }
  211. if (j_lm && (navigator_appName == "Microsoft Internet Explorer"))
  212. {
  213. BigInteger.prototype.am = am2;
  214. dbits = 30;
  215. }
  216. else if (j_lm && (navigator_appName != "Netscape"))
  217. {
  218. BigInteger.prototype.am = am1;
  219. dbits = 26;
  220. }
  221. else
  222. { // Mozilla/Netscape seems to prefer am3
  223. BigInteger.prototype.am = am3;
  224. dbits = 28;
  225. }
  226. BigInteger.prototype.DB = dbits;
  227. BigInteger.prototype.DM = ((1 << dbits) - 1);
  228. BigInteger.prototype.DV = (1 << dbits);
  229. var BI_FP = 52;
  230. BigInteger.prototype.FV = Math.pow(2, BI_FP);
  231. BigInteger.prototype.F1 = BI_FP - dbits;
  232. BigInteger.prototype.F2 = 2 * dbits - BI_FP;
  233. // Digit conversions
  234. var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
  235. var BI_RC = new Array();
  236. var rr, vv;
  237. rr = "0".charCodeAt(0);
  238. for (vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
  239. rr = "a".charCodeAt(0);
  240. for (vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
  241. rr = "A".charCodeAt(0);
  242. for (vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
  243. function int2char(n)
  244. {
  245. return BI_RM.charAt(n);
  246. }
  247. function intAt(s, i)
  248. {
  249. var c = BI_RC[s.charCodeAt(i)];
  250. return (c == null) ? -1 : c;
  251. }
  252. // (protected) copy this to r
  253. function bnpCopyTo(r)
  254. {
  255. for (var i = this.t - 1; i >= 0; --i) r[i] = this[i];
  256. r.t = this.t;
  257. r.s = this.s;
  258. }
  259. // (protected) set from integer value x, -DV <= x < DV
  260. function bnpFromInt(x)
  261. {
  262. this.t = 1;
  263. this.s = (x < 0) ? -1 : 0;
  264. if (x > 0) this[0] = x;
  265. else if (x < -1) this[0] = x + this.DV;
  266. else this.t = 0;
  267. }
  268. // return bigint initialized to value
  269. function nbv(i)
  270. {
  271. var r = nbi();
  272. r.fromInt(i);
  273. return r;
  274. }
  275. // (protected) set from string and radix
  276. function bnpFromString(s, b)
  277. {
  278. var k;
  279. if (b == 16) k = 4;
  280. else if (b == 8) k = 3;
  281. else if (b == 256) k = 8; // byte array
  282. else if (b == 2) k = 1;
  283. else if (b == 32) k = 5;
  284. else if (b == 4) k = 2;
  285. else
  286. {
  287. this.fromRadix(s, b);
  288. return;
  289. }
  290. this.t = 0;
  291. this.s = 0;
  292. var i = s.length,
  293. mi = false,
  294. sh = 0;
  295. while (--i >= 0)
  296. {
  297. var x = (k == 8) ? s[i] & 0xff : intAt(s, i);
  298. if (x < 0)
  299. {
  300. if (s.charAt(i) == "-") mi = true;
  301. continue;
  302. }
  303. mi = false;
  304. if (sh == 0)
  305. this[this.t++] = x;
  306. else if (sh + k > this.DB)
  307. {
  308. this[this.t - 1] |= (x & ((1 << (this.DB - sh)) - 1)) << sh;
  309. this[this.t++] = (x >> (this.DB - sh));
  310. }
  311. else
  312. this[this.t - 1] |= x << sh;
  313. sh += k;
  314. if (sh >= this.DB) sh -= this.DB;
  315. }
  316. if (k == 8 && (s[0] & 0x80) != 0)
  317. {
  318. this.s = -1;
  319. if (sh > 0) this[this.t - 1] |= ((1 << (this.DB - sh)) - 1) << sh;
  320. }
  321. this.clamp();
  322. if (mi) BigInteger.ZERO.subTo(this, this);
  323. }
  324. // (protected) clamp off excess high words
  325. function bnpClamp()
  326. {
  327. var c = this.s & this.DM;
  328. while (this.t > 0 && this[this.t - 1] == c) --this.t;
  329. }
  330. // (public) return string representation in given radix
  331. function bnToString(b)
  332. {
  333. if (this.s < 0) return "-" + this.negate().toString(b);
  334. var k;
  335. if (b == 16) k = 4;
  336. else if (b == 8) k = 3;
  337. else if (b == 2) k = 1;
  338. else if (b == 32) k = 5;
  339. else if (b == 4) k = 2;
  340. else return this.toRadix(b);
  341. var km = (1 << k) - 1,
  342. d, m = false,
  343. r = "",
  344. i = this.t;
  345. var p = this.DB - (i * this.DB) % k;
  346. if (i-- > 0)
  347. {
  348. if (p < this.DB && (d = this[i] >> p) > 0)
  349. {
  350. m = true;
  351. r = int2char(d);
  352. }
  353. while (i >= 0)
  354. {
  355. if (p < k)
  356. {
  357. d = (this[i] & ((1 << p) - 1)) << (k - p);
  358. d |= this[--i] >> (p += this.DB - k);
  359. }
  360. else
  361. {
  362. d = (this[i] >> (p -= k)) & km;
  363. if (p <= 0)
  364. {
  365. p += this.DB;
  366. --i;
  367. }
  368. }
  369. if (d > 0) m = true;
  370. if (m) r += int2char(d);
  371. }
  372. }
  373. return m ? r : "0";
  374. }
  375. // (public) -this
  376. function bnNegate()
  377. {
  378. var r = nbi();
  379. BigInteger.ZERO.subTo(this, r);
  380. return r;
  381. }
  382. // (public) |this|
  383. function bnAbs()
  384. {
  385. return (this.s < 0) ? this.negate() : this;
  386. }
  387. // (public) return + if this > a, - if this < a, 0 if equal
  388. function bnCompareTo(a)
  389. {
  390. var r = this.s - a.s;
  391. if (r != 0) return r;
  392. var i = this.t;
  393. r = i - a.t;
  394. if (r != 0) return (this.s < 0) ? -r : r;
  395. while (--i >= 0)
  396. if ((r = this[i] - a[i]) != 0) return r;
  397. return 0;
  398. }
  399. // returns bit length of the integer x
  400. function nbits(x)
  401. {
  402. var r = 1,
  403. t;
  404. if ((t = x >>> 16) != 0)
  405. {
  406. x = t;
  407. r += 16;
  408. }
  409. if ((t = x >> 8) != 0)
  410. {
  411. x = t;
  412. r += 8;
  413. }
  414. if ((t = x >> 4) != 0)
  415. {
  416. x = t;
  417. r += 4;
  418. }
  419. if ((t = x >> 2) != 0)
  420. {
  421. x = t;
  422. r += 2;
  423. }
  424. if ((t = x >> 1) != 0)
  425. {
  426. x = t;
  427. r += 1;
  428. }
  429. return r;
  430. }
  431. // (public) return the number of bits in "this"
  432. function bnBitLength()
  433. {
  434. if (this.t <= 0) return 0;
  435. return this.DB * (this.t - 1) + nbits(this[this.t - 1] ^ (this.s & this.DM));
  436. }
  437. // (protected) r = this << n*DB
  438. function bnpDLShiftTo(n, r)
  439. {
  440. var i;
  441. for (i = this.t - 1; i >= 0; --i) r[i + n] = this[i];
  442. for (i = n - 1; i >= 0; --i) r[i] = 0;
  443. r.t = this.t + n;
  444. r.s = this.s;
  445. }
  446. // (protected) r = this >> n*DB
  447. function bnpDRShiftTo(n, r)
  448. {
  449. for (var i = n; i < this.t; ++i) r[i - n] = this[i];
  450. r.t = Math.max(this.t - n, 0);
  451. r.s = this.s;
  452. }
  453. // (protected) r = this << n
  454. function bnpLShiftTo(n, r)
  455. {
  456. var bs = n % this.DB;
  457. var cbs = this.DB - bs;
  458. var bm = (1 << cbs) - 1;
  459. var ds = Math.floor(n / this.DB),
  460. c = (this.s << bs) & this.DM,
  461. i;
  462. for (i = this.t - 1; i >= 0; --i)
  463. {
  464. r[i + ds + 1] = (this[i] >> cbs) | c;
  465. c = (this[i] & bm) << bs;
  466. }
  467. for (i = ds - 1; i >= 0; --i) r[i] = 0;
  468. r[ds] = c;
  469. r.t = this.t + ds + 1;
  470. r.s = this.s;
  471. r.clamp();
  472. }
  473. // (protected) r = this >> n
  474. function bnpRShiftTo(n, r)
  475. {
  476. r.s = this.s;
  477. var ds = Math.floor(n / this.DB);
  478. if (ds >= this.t)
  479. {
  480. r.t = 0;
  481. return;
  482. }
  483. var bs = n % this.DB;
  484. var cbs = this.DB - bs;
  485. var bm = (1 << bs) - 1;
  486. r[0] = this[ds] >> bs;
  487. for (var i = ds + 1; i < this.t; ++i)
  488. {
  489. r[i - ds - 1] |= (this[i] & bm) << cbs;
  490. r[i - ds] = this[i] >> bs;
  491. }
  492. if (bs > 0) r[this.t - ds - 1] |= (this.s & bm) << cbs;
  493. r.t = this.t - ds;
  494. r.clamp();
  495. }
  496. // (protected) r = this - a
  497. function bnpSubTo(a, r)
  498. {
  499. var i = 0,
  500. c = 0,
  501. m = Math.min(a.t, this.t);
  502. while (i < m)
  503. {
  504. c += this[i] - a[i];
  505. r[i++] = c & this.DM;
  506. c >>= this.DB;
  507. }
  508. if (a.t < this.t)
  509. {
  510. c -= a.s;
  511. while (i < this.t)
  512. {
  513. c += this[i];
  514. r[i++] = c & this.DM;
  515. c >>= this.DB;
  516. }
  517. c += this.s;
  518. }
  519. else
  520. {
  521. c += this.s;
  522. while (i < a.t)
  523. {
  524. c -= a[i];
  525. r[i++] = c & this.DM;
  526. c >>= this.DB;
  527. }
  528. c -= a.s;
  529. }
  530. r.s = (c < 0) ? -1 : 0;
  531. if (c < -1) r[i++] = this.DV + c;
  532. else if (c > 0) r[i++] = c;
  533. r.t = i;
  534. r.clamp();
  535. }
  536. // (protected) r = this * a, r != this,a (HAC 14.12)
  537. // "this" should be the larger one if appropriate.
  538. function bnpMultiplyTo(a, r)
  539. {
  540. var x = this.abs(),
  541. y = a.abs();
  542. var i = x.t;
  543. r.t = i + y.t;
  544. while (--i >= 0) r[i] = 0;
  545. for (i = 0; i < y.t; ++i) r[i + x.t] = x.am(0, y[i], r, i, 0, x.t);
  546. r.s = 0;
  547. r.clamp();
  548. if (this.s != a.s) BigInteger.ZERO.subTo(r, r);
  549. }
  550. // (protected) r = this^2, r != this (HAC 14.16)
  551. function bnpSquareTo(r)
  552. {
  553. var x = this.abs();
  554. var i = r.t = 2 * x.t;
  555. while (--i >= 0) r[i] = 0;
  556. for (i = 0; i < x.t - 1; ++i)
  557. {
  558. var c = x.am(i, x[i], r, 2 * i, 0, 1);
  559. if ((r[i + x.t] += x.am(i + 1, 2 * x[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV)
  560. {
  561. r[i + x.t] -= x.DV;
  562. r[i + x.t + 1] = 1;
  563. }
  564. }
  565. if (r.t > 0) r[r.t - 1] += x.am(i, x[i], r, 2 * i, 0, 1);
  566. r.s = 0;
  567. r.clamp();
  568. }
  569. // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
  570. // r != q, this != m. q or r may be null.
  571. function bnpDivRemTo(m, q, r)
  572. {
  573. var pm = m.abs();
  574. if (pm.t <= 0) return;
  575. var pt = this.abs();
  576. if (pt.t < pm.t)
  577. {
  578. if (q != null) q.fromInt(0);
  579. if (r != null) this.copyTo(r);
  580. return;
  581. }
  582. if (r == null) r = nbi();
  583. var y = nbi(),
  584. ts = this.s,
  585. ms = m.s;
  586. var nsh = this.DB - nbits(pm[pm.t - 1]); // normalize modulus
  587. if (nsh > 0)
  588. {
  589. pm.lShiftTo(nsh, y);
  590. pt.lShiftTo(nsh, r);
  591. }
  592. else
  593. {
  594. pm.copyTo(y);
  595. pt.copyTo(r);
  596. }
  597. var ys = y.t;
  598. var y0 = y[ys - 1];
  599. if (y0 == 0) return;
  600. var yt = y0 * (1 << this.F1) + ((ys > 1) ? y[ys - 2] >> this.F2 : 0);
  601. var d1 = this.FV / yt,
  602. d2 = (1 << this.F1) / yt,
  603. e = 1 << this.F2;
  604. var i = r.t,
  605. j = i - ys,
  606. t = (q == null) ? nbi() : q;
  607. y.dlShiftTo(j, t);
  608. if (r.compareTo(t) >= 0)
  609. {
  610. r[r.t++] = 1;
  611. r.subTo(t, r);
  612. }
  613. BigInteger.ONE.dlShiftTo(ys, t);
  614. t.subTo(y, y); // "negative" y so we can replace sub with am later
  615. while (y.t < ys) y[y.t++] = 0;
  616. while (--j >= 0)
  617. {
  618. // Estimate quotient digit
  619. var qd = (r[--i] == y0) ? this.DM : Math.floor(r[i] * d1 + (r[i - 1] + e) * d2);
  620. if ((r[i] += y.am(0, qd, r, j, 0, ys)) < qd)
  621. { // Try it out
  622. y.dlShiftTo(j, t);
  623. r.subTo(t, r);
  624. while (r[i] < --qd) r.subTo(t, r);
  625. }
  626. }
  627. if (q != null)
  628. {
  629. r.drShiftTo(ys, q);
  630. if (ts != ms) BigInteger.ZERO.subTo(q, q);
  631. }
  632. r.t = ys;
  633. r.clamp();
  634. if (nsh > 0) r.rShiftTo(nsh, r); // Denormalize remainder
  635. if (ts < 0) BigInteger.ZERO.subTo(r, r);
  636. }
  637. // (public) this mod a
  638. function bnMod(a)
  639. {
  640. var r = nbi();
  641. this.abs().divRemTo(a, null, r);
  642. if (this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r, r);
  643. return r;
  644. }
  645. // Modular reduction using "classic" algorithm
  646. /**
  647. * @constructor
  648. */
  649. function Classic(m)
  650. {
  651. this.m = m;
  652. }
  653. function cConvert(x)
  654. {
  655. if (x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
  656. else return x;
  657. }
  658. function cRevert(x)
  659. {
  660. return x;
  661. }
  662. function cReduce(x)
  663. {
  664. x.divRemTo(this.m, null, x);
  665. }
  666. function cMulTo(x, y, r)
  667. {
  668. x.multiplyTo(y, r);
  669. this.reduce(r);
  670. }
  671. function cSqrTo(x, r)
  672. {
  673. x.squareTo(r);
  674. this.reduce(r);
  675. }
  676. Classic.prototype.convert = cConvert;
  677. Classic.prototype.revert = cRevert;
  678. Classic.prototype.reduce = cReduce;
  679. Classic.prototype.mulTo = cMulTo;
  680. Classic.prototype.sqrTo = cSqrTo;
  681. // (protected) return "-1/this % 2^DB"; useful for Mont. reduction
  682. // justification:
  683. // xy == 1 (mod m)
  684. // xy = 1+km
  685. // xy(2-xy) = (1+km)(1-km)
  686. // x[y(2-xy)] = 1-k^2m^2
  687. // x[y(2-xy)] == 1 (mod m^2)
  688. // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
  689. // should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
  690. // JS multiply "overflows" differently from C/C++, so care is needed here.
  691. function bnpInvDigit()
  692. {
  693. if (this.t < 1) return 0;
  694. var x = this[0];
  695. if ((x & 1) == 0) return 0;
  696. var y = x & 3; // y == 1/x mod 2^2
  697. y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
  698. y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8
  699. y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
  700. // last step - calculate inverse mod DV directly;
  701. // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
  702. y = (y * (2 - x * y % this.DV)) % this.DV; // y == 1/x mod 2^dbits
  703. // we really want the negative inverse, and -DV < y < DV
  704. return (y > 0) ? this.DV - y : -y;
  705. }
  706. // Montgomery reduction
  707. /**
  708. * @constructor
  709. */
  710. function Montgomery(m)
  711. {
  712. this.m = m;
  713. this.mp = m.invDigit();
  714. this.mpl = this.mp & 0x7fff;
  715. this.mph = this.mp >> 15;
  716. this.um = (1 << (m.DB - 15)) - 1;
  717. this.mt2 = 2 * m.t;
  718. }
  719. // xR mod m
  720. function montConvert(x)
  721. {
  722. var r = nbi();
  723. x.abs().dlShiftTo(this.m.t, r);
  724. r.divRemTo(this.m, null, r);
  725. if (x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r, r);
  726. return r;
  727. }
  728. // x/R mod m
  729. function montRevert(x)
  730. {
  731. var r = nbi();
  732. x.copyTo(r);
  733. this.reduce(r);
  734. return r;
  735. }
  736. // x = x/R mod m (HAC 14.32)
  737. function montReduce(x)
  738. {
  739. while (x.t <= this.mt2) // pad x so am has enough room later
  740. x[x.t++] = 0;
  741. for (var i = 0; i < this.m.t; ++i)
  742. {
  743. // faster way of calculating u0 = x[i]*mp mod DV
  744. var j = x[i] & 0x7fff;
  745. var u0 = (j * this.mpl + (((j * this.mph + (x[i] >> 15) * this.mpl) & this.um) << 15)) & x.DM;
  746. // use am to combine the multiply-shift-add into one call
  747. j = i + this.m.t;
  748. x[j] += this.m.am(0, u0, x, i, 0, this.m.t);
  749. // propagate carry
  750. while (x[j] >= x.DV)
  751. {
  752. x[j] -= x.DV;
  753. x[++j]++;
  754. }
  755. }
  756. x.clamp();
  757. x.drShiftTo(this.m.t, x);
  758. if (x.compareTo(this.m) >= 0) x.subTo(this.m, x);
  759. }
  760. // r = "x^2/R mod m"; x != r
  761. function montSqrTo(x, r)
  762. {
  763. x.squareTo(r);
  764. this.reduce(r);
  765. }
  766. // r = "xy/R mod m"; x,y != r
  767. function montMulTo(x, y, r)
  768. {
  769. x.multiplyTo(y, r);
  770. this.reduce(r);
  771. }
  772. Montgomery.prototype.convert = montConvert;
  773. Montgomery.prototype.revert = montRevert;
  774. Montgomery.prototype.reduce = montReduce;
  775. Montgomery.prototype.mulTo = montMulTo;
  776. Montgomery.prototype.sqrTo = montSqrTo;
  777. // (protected) true iff this is even
  778. function bnpIsEven()
  779. {
  780. return ((this.t > 0) ? (this[0] & 1) : this.s) == 0;
  781. }
  782. // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
  783. function bnpExp(e, z)
  784. {
  785. if (e > 0xffffffff || e < 1) return BigInteger.ONE;
  786. var r = nbi(),
  787. r2 = nbi(),
  788. g = z.convert(this),
  789. i = nbits(e) - 1;
  790. g.copyTo(r);
  791. while (--i >= 0)
  792. {
  793. z.sqrTo(r, r2);
  794. if ((e & (1 << i)) > 0) z.mulTo(r2, g, r);
  795. else
  796. {
  797. var t = r;
  798. r = r2;
  799. r2 = t;
  800. }
  801. }
  802. return z.revert(r);
  803. }
  804. // (public) this^e % m, 0 <= e < 2^32
  805. function bnModPowInt(e, m)
  806. {
  807. var z;
  808. if (e < 256 || m.isEven()) z = new Classic(m);
  809. else z = new Montgomery(m);
  810. return this.exp(e, z);
  811. }
  812. // protected
  813. BigInteger.prototype.copyTo = bnpCopyTo;
  814. BigInteger.prototype.fromInt = bnpFromInt;
  815. BigInteger.prototype.fromString = bnpFromString;
  816. BigInteger.prototype.clamp = bnpClamp;
  817. BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
  818. BigInteger.prototype.drShiftTo = bnpDRShiftTo;
  819. BigInteger.prototype.lShiftTo = bnpLShiftTo;
  820. BigInteger.prototype.rShiftTo = bnpRShiftTo;
  821. BigInteger.prototype.subTo = bnpSubTo;
  822. BigInteger.prototype.multiplyTo = bnpMultiplyTo;
  823. BigInteger.prototype.squareTo = bnpSquareTo;
  824. BigInteger.prototype.divRemTo = bnpDivRemTo;
  825. BigInteger.prototype.invDigit = bnpInvDigit;
  826. BigInteger.prototype.isEven = bnpIsEven;
  827. BigInteger.prototype.exp = bnpExp;
  828. // public
  829. BigInteger.prototype.toString = bnToString;
  830. BigInteger.prototype.negate = bnNegate;
  831. BigInteger.prototype.abs = bnAbs;
  832. BigInteger.prototype.compareTo = bnCompareTo;
  833. BigInteger.prototype.bitLength = bnBitLength;
  834. BigInteger.prototype.mod = bnMod;
  835. BigInteger.prototype.modPowInt = bnModPowInt;
  836. // "constants"
  837. BigInteger.ZERO = nbv(0);
  838. BigInteger.ONE = nbv(1);
  839. // Copyright (c) 2005-2009 Tom Wu
  840. // All Rights Reserved.
  841. // See "LICENSE" for details.
  842. // Extended JavaScript BN functions, required for RSA private ops.
  843. // Version 1.1: new BigInteger("0", 10) returns "proper" zero
  844. // Version 1.2: square() API, isProbablePrime fix
  845. // (public)
  846. function bnClone()
  847. {
  848. var r = nbi();
  849. this.copyTo(r);
  850. return r;
  851. }
  852. // (public) return value as integer
  853. function bnIntValue()
  854. {
  855. if (this.s < 0)
  856. {
  857. if (this.t == 1) return this[0] - this.DV;
  858. else if (this.t == 0) return -1;
  859. }
  860. else if (this.t == 1) return this[0];
  861. else if (this.t == 0) return 0;
  862. // assumes 16 < DB < 32
  863. return ((this[1] & ((1 << (32 - this.DB)) - 1)) << this.DB) | this[0];
  864. }
  865. // (public) return value as byte
  866. function bnByteValue()
  867. {
  868. return (this.t == 0) ? this.s : (this[0] << 24) >> 24;
  869. }
  870. // (public) return value as short (assumes DB>=16)
  871. function bnShortValue()
  872. {
  873. return (this.t == 0) ? this.s : (this[0] << 16) >> 16;
  874. }
  875. // (protected) return x s.t. r^x < DV
  876. function bnpChunkSize(r)
  877. {
  878. return Math.floor(Math.LN2 * this.DB / Math.log(r));
  879. }
  880. // (public) 0 if this == 0, 1 if this > 0
  881. function bnSigNum()
  882. {
  883. if (this.s < 0) return -1;
  884. else if (this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
  885. else return 1;
  886. }
  887. // (protected) convert to radix string
  888. function bnpToRadix(b)
  889. {
  890. if (b == null) b = 10;
  891. if (this.signum() == 0 || b < 2 || b > 36) return "0";
  892. var cs = this.chunkSize(b);
  893. var a = Math.pow(b, cs);
  894. var d = nbv(a),
  895. y = nbi(),
  896. z = nbi(),
  897. r = "";
  898. this.divRemTo(d, y, z);
  899. while (y.signum() > 0)
  900. {
  901. r = (a + z.intValue()).toString(b).substr(1) + r;
  902. y.divRemTo(d, y, z);
  903. }
  904. return z.intValue().toString(b) + r;
  905. }
  906. // (protected) convert from radix string
  907. function bnpFromRadix(s, b)
  908. {
  909. this.fromInt(0);
  910. if (b == null) b = 10;
  911. var cs = this.chunkSize(b);
  912. var d = Math.pow(b, cs),
  913. mi = false,
  914. j = 0,
  915. w = 0;
  916. for (var i = 0; i < s.length; ++i)
  917. {
  918. var x = intAt(s, i);
  919. if (x < 0)
  920. {
  921. if (s.charAt(i) == "-" && this.signum() == 0) mi = true;
  922. continue;
  923. }
  924. w = b * w + x;
  925. if (++j >= cs)
  926. {
  927. this.dMultiply(d);
  928. this.dAddOffset(w, 0);
  929. j = 0;
  930. w = 0;
  931. }
  932. }
  933. if (j > 0)
  934. {
  935. this.dMultiply(Math.pow(b, j));
  936. this.dAddOffset(w, 0);
  937. }
  938. if (mi) BigInteger.ZERO.subTo(this, this);
  939. }
  940. // (protected) alternate constructor
  941. function bnpFromNumber(a, b, c)
  942. {
  943. if ("number" == typeof b)
  944. {
  945. // new BigInteger(int,int,RNG)
  946. if (a < 2) this.fromInt(1);
  947. else
  948. {
  949. this.fromNumber(a, c);
  950. if (!this.testBit(a - 1)) // force MSB set
  951. this.bitwiseTo(BigInteger.ONE.shiftLeft(a - 1), op_or, this);
  952. if (this.isEven()) this.dAddOffset(1, 0); // force odd
  953. while (!this.isProbablePrime(b))
  954. {
  955. this.dAddOffset(2, 0);
  956. if (this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a - 1), this);
  957. }
  958. }
  959. }
  960. else
  961. {
  962. // new BigInteger(int,RNG)
  963. var x = new Array(),
  964. t = a & 7;
  965. x.length = (a >> 3) + 1;
  966. b.nextBytes(x);
  967. if (t > 0) x[0] &= ((1 << t) - 1);
  968. else x[0] = 0;
  969. this.fromString(x, 256);
  970. }
  971. }
  972. // (public) convert to bigendian byte array
  973. function bnToByteArray()
  974. {
  975. var i = this.t,
  976. r = new Array();
  977. r[0] = this.s;
  978. var p = this.DB - (i * this.DB) % 8,
  979. d, k = 0;
  980. if (i-- > 0)
  981. {
  982. if (p < this.DB && (d = this[i] >> p) != (this.s & this.DM) >> p)
  983. r[k++] = d | (this.s << (this.DB - p));
  984. while (i >= 0)
  985. {
  986. if (p < 8)
  987. {
  988. d = (this[i] & ((1 << p) - 1)) << (8 - p);
  989. d |= this[--i] >> (p += this.DB - 8);
  990. }
  991. else
  992. {
  993. d = (this[i] >> (p -= 8)) & 0xff;
  994. if (p <= 0)
  995. {
  996. p += this.DB;
  997. --i;
  998. }
  999. }
  1000. if ((d & 0x80) != 0) d |= -256;
  1001. if (k == 0 && (this.s & 0x80) != (d & 0x80)) ++k;
  1002. if (k > 0 || d != this.s) r[k++] = d;
  1003. }
  1004. }
  1005. return r;
  1006. }
  1007. function bnEquals(a)
  1008. {
  1009. return (this.compareTo(a) == 0);
  1010. }
  1011. function bnMin(a)
  1012. {
  1013. return (this.compareTo(a) < 0) ? this : a;
  1014. }
  1015. function bnMax(a)
  1016. {
  1017. return (this.compareTo(a) > 0) ? this : a;
  1018. }
  1019. // (protected) r = this op a (bitwise)
  1020. function bnpBitwiseTo(a, op, r)
  1021. {
  1022. var i, f, m = Math.min(a.t, this.t);
  1023. for (i = 0; i < m; ++i) r[i] = op(this[i], a[i]);
  1024. if (a.t < this.t)
  1025. {
  1026. f = a.s & this.DM;
  1027. for (i = m; i < this.t; ++i) r[i] = op(this[i], f);
  1028. r.t = this.t;
  1029. }
  1030. else
  1031. {
  1032. f = this.s & this.DM;
  1033. for (i = m; i < a.t; ++i) r[i] = op(f, a[i]);
  1034. r.t = a.t;
  1035. }
  1036. r.s = op(this.s, a.s);
  1037. r.clamp();
  1038. }
  1039. // (public) this & a
  1040. function op_and(x, y)
  1041. {
  1042. return x & y;
  1043. }
  1044. function bnAnd(a)
  1045. {
  1046. var r = nbi();
  1047. this.bitwiseTo(a, op_and, r);
  1048. return r;
  1049. }
  1050. // (public) this | a
  1051. function op_or(x, y)
  1052. {
  1053. return x | y;
  1054. }
  1055. function bnOr(a)
  1056. {
  1057. var r = nbi();
  1058. this.bitwiseTo(a, op_or, r);
  1059. return r;
  1060. }
  1061. // (public) this ^ a
  1062. function op_xor(x, y)
  1063. {
  1064. return x ^ y;
  1065. }
  1066. function bnXor(a)
  1067. {
  1068. var r = nbi();
  1069. this.bitwiseTo(a, op_xor, r);
  1070. return r;
  1071. }
  1072. // (public) this & ~a
  1073. function op_andnot(x, y)
  1074. {
  1075. return x & ~y;
  1076. }
  1077. function bnAndNot(a)
  1078. {
  1079. var r = nbi();
  1080. this.bitwiseTo(a, op_andnot, r);
  1081. return r;
  1082. }
  1083. // (public) ~this
  1084. function bnNot()
  1085. {
  1086. var r = nbi();
  1087. for (var i = 0; i < this.t; ++i) r[i] = this.DM & ~this[i];
  1088. r.t = this.t;
  1089. r.s = ~this.s;
  1090. return r;
  1091. }
  1092. // (public) this << n
  1093. function bnShiftLeft(n)
  1094. {
  1095. var r = nbi();
  1096. if (n < 0) this.rShiftTo(-n, r);
  1097. else this.lShiftTo(n, r);
  1098. return r;
  1099. }
  1100. // (public) this >> n
  1101. function bnShiftRight(n)
  1102. {
  1103. var r = nbi();
  1104. if (n < 0) this.lShiftTo(-n, r);
  1105. else this.rShiftTo(n, r);
  1106. return r;
  1107. }
  1108. // return index of lowest 1-bit in x, x < 2^31
  1109. function lbit(x)
  1110. {
  1111. if (x == 0) return -1;
  1112. var r = 0;
  1113. if ((x & 0xffff) == 0)
  1114. {
  1115. x >>= 16;
  1116. r += 16;
  1117. }
  1118. if ((x & 0xff) == 0)
  1119. {
  1120. x >>= 8;
  1121. r += 8;
  1122. }
  1123. if ((x & 0xf) == 0)
  1124. {
  1125. x >>= 4;
  1126. r += 4;
  1127. }
  1128. if ((x & 3) == 0)
  1129. {
  1130. x >>= 2;
  1131. r += 2;
  1132. }
  1133. if ((x & 1) == 0) ++r;
  1134. return r;
  1135. }
  1136. // (public) returns index of lowest 1-bit (or -1 if none)
  1137. function bnGetLowestSetBit()
  1138. {
  1139. for (var i = 0; i < this.t; ++i)
  1140. if (this[i] != 0) return i * this.DB + lbit(this[i]);
  1141. if (this.s < 0) return this.t * this.DB;
  1142. return -1;
  1143. }
  1144. // return number of 1 bits in x
  1145. function cbit(x)
  1146. {
  1147. var r = 0;
  1148. while (x != 0)
  1149. {
  1150. x &= x - 1;
  1151. ++r;
  1152. }
  1153. return r;
  1154. }
  1155. // (public) return number of set bits
  1156. function bnBitCount()
  1157. {
  1158. var r = 0,
  1159. x = this.s & this.DM;
  1160. for (var i = 0; i < this.t; ++i) r += cbit(this[i] ^ x);
  1161. return r;
  1162. }
  1163. // (public) true iff nth bit is set
  1164. function bnTestBit(n)
  1165. {
  1166. var j = Math.floor(n / this.DB);
  1167. if (j >= this.t) return (this.s != 0);
  1168. return ((this[j] & (1 << (n % this.DB))) != 0);
  1169. }
  1170. // (protected) this op (1<<n)
  1171. function bnpChangeBit(n, op)
  1172. {
  1173. var r = BigInteger.ONE.shiftLeft(n);
  1174. this.bitwiseTo(r, op, r);
  1175. return r;
  1176. }
  1177. // (public) this | (1<<n)
  1178. function bnSetBit(n)
  1179. {
  1180. return this.changeBit(n, op_or);
  1181. }
  1182. // (public) this & ~(1<<n)
  1183. function bnClearBit(n)
  1184. {
  1185. return this.changeBit(n, op_andnot);
  1186. }
  1187. // (public) this ^ (1<<n)
  1188. function bnFlipBit(n)
  1189. {
  1190. return this.changeBit(n, op_xor);
  1191. }
  1192. // (protected) r = this + a
  1193. function bnpAddTo(a, r)
  1194. {
  1195. var i = 0,
  1196. c = 0,
  1197. m = Math.min(a.t, this.t);
  1198. while (i < m)
  1199. {
  1200. c += this[i] + a[i];
  1201. r[i++] = c & this.DM;
  1202. c >>= this.DB;
  1203. }
  1204. if (a.t < this.t)
  1205. {
  1206. c += a.s;
  1207. while (i < this.t)
  1208. {
  1209. c += this[i];
  1210. r[i++] = c & this.DM;
  1211. c >>= this.DB;
  1212. }
  1213. c += this.s;
  1214. }
  1215. else
  1216. {
  1217. c += this.s;
  1218. while (i < a.t)
  1219. {
  1220. c += a[i];
  1221. r[i++] = c & this.DM;
  1222. c >>= this.DB;
  1223. }
  1224. c += a.s;
  1225. }
  1226. r.s = (c < 0) ? -1 : 0;
  1227. if (c > 0) r[i++] = c;
  1228. else if (c < -1) r[i++] = this.DV + c;
  1229. r.t = i;
  1230. r.clamp();
  1231. }
  1232. // (public) this + a
  1233. function bnAdd(a)
  1234. {
  1235. var r = nbi();
  1236. this.addTo(a, r);
  1237. return r;
  1238. }
  1239. // (public) this - a
  1240. function bnSubtract(a)
  1241. {
  1242. var r = nbi();
  1243. this.subTo(a, r);
  1244. return r;
  1245. }
  1246. // (public) this * a
  1247. function bnMultiply(a)
  1248. {
  1249. var r = nbi();
  1250. this.multiplyTo(a, r);
  1251. return r;
  1252. }
  1253. // (public) this^2
  1254. function bnSquare()
  1255. {
  1256. var r = nbi();
  1257. this.squareTo(r);
  1258. return r;
  1259. }
  1260. // (public) this / a
  1261. function bnDivide(a)
  1262. {
  1263. var r = nbi();
  1264. this.divRemTo(a, r, null);
  1265. return r;
  1266. }
  1267. // (public) this % a
  1268. function bnRemainder(a)
  1269. {
  1270. var r = nbi();
  1271. this.divRemTo(a, null, r);
  1272. return r;
  1273. }
  1274. // (public) [this/a,this%a]
  1275. function bnDivideAndRemainder(a)
  1276. {
  1277. var q = nbi(),
  1278. r = nbi();
  1279. this.divRemTo(a, q, r);
  1280. return new Array(q, r);
  1281. }
  1282. // (protected) this *= n, this >= 0, 1 < n < DV
  1283. function bnpDMultiply(n)
  1284. {
  1285. this[this.t] = this.am(0, n - 1, this, 0, 0, this.t);
  1286. ++this.t;
  1287. this.clamp();
  1288. }
  1289. // (protected) this += n << w words, this >= 0
  1290. function bnpDAddOffset(n, w)
  1291. {
  1292. if (n == 0) return;
  1293. while (this.t <= w) this[this.t++] = 0;
  1294. this[w] += n;
  1295. while (this[w] >= this.DV)
  1296. {
  1297. this[w] -= this.DV;
  1298. if (++w >= this.t) this[this.t++] = 0;
  1299. ++this[w];
  1300. }
  1301. }
  1302. // A "null" reducer
  1303. /**
  1304. * @constructor
  1305. */
  1306. function NullExp()
  1307. {}
  1308. function nNop(x)
  1309. {
  1310. return x;
  1311. }
  1312. function nMulTo(x, y, r)
  1313. {
  1314. x.multiplyTo(y, r);
  1315. }
  1316. function nSqrTo(x, r)
  1317. {
  1318. x.squareTo(r);
  1319. }
  1320. NullExp.prototype.convert = nNop;
  1321. NullExp.prototype.revert = nNop;
  1322. NullExp.prototype.mulTo = nMulTo;
  1323. NullExp.prototype.sqrTo = nSqrTo;
  1324. // (public) this^e
  1325. function bnPow(e)
  1326. {
  1327. return this.exp(e, new NullExp());
  1328. }
  1329. // (protected) r = lower n words of "this * a", a.t <= n
  1330. // "this" should be the larger one if appropriate.
  1331. function bnpMultiplyLowerTo(a, n, r)
  1332. {
  1333. var i = Math.min(this.t + a.t, n);
  1334. r.s = 0; // assumes a,this >= 0
  1335. r.t = i;
  1336. while (i > 0) r[--i] = 0;
  1337. var j;
  1338. for (j = r.t - this.t; i < j; ++i) r[i + this.t] = this.am(0, a[i], r, i, 0, this.t);
  1339. for (j = Math.min(a.t, n); i < j; ++i) this.am(0, a[i], r, i, 0, n - i);
  1340. r.clamp();
  1341. }
  1342. // (protected) r = "this * a" without lower n words, n > 0
  1343. // "this" should be the larger one if appropriate.
  1344. function bnpMultiplyUpperTo(a, n, r)
  1345. {
  1346. --n;
  1347. var i = r.t = this.t + a.t - n;
  1348. r.s = 0; // assumes a,this >= 0
  1349. while (--i >= 0) r[i] = 0;
  1350. for (i = Math.max(n - this.t, 0); i < a.t; ++i)
  1351. r[this.t + i - n] = this.am(n - i, a[i], r, 0, 0, this.t + i - n);
  1352. r.clamp();
  1353. r.drShiftTo(1, r);
  1354. }
  1355. // Barrett modular reduction
  1356. /**
  1357. * @constructor
  1358. */
  1359. function Barrett(m)
  1360. {
  1361. // setup Barrett
  1362. this.r2 = nbi();
  1363. this.q3 = nbi();
  1364. BigInteger.ONE.dlShiftTo(2 * m.t, this.r2);
  1365. this.mu = this.r2.divide(m);
  1366. this.m = m;
  1367. }
  1368. function barrettConvert(x)
  1369. {
  1370. if (x.s < 0 || x.t > 2 * this.m.t) return x.mod(this.m);
  1371. else if (x.compareTo(this.m) < 0) return x;
  1372. else
  1373. {
  1374. var r = nbi();
  1375. x.copyTo(r);
  1376. this.reduce(r);
  1377. return r;
  1378. }
  1379. }
  1380. function barrettRevert(x)
  1381. {
  1382. return x;
  1383. }
  1384. // x = x mod m (HAC 14.42)
  1385. function barrettReduce(x)
  1386. {
  1387. x.drShiftTo(this.m.t - 1, this.r2);
  1388. if (x.t > this.m.t + 1)
  1389. {
  1390. x.t = this.m.t + 1;
  1391. x.clamp();
  1392. }
  1393. this.mu.multiplyUpperTo(this.r2, this.m.t + 1, this.q3);
  1394. this.m.multiplyLowerTo(this.q3, this.m.t + 1, this.r2);
  1395. while (x.compareTo(this.r2) < 0) x.dAddOffset(1, this.m.t + 1);
  1396. x.subTo(this.r2, x);
  1397. while (x.compareTo(this.m) >= 0) x.subTo(this.m, x);
  1398. }
  1399. // r = x^2 mod m; x != r
  1400. function barrettSqrTo(x, r)
  1401. {
  1402. x.squareTo(r);
  1403. this.reduce(r);
  1404. }
  1405. // r = x*y mod m; x,y != r
  1406. function barrettMulTo(x, y, r)
  1407. {
  1408. x.multiplyTo(y, r);
  1409. this.reduce(r);
  1410. }
  1411. Barrett.prototype.convert = barrettConvert;
  1412. Barrett.prototype.revert = barrettRevert;
  1413. Barrett.prototype.reduce = barrettReduce;
  1414. Barrett.prototype.mulTo = barrettMulTo;
  1415. Barrett.prototype.sqrTo = barrettSqrTo;
  1416. // (public) this^e % m (HAC 14.85)
  1417. function bnModPow(e, m)
  1418. {
  1419. var i = e.bitLength(),
  1420. k, r = nbv(1),
  1421. z;
  1422. if (i <= 0) return r;
  1423. else if (i < 18) k = 1;
  1424. else if (i < 48) k = 3;
  1425. else if (i < 144) k = 4;
  1426. else if (i < 768) k = 5;
  1427. else k = 6;
  1428. if (i < 8)
  1429. z = new Classic(m);
  1430. else if (m.isEven())
  1431. z = new Barrett(m);
  1432. else
  1433. z = new Montgomery(m);
  1434. // precomputation
  1435. var g = new Array(),
  1436. n = 3,
  1437. k1 = k - 1,
  1438. km = (1 << k) - 1;
  1439. g[1] = z.convert(this);
  1440. if (k > 1)
  1441. {
  1442. var g2 = nbi();
  1443. z.sqrTo(g[1], g2);
  1444. while (n <= km)
  1445. {
  1446. g[n] = nbi();
  1447. z.mulTo(g2, g[n - 2], g[n]);
  1448. n += 2;
  1449. }
  1450. }
  1451. var j = e.t - 1,
  1452. w, is1 = true,
  1453. r2 = nbi(),
  1454. t;
  1455. i = nbits(e[j]) - 1;
  1456. while (j >= 0)
  1457. {
  1458. if (i >= k1) w = (e[j] >> (i - k1)) & km;
  1459. else
  1460. {
  1461. w = (e[j] & ((1 << (i + 1)) - 1)) << (k1 - i);
  1462. if (j > 0) w |= e[j - 1] >> (this.DB + i - k1);
  1463. }
  1464. n = k;
  1465. while ((w & 1) == 0)
  1466. {
  1467. w >>= 1;
  1468. --n;
  1469. }
  1470. if ((i -= n) < 0)
  1471. {
  1472. i += this.DB;
  1473. --j;
  1474. }
  1475. if (is1)
  1476. { // ret == 1, don't bother squaring or multiplying it
  1477. g[w].copyTo(r);
  1478. is1 = false;
  1479. }
  1480. else
  1481. {
  1482. while (n > 1)
  1483. {
  1484. z.sqrTo(r, r2);
  1485. z.sqrTo(r2, r);
  1486. n -= 2;
  1487. }
  1488. if (n > 0) z.sqrTo(r, r2);
  1489. else
  1490. {
  1491. t = r;
  1492. r = r2;
  1493. r2 = t;
  1494. }
  1495. z.mulTo(r2, g[w], r);
  1496. }
  1497. while (j >= 0 && (e[j] & (1 << i)) == 0)
  1498. {
  1499. z.sqrTo(r, r2);
  1500. t = r;
  1501. r = r2;
  1502. r2 = t;
  1503. if (--i < 0)
  1504. {
  1505. i = this.DB - 1;
  1506. --j;
  1507. }
  1508. }
  1509. }
  1510. return z.revert(r);
  1511. }
  1512. // (public) gcd(this,a) (HAC 14.54)
  1513. function bnGCD(a)
  1514. {
  1515. var x = (this.s < 0) ? this.negate() : this.clone();
  1516. var y = (a.s < 0) ? a.negate() : a.clone();
  1517. if (x.compareTo(y) < 0)
  1518. {
  1519. var t = x;
  1520. x = y;
  1521. y = t;
  1522. }
  1523. var i = x.getLowestSetBit(),
  1524. g = y.getLowestSetBit();
  1525. if (g < 0) return x;
  1526. if (i < g) g = i;
  1527. if (g > 0)
  1528. {
  1529. x.rShiftTo(g, x);
  1530. y.rShiftTo(g, y);
  1531. }
  1532. while (x.signum() > 0)
  1533. {
  1534. if ((i = x.getLowestSetBit()) > 0) x.rShiftTo(i, x);
  1535. if ((i = y.getLowestSetBit()) > 0) y.rShiftTo(i, y);
  1536. if (x.compareTo(y) >= 0)
  1537. {
  1538. x.subTo(y, x);
  1539. x.rShiftTo(1, x);
  1540. }
  1541. else
  1542. {
  1543. y.subTo(x, y);
  1544. y.rShiftTo(1, y);
  1545. }
  1546. }
  1547. if (g > 0) y.lShiftTo(g, y);
  1548. return y;
  1549. }
  1550. // (protected) this % n, n < 2^26
  1551. function bnpModInt(n)
  1552. {
  1553. if (n <= 0) return 0;
  1554. var d = this.DV % n,
  1555. r = (this.s < 0) ? n - 1 : 0;
  1556. if (this.t > 0)
  1557. if (d == 0) r = this[0] % n;
  1558. else
  1559. for (var i = this.t - 1; i >= 0; --i) r = (d * r + this[i]) % n;
  1560. return r;
  1561. }
  1562. // (public) 1/this % m (HAC 14.61)
  1563. function bnModInverse(m)
  1564. {
  1565. var ac = m.isEven();
  1566. if ((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
  1567. var u = m.clone(),
  1568. v = this.clone();
  1569. var a = nbv(1),
  1570. b = nbv(0),
  1571. c = nbv(0),
  1572. d = nbv(1);
  1573. while (u.signum() != 0)
  1574. {
  1575. while (u.isEven())
  1576. {
  1577. u.rShiftTo(1, u);
  1578. if (ac)
  1579. {
  1580. if (!a.isEven() || !b.isEven())
  1581. {
  1582. a.addTo(this, a);
  1583. b.subTo(m, b);
  1584. }
  1585. a.rShiftTo(1, a);
  1586. }
  1587. else if (!b.isEven()) b.subTo(m, b);
  1588. b.rShiftTo(1, b);
  1589. }
  1590. while (v.isEven())
  1591. {
  1592. v.rShiftTo(1, v);
  1593. if (ac)
  1594. {
  1595. if (!c.isEven() || !d.isEven())
  1596. {
  1597. c.addTo(this, c);
  1598. d.subTo(m, d);
  1599. }
  1600. c.rShiftTo(1, c);
  1601. }
  1602. else if (!d.isEven()) d.subTo(m, d);
  1603. d.rShiftTo(1, d);
  1604. }
  1605. if (u.compareTo(v) >= 0)
  1606. {
  1607. u.subTo(v, u);
  1608. if (ac) a.subTo(c, a);
  1609. b.subTo(d, b);
  1610. }
  1611. else
  1612. {
  1613. v.subTo(u, v);
  1614. if (ac) c.subTo(a, c);
  1615. d.subTo(b, d);
  1616. }
  1617. }
  1618. if (v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
  1619. if (d.compareTo(m) >= 0) return d.subtract(m);
  1620. if (d.signum() < 0) d.addTo(m, d);
  1621. else return d;
  1622. if (d.signum() < 0) return d.add(m);
  1623. else return d;
  1624. }
  1625. var lowprimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997];
  1626. var lplim = (1 << 26) / lowprimes[lowprimes.length - 1];
  1627. // (public) test primality with certainty >= 1-.5^t
  1628. function bnIsProbablePrime(t)
  1629. {
  1630. var i, x = this.abs();
  1631. if (x.t == 1 && x[0] <= lowprimes[lowprimes.length - 1])
  1632. {
  1633. for (i = 0; i < lowprimes.length; ++i)
  1634. if (x[0] == lowprimes[i]) return true;
  1635. return false;
  1636. }
  1637. if (x.isEven()) return false;
  1638. i = 1;
  1639. while (i < lowprimes.length)
  1640. {
  1641. var m = lowprimes[i],
  1642. j = i + 1;
  1643. while (j < lowprimes.length && m < lplim) m *= lowprimes[j++];
  1644. m = x.modInt(m);
  1645. while (i < j)
  1646. if (m % lowprimes[i++] == 0) return false;
  1647. }
  1648. return x.millerRabin(t);
  1649. }
  1650. // (protected) true if probably prime (HAC 4.24, Miller-Rabin)
  1651. function bnpMillerRabin(t)
  1652. {
  1653. var n1 = this.subtract(BigInteger.ONE);
  1654. var k = n1.getLowestSetBit();
  1655. if (k <= 0) return false;
  1656. var r = n1.shiftRight(k);
  1657. t = (t + 1) >> 1;
  1658. if (t > lowprimes.length) t = lowprimes.length;
  1659. var a = nbi();
  1660. for (var i = 0; i < t; ++i)
  1661. {
  1662. //Pick bases at random, instead of starting at 2
  1663. a.fromInt(lowprimes[Math.floor(Math.random() * lowprimes.length)]);
  1664. var y = a.modPow(r, this);
  1665. if (y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0)
  1666. {
  1667. var j = 1;
  1668. while (j++ < k && y.compareTo(n1) != 0)
  1669. {
  1670. y = y.modPowInt(2, this);
  1671. if (y.compareTo(BigInteger.ONE) == 0) return false;
  1672. }
  1673. if (y.compareTo(n1) != 0) return false;
  1674. }
  1675. }
  1676. return true;
  1677. }
  1678. // protected
  1679. BigInteger.prototype.chunkSize = bnpChunkSize;
  1680. BigInteger.prototype.toRadix = bnpToRadix;
  1681. BigInteger.prototype.fromRadix = bnpFromRadix;
  1682. BigInteger.prototype.fromNumber = bnpFromNumber;
  1683. BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
  1684. BigInteger.prototype.changeBit = bnpChangeBit;
  1685. BigInteger.prototype.addTo = bnpAddTo;
  1686. BigInteger.prototype.dMultiply = bnpDMultiply;
  1687. BigInteger.prototype.dAddOffset = bnpDAddOffset;
  1688. BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
  1689. BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
  1690. BigInteger.prototype.modInt = bnpModInt;
  1691. BigInteger.prototype.millerRabin = bnpMillerRabin;
  1692. // public
  1693. BigInteger.prototype.clone = bnClone;
  1694. BigInteger.prototype.intValue = bnIntValue;
  1695. BigInteger.prototype.byteValue = bnByteValue;
  1696. BigInteger.prototype.shortValue = bnShortValue;
  1697. BigInteger.prototype.signum = bnSigNum;
  1698. BigInteger.prototype.toByteArray = bnToByteArray;
  1699. BigInteger.prototype.equals = bnEquals;
  1700. BigInteger.prototype.min = bnMin;
  1701. BigInteger.prototype.max = bnMax;
  1702. BigInteger.prototype.and = bnAnd;
  1703. BigInteger.prototype.or = bnOr;
  1704. BigInteger.prototype.xor = bnXor;
  1705. BigInteger.prototype.andNot = bnAndNot;
  1706. BigInteger.prototype.not = bnNot;
  1707. BigInteger.prototype.shiftLeft = bnShiftLeft;
  1708. BigInteger.prototype.shiftRight = bnShiftRight;
  1709. BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
  1710. BigInteger.prototype.bitCount = bnBitCount;
  1711. BigInteger.prototype.testBit = bnTestBit;
  1712. BigInteger.prototype.setBit = bnSetBit;
  1713. BigInteger.prototype.clearBit = bnClearBit;
  1714. BigInteger.prototype.flipBit = bnFlipBit;
  1715. BigInteger.prototype.add = bnAdd;
  1716. BigInteger.prototype.subtract = bnSubtract;
  1717. BigInteger.prototype.multiply = bnMultiply;
  1718. BigInteger.prototype.divide = bnDivide;
  1719. BigInteger.prototype.remainder = bnRemainder;
  1720. BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
  1721. BigInteger.prototype.modPow = bnModPow;
  1722. BigInteger.prototype.modInverse = bnModInverse;
  1723. BigInteger.prototype.pow = bnPow;
  1724. BigInteger.prototype.gcd = bnGCD;
  1725. BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
  1726. // JSBN-specific extension
  1727. BigInteger.prototype.square = bnSquare;
  1728. var Int128 = BigInteger;
  1729. // BigInteger interfaces not implemented in jsbn:
  1730. // BigInteger(int signum, byte[] magnitude)
  1731. // double doubleValue()
  1732. // float floatValue()
  1733. // int hashCode()
  1734. // long longValue()
  1735. // static BigInteger valueOf(long val)
  1736. // Helper functions to make BigInteger functions callable with two parameters
  1737. // as in original C# Clipper
  1738. Int128.prototype.IsNegative = function ()
  1739. {
  1740. if (this.compareTo(Int128.ZERO) == -1) return true;
  1741. else return false;
  1742. };
  1743. Int128.op_Equality = function (val1, val2)
  1744. {
  1745. if (val1.compareTo(val2) == 0) return true;
  1746. else return false;
  1747. };
  1748. Int128.op_Inequality = function (val1, val2)
  1749. {
  1750. if (val1.compareTo(val2) != 0) return true;
  1751. else return false;
  1752. };
  1753. Int128.op_GreaterThan = function (val1, val2)
  1754. {
  1755. if (val1.compareTo(val2) > 0) return true;
  1756. else return false;
  1757. };
  1758. Int128.op_LessThan = function (val1, val2)
  1759. {
  1760. if (val1.compareTo(val2) < 0) return true;
  1761. else return false;
  1762. };
  1763. Int128.op_Addition = function (lhs, rhs)
  1764. {
  1765. return new Int128(lhs, undefined, undefined).add(new Int128(rhs, undefined, undefined));
  1766. };
  1767. Int128.op_Subtraction = function (lhs, rhs)
  1768. {
  1769. return new Int128(lhs, undefined, undefined).subtract(new Int128(rhs, undefined, undefined));
  1770. };
  1771. Int128.Int128Mul = function (lhs, rhs)
  1772. {
  1773. return new Int128(lhs, undefined, undefined).multiply(new Int128(rhs, undefined, undefined));
  1774. };
  1775. Int128.op_Division = function (lhs, rhs)
  1776. {
  1777. return lhs.divide(rhs);
  1778. };
  1779. Int128.prototype.ToDouble = function ()
  1780. {
  1781. return parseFloat(this.toString()); // This could be something faster
  1782. };
  1783. // end of Int128 section
  1784. /*
  1785. // Uncomment the following two lines if you want to use Int128 outside ClipperLib
  1786. if (typeof(document) !== "undefined") window.Int128 = Int128;
  1787. else self.Int128 = Int128;
  1788. */
  1789. // ---------------------------------------------
  1790. // Here starts the actual Clipper library:
  1791. // Helper function to support Inheritance in Javascript
  1792. var Inherit = function (ce, ce2)
  1793. {
  1794. var p;
  1795. if (typeof (Object.getOwnPropertyNames) === 'undefined')
  1796. {
  1797. for (p in ce2.prototype)
  1798. if (typeof (ce.prototype[p]) === 'undefined' || ce.prototype[p] === Object.prototype[p]) ce.prototype[p] = ce2.prototype[p];
  1799. for (p in ce2)
  1800. if (typeof (ce[p]) === 'undefined') ce[p] = ce2[p];
  1801. ce.$baseCtor = ce2;
  1802. }
  1803. else
  1804. {
  1805. var props = Object.getOwnPropertyNames(ce2.prototype);
  1806. for (var i = 0; i < props.length; i++)
  1807. if (typeof (Object.getOwnPropertyDescriptor(ce.prototype, props[i])) === 'undefined') Object.defineProperty(ce.prototype, props[i], Object.getOwnPropertyDescriptor(ce2.prototype, props[i]));
  1808. for (p in ce2)
  1809. if (typeof (ce[p]) === 'undefined') ce[p] = ce2[p];
  1810. ce.$baseCtor = ce2;
  1811. }
  1812. };
  1813. /**
  1814. * @constructor
  1815. */
  1816. ClipperLib.Path = function ()
  1817. {
  1818. return [];
  1819. };
  1820. ClipperLib.Path.prototype.push = Array.prototype.push;
  1821. /**
  1822. * @constructor
  1823. */
  1824. ClipperLib.Paths = function ()
  1825. {
  1826. return []; // Was previously [[]], but caused problems when pushed
  1827. };
  1828. ClipperLib.Paths.prototype.push = Array.prototype.push;
  1829. // Preserves the calling way of original C# Clipper
  1830. // Is essential due to compatibility, because DoublePoint is public class in original C# version
  1831. /**
  1832. * @constructor
  1833. */
  1834. ClipperLib.DoublePoint = function ()
  1835. {
  1836. var a = arguments;
  1837. this.X = 0;
  1838. this.Y = 0;
  1839. // public DoublePoint(DoublePoint dp)
  1840. // public DoublePoint(IntPoint ip)
  1841. if (a.length === 1)
  1842. {
  1843. this.X = a[0].X;
  1844. this.Y = a[0].Y;
  1845. }
  1846. else if (a.length === 2)
  1847. {
  1848. this.X = a[0];
  1849. this.Y = a[1];
  1850. }
  1851. }; // This is internal faster function when called without arguments
  1852. /**
  1853. * @constructor
  1854. */
  1855. ClipperLib.DoublePoint0 = function ()
  1856. {
  1857. this.X = 0;
  1858. this.Y = 0;
  1859. };
  1860. ClipperLib.DoublePoint0.prototype = ClipperLib.DoublePoint.prototype;
  1861. // This is internal faster function when called with 1 argument (dp or ip)
  1862. /**
  1863. * @constructor
  1864. */
  1865. ClipperLib.DoublePoint1 = function (dp)
  1866. {
  1867. this.X = dp.X;
  1868. this.Y = dp.Y;
  1869. };
  1870. ClipperLib.DoublePoint1.prototype = ClipperLib.DoublePoint.prototype;
  1871. // This is internal faster function when called with 2 arguments (x and y)
  1872. /**
  1873. * @constructor
  1874. */
  1875. ClipperLib.DoublePoint2 = function (x, y)
  1876. {
  1877. this.X = x;
  1878. this.Y = y;
  1879. };
  1880. ClipperLib.DoublePoint2.prototype = ClipperLib.DoublePoint.prototype;
  1881. // PolyTree & PolyNode start
  1882. /**
  1883. * @suppress {missingProperties}
  1884. */
  1885. ClipperLib.PolyNode = function ()
  1886. {
  1887. this.m_Parent = null;
  1888. this.m_polygon = new ClipperLib.Path();
  1889. this.m_Index = 0;
  1890. this.m_jointype = 0;
  1891. this.m_endtype = 0;
  1892. this.m_Childs = [];
  1893. this.IsOpen = false;
  1894. };
  1895. ClipperLib.PolyNode.prototype.IsHoleNode = function ()
  1896. {
  1897. var result = true;
  1898. var node = this.m_Parent;
  1899. while (node !== null)
  1900. {
  1901. result = !result;
  1902. node = node.m_Parent;
  1903. }
  1904. return result;
  1905. };
  1906. ClipperLib.PolyNode.prototype.ChildCount = function ()
  1907. {
  1908. return this.m_Childs.length;
  1909. };
  1910. ClipperLib.PolyNode.prototype.Contour = function ()
  1911. {
  1912. return this.m_polygon;
  1913. };
  1914. ClipperLib.PolyNode.prototype.AddChild = function (Child)
  1915. {
  1916. var cnt = this.m_Childs.length;
  1917. this.m_Childs.push(Child);
  1918. Child.m_Parent = this;
  1919. Child.m_Index = cnt;
  1920. };
  1921. ClipperLib.PolyNode.prototype.GetNext = function ()
  1922. {
  1923. if (this.m_Childs.length > 0)
  1924. return this.m_Childs[0];
  1925. else
  1926. return this.GetNextSiblingUp();
  1927. };
  1928. ClipperLib.PolyNode.prototype.GetNextSiblingUp = function ()
  1929. {
  1930. if (this.m_Parent === null)
  1931. return null;
  1932. else if (this.m_Index === this.m_Parent.m_Childs.length - 1)
  1933. return this.m_Parent.GetNextSiblingUp();
  1934. else
  1935. return this.m_Parent.m_Childs[this.m_Index + 1];
  1936. };
  1937. ClipperLib.PolyNode.prototype.Childs = function ()
  1938. {
  1939. return this.m_Childs;
  1940. };
  1941. ClipperLib.PolyNode.prototype.Parent = function ()
  1942. {
  1943. return this.m_Parent;
  1944. };
  1945. ClipperLib.PolyNode.prototype.IsHole = function ()
  1946. {
  1947. return this.IsHoleNode();
  1948. };
  1949. // PolyTree : PolyNode
  1950. /**
  1951. * @suppress {missingProperties}
  1952. * @constructor
  1953. */
  1954. ClipperLib.PolyTree = function ()
  1955. {
  1956. this.m_AllPolys = [];
  1957. ClipperLib.PolyNode.call(this);
  1958. };
  1959. ClipperLib.PolyTree.prototype.Clear = function ()
  1960. {
  1961. for (var i = 0, ilen = this.m_AllPolys.length; i < ilen; i++)
  1962. this.m_AllPolys[i] = null;
  1963. this.m_AllPolys.length = 0;
  1964. this.m_Childs.length = 0;
  1965. };
  1966. ClipperLib.PolyTree.prototype.GetFirst = function ()
  1967. {
  1968. if (this.m_Childs.length > 0)
  1969. return this.m_Childs[0];
  1970. else
  1971. return null;
  1972. };
  1973. ClipperLib.PolyTree.prototype.Total = function ()
  1974. {
  1975. var result = this.m_AllPolys.length;
  1976. //with negative offsets, ignore the hidden outer polygon ...
  1977. if (result > 0 && this.m_Childs[0] !== this.m_AllPolys[0]) result--;
  1978. return result;
  1979. };
  1980. Inherit(ClipperLib.PolyTree, ClipperLib.PolyNode);
  1981. // PolyTree & PolyNode end
  1982. ClipperLib.Math_Abs_Int64 = ClipperLib.Math_Abs_Int32 = ClipperLib.Math_Abs_Double = function (a)
  1983. {
  1984. return Math.abs(a);
  1985. };
  1986. ClipperLib.Math_Max_Int32_Int32 = function (a, b)
  1987. {
  1988. return Math.max(a, b);
  1989. };
  1990. /*
  1991. -----------------------------------
  1992. cast_32 speedtest: http://jsperf.com/truncate-float-to-integer/2
  1993. -----------------------------------
  1994. */
  1995. if (browser.msie || browser.opera || browser.safari) ClipperLib.Cast_Int32 = function (a)
  1996. {
  1997. return a | 0;
  1998. };
  1999. else ClipperLib.Cast_Int32 = function (a)
  2000. { // eg. browser.chrome || browser.chromium || browser.firefox
  2001. return ~~a;
  2002. };
  2003. /*
  2004. --------------------------
  2005. cast_64 speedtests: http://jsperf.com/truncate-float-to-integer
  2006. Chrome: bitwise_not_floor
  2007. Firefox17: toInteger (typeof test)
  2008. IE9: bitwise_or_floor
  2009. IE7 and IE8: to_parseint
  2010. Chromium: to_floor_or_ceil
  2011. Firefox3: to_floor_or_ceil
  2012. Firefox15: to_floor_or_ceil
  2013. Opera: to_floor_or_ceil
  2014. Safari: to_floor_or_ceil
  2015. --------------------------
  2016. */
  2017. if (typeof Number.toInteger === "undefined")
  2018. Number.toInteger = null;
  2019. if (browser.chrome) ClipperLib.Cast_Int64 = function (a)
  2020. {
  2021. if (a < -2147483648 || a > 2147483647)
  2022. return a < 0 ? Math.ceil(a) : Math.floor(a);
  2023. else return ~~a;
  2024. };
  2025. else if (browser.firefox && typeof (Number.toInteger) === "function") ClipperLib.Cast_Int64 = function (a)
  2026. {
  2027. return Number.toInteger(a);
  2028. };
  2029. else if (browser.msie7 || browser.msie8) ClipperLib.Cast_Int64 = function (a)
  2030. {
  2031. return parseInt(a, 10);
  2032. };
  2033. else if (browser.msie) ClipperLib.Cast_Int64 = function (a)
  2034. {
  2035. if (a < -2147483648 || a > 2147483647)
  2036. return a < 0 ? Math.ceil(a) : Math.floor(a);
  2037. return a | 0;
  2038. };
  2039. // eg. browser.chromium || browser.firefox || browser.opera || browser.safari
  2040. else ClipperLib.Cast_Int64 = function (a)
  2041. {
  2042. return a < 0 ? Math.ceil(a) : Math.floor(a);
  2043. };
  2044. ClipperLib.Clear = function (a)
  2045. {
  2046. a.length = 0;
  2047. };
  2048. //ClipperLib.MaxSteps = 64; // How many steps at maximum in arc in BuildArc() function
  2049. ClipperLib.PI = 3.141592653589793;
  2050. ClipperLib.PI2 = 2 * 3.141592653589793;
  2051. /**
  2052. * @constructor
  2053. */
  2054. ClipperLib.IntPoint = function ()
  2055. {
  2056. var a = arguments,
  2057. alen = a.length;
  2058. this.X = 0;
  2059. this.Y = 0;
  2060. if (ClipperLib.use_xyz)
  2061. {
  2062. this.Z = 0;
  2063. if (alen === 3) // public IntPoint(cInt x, cInt y, cInt z = 0)
  2064. {
  2065. this.X = a[0];
  2066. this.Y = a[1];
  2067. this.Z = a[2];
  2068. }
  2069. else if (alen === 2) // public IntPoint(cInt x, cInt y)
  2070. {
  2071. this.X = a[0];
  2072. this.Y = a[1];
  2073. this.Z = 0;
  2074. }
  2075. else if (alen === 1)
  2076. {
  2077. if (a[0] instanceof ClipperLib.DoublePoint) // public IntPoint(DoublePoint dp)
  2078. {
  2079. var dp = a[0];
  2080. this.X = ClipperLib.Clipper.Round(dp.X);
  2081. this.Y = ClipperLib.Clipper.Round(dp.Y);
  2082. this.Z = 0;
  2083. }
  2084. else // public IntPoint(IntPoint pt)
  2085. {
  2086. var pt = a[0];
  2087. if (typeof (pt.Z) === "undefined") pt.Z = 0;
  2088. this.X = pt.X;
  2089. this.Y = pt.Y;
  2090. this.Z = pt.Z;
  2091. }
  2092. }
  2093. else // public IntPoint()
  2094. {
  2095. this.X = 0;
  2096. this.Y = 0;
  2097. this.Z = 0;
  2098. }
  2099. }
  2100. else // if (!ClipperLib.use_xyz)
  2101. {
  2102. if (alen === 2) // public IntPoint(cInt X, cInt Y)
  2103. {
  2104. this.X = a[0];
  2105. this.Y = a[1];
  2106. }
  2107. else if (alen === 1)
  2108. {
  2109. if (a[0] instanceof ClipperLib.DoublePoint) // public IntPoint(DoublePoint dp)
  2110. {
  2111. var dp = a[0];
  2112. this.X = ClipperLib.Clipper.Round(dp.X);
  2113. this.Y = ClipperLib.Clipper.Round(dp.Y);
  2114. }
  2115. else // public IntPoint(IntPoint pt)
  2116. {
  2117. var pt = a[0];
  2118. this.X = pt.X;
  2119. this.Y = pt.Y;
  2120. }
  2121. }
  2122. else // public IntPoint(IntPoint pt)
  2123. {
  2124. this.X = 0;
  2125. this.Y = 0;
  2126. }
  2127. }
  2128. };
  2129. ClipperLib.IntPoint.op_Equality = function (a, b)
  2130. {
  2131. //return a == b;
  2132. return a.X === b.X && a.Y === b.Y;
  2133. };
  2134. ClipperLib.IntPoint.op_Inequality = function (a, b)
  2135. {
  2136. //return a !== b;
  2137. return a.X !== b.X || a.Y !== b.Y;
  2138. };
  2139. /*
  2140. ClipperLib.IntPoint.prototype.Equals = function (obj)
  2141. {
  2142. if (obj === null)
  2143. return false;
  2144. if (obj instanceof ClipperLib.IntPoint)
  2145. {
  2146. var a = Cast(obj, ClipperLib.IntPoint);
  2147. return (this.X == a.X) && (this.Y == a.Y);
  2148. }
  2149. else
  2150. return false;
  2151. };
  2152. */
  2153. /**
  2154. * @constructor
  2155. */
  2156. ClipperLib.IntPoint0 = function ()
  2157. {
  2158. this.X = 0;
  2159. this.Y = 0;
  2160. if (ClipperLib.use_xyz)
  2161. this.Z = 0;
  2162. };
  2163. ClipperLib.IntPoint0.prototype = ClipperLib.IntPoint.prototype;
  2164. /**
  2165. * @constructor
  2166. */
  2167. ClipperLib.IntPoint1 = function (pt)
  2168. {
  2169. this.X = pt.X;
  2170. this.Y = pt.Y;
  2171. if (ClipperLib.use_xyz)
  2172. {
  2173. if (typeof pt.Z === "undefined") this.Z = 0;
  2174. else this.Z = pt.Z;
  2175. }
  2176. };
  2177. ClipperLib.IntPoint1.prototype = ClipperLib.IntPoint.prototype;
  2178. /**
  2179. * @constructor
  2180. */
  2181. ClipperLib.IntPoint1dp = function (dp)
  2182. {
  2183. this.X = ClipperLib.Clipper.Round(dp.X);
  2184. this.Y = ClipperLib.Clipper.Round(dp.Y);
  2185. if (ClipperLib.use_xyz)
  2186. this.Z = 0;
  2187. };
  2188. ClipperLib.IntPoint1dp.prototype = ClipperLib.IntPoint.prototype;
  2189. /**
  2190. * @constructor
  2191. */
  2192. ClipperLib.IntPoint2 = function (x, y, z)
  2193. {
  2194. this.X = x;
  2195. this.Y = y;
  2196. if (ClipperLib.use_xyz)
  2197. {
  2198. if (typeof z === "undefined") this.Z = 0;
  2199. else this.Z = z;
  2200. }
  2201. };
  2202. ClipperLib.IntPoint2.prototype = ClipperLib.IntPoint.prototype;
  2203. /**
  2204. * @constructor
  2205. */
  2206. ClipperLib.IntRect = function ()
  2207. {
  2208. var a = arguments,
  2209. alen = a.length;
  2210. if (alen === 4) // function (l, t, r, b)
  2211. {
  2212. this.left = a[0];
  2213. this.top = a[1];
  2214. this.right = a[2];
  2215. this.bottom = a[3];
  2216. }
  2217. else if (alen === 1) // function (ir)
  2218. {
  2219. var ir = a[0];
  2220. this.left = ir.left;
  2221. this.top = ir.top;
  2222. this.right = ir.right;
  2223. this.bottom = ir.bottom;
  2224. }
  2225. else // function ()
  2226. {
  2227. this.left = 0;
  2228. this.top = 0;
  2229. this.right = 0;
  2230. this.bottom = 0;
  2231. }
  2232. };
  2233. /**
  2234. * @constructor
  2235. */
  2236. ClipperLib.IntRect0 = function ()
  2237. {
  2238. this.left = 0;
  2239. this.top = 0;
  2240. this.right = 0;
  2241. this.bottom = 0;
  2242. };
  2243. ClipperLib.IntRect0.prototype = ClipperLib.IntRect.prototype;
  2244. /**
  2245. * @constructor
  2246. */
  2247. ClipperLib.IntRect1 = function (ir)
  2248. {
  2249. this.left = ir.left;
  2250. this.top = ir.top;
  2251. this.right = ir.right;
  2252. this.bottom = ir.bottom;
  2253. };
  2254. ClipperLib.IntRect1.prototype = ClipperLib.IntRect.prototype;
  2255. /**
  2256. * @constructor
  2257. */
  2258. ClipperLib.IntRect4 = function (l, t, r, b)
  2259. {
  2260. this.left = l;
  2261. this.top = t;
  2262. this.right = r;
  2263. this.bottom = b;
  2264. };
  2265. ClipperLib.IntRect4.prototype = ClipperLib.IntRect.prototype;
  2266. ClipperLib.ClipType = {
  2267. ctIntersection: 0,
  2268. ctUnion: 1,
  2269. ctDifference: 2,
  2270. ctXor: 3
  2271. };
  2272. ClipperLib.PolyType = {
  2273. ptSubject: 0,
  2274. ptClip: 1
  2275. };
  2276. ClipperLib.PolyFillType = {
  2277. pftEvenOdd: 0,
  2278. pftNonZero: 1,
  2279. pftPositive: 2,
  2280. pftNegative: 3
  2281. };
  2282. ClipperLib.JoinType = {
  2283. jtSquare: 0,
  2284. jtRound: 1,
  2285. jtMiter: 2
  2286. };
  2287. ClipperLib.EndType = {
  2288. etOpenSquare: 0,
  2289. etOpenRound: 1,
  2290. etOpenButt: 2,
  2291. etClosedLine: 3,
  2292. etClosedPolygon: 4
  2293. };
  2294. ClipperLib.EdgeSide = {
  2295. esLeft: 0,
  2296. esRight: 1
  2297. };
  2298. ClipperLib.Direction = {
  2299. dRightToLeft: 0,
  2300. dLeftToRight: 1
  2301. };
  2302. /**
  2303. * @constructor
  2304. */
  2305. ClipperLib.TEdge = function ()
  2306. {
  2307. this.Bot = new ClipperLib.IntPoint0();
  2308. this.Curr = new ClipperLib.IntPoint0(); //current (updated for every new scanbeam)
  2309. this.Top = new ClipperLib.IntPoint0();
  2310. this.Delta = new ClipperLib.IntPoint0();
  2311. this.Dx = 0;
  2312. this.PolyTyp = ClipperLib.PolyType.ptSubject;
  2313. this.Side = ClipperLib.EdgeSide.esLeft; //side only refers to current side of solution poly
  2314. this.WindDelta = 0; //1 or -1 depending on winding direction
  2315. this.WindCnt = 0;
  2316. this.WindCnt2 = 0; //winding count of the opposite polytype
  2317. this.OutIdx = 0;
  2318. this.Next = null;
  2319. this.Prev = null;
  2320. this.NextInLML = null;
  2321. this.NextInAEL = null;
  2322. this.PrevInAEL = null;
  2323. this.NextInSEL = null;
  2324. this.PrevInSEL = null;
  2325. };
  2326. /**
  2327. * @constructor
  2328. */
  2329. ClipperLib.IntersectNode = function ()
  2330. {
  2331. this.Edge1 = null;
  2332. this.Edge2 = null;
  2333. this.Pt = new ClipperLib.IntPoint0();
  2334. };
  2335. ClipperLib.MyIntersectNodeSort = function () {};
  2336. ClipperLib.MyIntersectNodeSort.Compare = function (node1, node2)
  2337. {
  2338. var i = node2.Pt.Y - node1.Pt.Y;
  2339. if (i > 0) return 1;
  2340. else if (i < 0) return -1;
  2341. else return 0;
  2342. };
  2343. /**
  2344. * @constructor
  2345. */
  2346. ClipperLib.LocalMinima = function ()
  2347. {
  2348. this.Y = 0;
  2349. this.LeftBound = null;
  2350. this.RightBound = null;
  2351. this.Next = null;
  2352. };
  2353. /**
  2354. * @constructor
  2355. */
  2356. ClipperLib.Scanbeam = function ()
  2357. {
  2358. this.Y = 0;
  2359. this.Next = null;
  2360. };
  2361. /**
  2362. * @constructor
  2363. */
  2364. ClipperLib.Maxima = function ()
  2365. {
  2366. this.X = 0;
  2367. this.Next = null;
  2368. this.Prev = null;
  2369. };
  2370. //OutRec: contains a path in the clipping solution. Edges in the AEL will
  2371. //carry a pointer to an OutRec when they are part of the clipping solution.
  2372. /**
  2373. * @constructor
  2374. */
  2375. ClipperLib.OutRec = function ()
  2376. {
  2377. this.Idx = 0;
  2378. this.IsHole = false;
  2379. this.IsOpen = false;
  2380. this.FirstLeft = null; //see comments in clipper.pas
  2381. this.Pts = null;
  2382. this.BottomPt = null;
  2383. this.PolyNode = null;
  2384. };
  2385. /**
  2386. * @constructor
  2387. */
  2388. ClipperLib.OutPt = function ()
  2389. {
  2390. this.Idx = 0;
  2391. this.Pt = new ClipperLib.IntPoint0();
  2392. this.Next = null;
  2393. this.Prev = null;
  2394. };
  2395. /**
  2396. * @constructor
  2397. */
  2398. ClipperLib.Join = function ()
  2399. {
  2400. this.OutPt1 = null;
  2401. this.OutPt2 = null;
  2402. this.OffPt = new ClipperLib.IntPoint0();
  2403. };
  2404. ClipperLib.ClipperBase = function ()
  2405. {
  2406. this.m_MinimaList = null;
  2407. this.m_CurrentLM = null;
  2408. this.m_edges = new Array();
  2409. this.m_UseFullRange = false;
  2410. this.m_HasOpenPaths = false;
  2411. this.PreserveCollinear = false;
  2412. this.m_Scanbeam = null;
  2413. this.m_PolyOuts = null;
  2414. this.m_ActiveEdges = null;
  2415. };
  2416. // Ranges are in original C# too high for Javascript (in current state 2013 september):
  2417. // protected const double horizontal = -3.4E+38;
  2418. // internal const cInt loRange = 0x3FFFFFFF; // = 1073741823 = sqrt(2^63 -1)/2
  2419. // internal const cInt hiRange = 0x3FFFFFFFFFFFFFFFL; // = 4611686018427387903 = sqrt(2^127 -1)/2
  2420. // So had to adjust them to more suitable for Javascript.
  2421. // If JS some day supports truly 64-bit integers, then these ranges can be as in C#
  2422. // and biginteger library can be more simpler (as then 128bit can be represented as two 64bit numbers)
  2423. ClipperLib.ClipperBase.horizontal = -9007199254740992; //-2^53
  2424. ClipperLib.ClipperBase.Skip = -2;
  2425. ClipperLib.ClipperBase.Unassigned = -1;
  2426. ClipperLib.ClipperBase.tolerance = 1E-20;
  2427. ClipperLib.ClipperBase.loRange = 47453132; // sqrt(2^53 -1)/2
  2428. ClipperLib.ClipperBase.hiRange = 4503599627370495; // sqrt(2^106 -1)/2
  2429. ClipperLib.ClipperBase.near_zero = function (val)
  2430. {
  2431. return (val > -ClipperLib.ClipperBase.tolerance) && (val < ClipperLib.ClipperBase.tolerance);
  2432. };
  2433. ClipperLib.ClipperBase.IsHorizontal = function (e)
  2434. {
  2435. return e.Delta.Y === 0;
  2436. };
  2437. ClipperLib.ClipperBase.prototype.PointIsVertex = function (pt, pp)
  2438. {
  2439. var pp2 = pp;
  2440. do {
  2441. if (ClipperLib.IntPoint.op_Equality(pp2.Pt, pt))
  2442. return true;
  2443. pp2 = pp2.Next;
  2444. }
  2445. while (pp2 !== pp)
  2446. return false;
  2447. };
  2448. ClipperLib.ClipperBase.prototype.PointOnLineSegment = function (pt, linePt1, linePt2, UseFullRange)
  2449. {
  2450. if (UseFullRange)
  2451. return ((pt.X === linePt1.X) && (pt.Y === linePt1.Y)) ||
  2452. ((pt.X === linePt2.X) && (pt.Y === linePt2.Y)) ||
  2453. (((pt.X > linePt1.X) === (pt.X < linePt2.X)) &&
  2454. ((pt.Y > linePt1.Y) === (pt.Y < linePt2.Y)) &&
  2455. (Int128.op_Equality(Int128.Int128Mul((pt.X - linePt1.X), (linePt2.Y - linePt1.Y)),
  2456. Int128.Int128Mul((linePt2.X - linePt1.X), (pt.Y - linePt1.Y)))));
  2457. else
  2458. return ((pt.X === linePt1.X) && (pt.Y === linePt1.Y)) || ((pt.X === linePt2.X) && (pt.Y === linePt2.Y)) || (((pt.X > linePt1.X) === (pt.X < linePt2.X)) && ((pt.Y > linePt1.Y) === (pt.Y < linePt2.Y)) && ((pt.X - linePt1.X) * (linePt2.Y - linePt1.Y) === (linePt2.X - linePt1.X) * (pt.Y - linePt1.Y)));
  2459. };
  2460. ClipperLib.ClipperBase.prototype.PointOnPolygon = function (pt, pp, UseFullRange)
  2461. {
  2462. var pp2 = pp;
  2463. while (true)
  2464. {
  2465. if (this.PointOnLineSegment(pt, pp2.Pt, pp2.Next.Pt, UseFullRange))
  2466. return true;
  2467. pp2 = pp2.Next;
  2468. if (pp2 === pp)
  2469. break;
  2470. }
  2471. return false;
  2472. };
  2473. ClipperLib.ClipperBase.prototype.SlopesEqual = ClipperLib.ClipperBase.SlopesEqual = function ()
  2474. {
  2475. var a = arguments,
  2476. alen = a.length;
  2477. var e1, e2, pt1, pt2, pt3, pt4, UseFullRange;
  2478. if (alen === 3) // function (e1, e2, UseFullRange)
  2479. {
  2480. e1 = a[0];
  2481. e2 = a[1];
  2482. UseFullRange = a[2];
  2483. if (UseFullRange)
  2484. return Int128.op_Equality(Int128.Int128Mul(e1.Delta.Y, e2.Delta.X), Int128.Int128Mul(e1.Delta.X, e2.Delta.Y));
  2485. else
  2486. return ClipperLib.Cast_Int64((e1.Delta.Y) * (e2.Delta.X)) === ClipperLib.Cast_Int64((e1.Delta.X) * (e2.Delta.Y));
  2487. }
  2488. else if (alen === 4) // function (pt1, pt2, pt3, UseFullRange)
  2489. {
  2490. pt1 = a[0];
  2491. pt2 = a[1];
  2492. pt3 = a[2];
  2493. UseFullRange = a[3];
  2494. if (UseFullRange)
  2495. return Int128.op_Equality(Int128.Int128Mul(pt1.Y - pt2.Y, pt2.X - pt3.X), Int128.Int128Mul(pt1.X - pt2.X, pt2.Y - pt3.Y));
  2496. else
  2497. return ClipperLib.Cast_Int64((pt1.Y - pt2.Y) * (pt2.X - pt3.X)) - ClipperLib.Cast_Int64((pt1.X - pt2.X) * (pt2.Y - pt3.Y)) === 0;
  2498. }
  2499. else // function (pt1, pt2, pt3, pt4, UseFullRange)
  2500. {
  2501. pt1 = a[0];
  2502. pt2 = a[1];
  2503. pt3 = a[2];
  2504. pt4 = a[3];
  2505. UseFullRange = a[4];
  2506. if (UseFullRange)
  2507. return Int128.op_Equality(Int128.Int128Mul(pt1.Y - pt2.Y, pt3.X - pt4.X), Int128.Int128Mul(pt1.X - pt2.X, pt3.Y - pt4.Y));
  2508. else
  2509. return ClipperLib.Cast_Int64((pt1.Y - pt2.Y) * (pt3.X - pt4.X)) - ClipperLib.Cast_Int64((pt1.X - pt2.X) * (pt3.Y - pt4.Y)) === 0;
  2510. }
  2511. };
  2512. ClipperLib.ClipperBase.SlopesEqual3 = function (e1, e2, UseFullRange)
  2513. {
  2514. if (UseFullRange)
  2515. return Int128.op_Equality(Int128.Int128Mul(e1.Delta.Y, e2.Delta.X), Int128.Int128Mul(e1.Delta.X, e2.Delta.Y));
  2516. else
  2517. return ClipperLib.Cast_Int64((e1.Delta.Y) * (e2.Delta.X)) === ClipperLib.Cast_Int64((e1.Delta.X) * (e2.Delta.Y));
  2518. };
  2519. ClipperLib.ClipperBase.SlopesEqual4 = function (pt1, pt2, pt3, UseFullRange)
  2520. {
  2521. if (UseFullRange)
  2522. return Int128.op_Equality(Int128.Int128Mul(pt1.Y - pt2.Y, pt2.X - pt3.X), Int128.Int128Mul(pt1.X - pt2.X, pt2.Y - pt3.Y));
  2523. else
  2524. return ClipperLib.Cast_Int64((pt1.Y - pt2.Y) * (pt2.X - pt3.X)) - ClipperLib.Cast_Int64((pt1.X - pt2.X) * (pt2.Y - pt3.Y)) === 0;
  2525. };
  2526. ClipperLib.ClipperBase.SlopesEqual5 = function (pt1, pt2, pt3, pt4, UseFullRange)
  2527. {
  2528. if (UseFullRange)
  2529. return Int128.op_Equality(Int128.Int128Mul(pt1.Y - pt2.Y, pt3.X - pt4.X), Int128.Int128Mul(pt1.X - pt2.X, pt3.Y - pt4.Y));
  2530. else
  2531. return ClipperLib.Cast_Int64((pt1.Y - pt2.Y) * (pt3.X - pt4.X)) - ClipperLib.Cast_Int64((pt1.X - pt2.X) * (pt3.Y - pt4.Y)) === 0;
  2532. };
  2533. ClipperLib.ClipperBase.prototype.Clear = function ()
  2534. {
  2535. this.DisposeLocalMinimaList();
  2536. for (var i = 0, ilen = this.m_edges.length; i < ilen; ++i)
  2537. {
  2538. for (var j = 0, jlen = this.m_edges[i].length; j < jlen; ++j)
  2539. this.m_edges[i][j] = null;
  2540. ClipperLib.Clear(this.m_edges[i]);
  2541. }
  2542. ClipperLib.Clear(this.m_edges);
  2543. this.m_UseFullRange = false;
  2544. this.m_HasOpenPaths = false;
  2545. };
  2546. ClipperLib.ClipperBase.prototype.DisposeLocalMinimaList = function ()
  2547. {
  2548. while (this.m_MinimaList !== null)
  2549. {
  2550. var tmpLm = this.m_MinimaList.Next;
  2551. this.m_MinimaList = null;
  2552. this.m_MinimaList = tmpLm;
  2553. }
  2554. this.m_CurrentLM = null;
  2555. };
  2556. ClipperLib.ClipperBase.prototype.RangeTest = function (Pt, useFullRange)
  2557. {
  2558. if (useFullRange.Value)
  2559. {
  2560. if (Pt.X > ClipperLib.ClipperBase.hiRange || Pt.Y > ClipperLib.ClipperBase.hiRange || -Pt.X > ClipperLib.ClipperBase.hiRange || -Pt.Y > ClipperLib.ClipperBase.hiRange)
  2561. ClipperLib.Error("Coordinate outside allowed range in RangeTest().");
  2562. }
  2563. else if (Pt.X > ClipperLib.ClipperBase.loRange || Pt.Y > ClipperLib.ClipperBase.loRange || -Pt.X > ClipperLib.ClipperBase.loRange || -Pt.Y > ClipperLib.ClipperBase.loRange)
  2564. {
  2565. useFullRange.Value = true;
  2566. this.RangeTest(Pt, useFullRange);
  2567. }
  2568. };
  2569. ClipperLib.ClipperBase.prototype.InitEdge = function (e, eNext, ePrev, pt)
  2570. {
  2571. e.Next = eNext;
  2572. e.Prev = ePrev;
  2573. //e.Curr = pt;
  2574. e.Curr.X = pt.X;
  2575. e.Curr.Y = pt.Y;
  2576. if (ClipperLib.use_xyz) e.Curr.Z = pt.Z;
  2577. e.OutIdx = -1;
  2578. };
  2579. ClipperLib.ClipperBase.prototype.InitEdge2 = function (e, polyType)
  2580. {
  2581. if (e.Curr.Y >= e.Next.Curr.Y)
  2582. {
  2583. //e.Bot = e.Curr;
  2584. e.Bot.X = e.Curr.X;
  2585. e.Bot.Y = e.Curr.Y;
  2586. if (ClipperLib.use_xyz) e.Bot.Z = e.Curr.Z;
  2587. //e.Top = e.Next.Curr;
  2588. e.Top.X = e.Next.Curr.X;
  2589. e.Top.Y = e.Next.Curr.Y;
  2590. if (ClipperLib.use_xyz) e.Top.Z = e.Next.Curr.Z;
  2591. }
  2592. else
  2593. {
  2594. //e.Top = e.Curr;
  2595. e.Top.X = e.Curr.X;
  2596. e.Top.Y = e.Curr.Y;
  2597. if (ClipperLib.use_xyz) e.Top.Z = e.Curr.Z;
  2598. //e.Bot = e.Next.Curr;
  2599. e.Bot.X = e.Next.Curr.X;
  2600. e.Bot.Y = e.Next.Curr.Y;
  2601. if (ClipperLib.use_xyz) e.Bot.Z = e.Next.Curr.Z;
  2602. }
  2603. this.SetDx(e);
  2604. e.PolyTyp = polyType;
  2605. };
  2606. ClipperLib.ClipperBase.prototype.FindNextLocMin = function (E)
  2607. {
  2608. var E2;
  2609. for (;;)
  2610. {
  2611. while (ClipperLib.IntPoint.op_Inequality(E.Bot, E.Prev.Bot) || ClipperLib.IntPoint.op_Equality(E.Curr, E.Top))
  2612. E = E.Next;
  2613. if (E.Dx !== ClipperLib.ClipperBase.horizontal && E.Prev.Dx !== ClipperLib.ClipperBase.horizontal)
  2614. break;
  2615. while (E.Prev.Dx === ClipperLib.ClipperBase.horizontal)
  2616. E = E.Prev;
  2617. E2 = E;
  2618. while (E.Dx === ClipperLib.ClipperBase.horizontal)
  2619. E = E.Next;
  2620. if (E.Top.Y === E.Prev.Bot.Y)
  2621. continue;
  2622. //ie just an intermediate horz.
  2623. if (E2.Prev.Bot.X < E.Bot.X)
  2624. E = E2;
  2625. break;
  2626. }
  2627. return E;
  2628. };
  2629. ClipperLib.ClipperBase.prototype.ProcessBound = function (E, LeftBoundIsForward)
  2630. {
  2631. var EStart;
  2632. var Result = E;
  2633. var Horz;
  2634. if (Result.OutIdx === ClipperLib.ClipperBase.Skip)
  2635. {
  2636. //check if there are edges beyond the skip edge in the bound and if so
  2637. //create another LocMin and calling ProcessBound once more ...
  2638. E = Result;
  2639. if (LeftBoundIsForward)
  2640. {
  2641. while (E.Top.Y === E.Next.Bot.Y) E = E.Next;
  2642. while (E !== Result && E.Dx === ClipperLib.ClipperBase.horizontal) E = E.Prev;
  2643. }
  2644. else
  2645. {
  2646. while (E.Top.Y === E.Prev.Bot.Y) E = E.Prev;
  2647. while (E !== Result && E.Dx === ClipperLib.ClipperBase.horizontal) E = E.Next;
  2648. }
  2649. if (E === Result)
  2650. {
  2651. if (LeftBoundIsForward) Result = E.Next;
  2652. else Result = E.Prev;
  2653. }
  2654. else
  2655. {
  2656. //there are more edges in the bound beyond result starting with E
  2657. if (LeftBoundIsForward)
  2658. E = Result.Next;
  2659. else
  2660. E = Result.Prev;
  2661. var locMin = new ClipperLib.LocalMinima();
  2662. locMin.Next = null;
  2663. locMin.Y = E.Bot.Y;
  2664. locMin.LeftBound = null;
  2665. locMin.RightBound = E;
  2666. E.WindDelta = 0;
  2667. Result = this.ProcessBound(E, LeftBoundIsForward);
  2668. this.InsertLocalMinima(locMin);
  2669. }
  2670. return Result;
  2671. }
  2672. if (E.Dx === ClipperLib.ClipperBase.horizontal)
  2673. {
  2674. //We need to be careful with open paths because this may not be a
  2675. //true local minima (ie E may be following a skip edge).
  2676. //Also, consecutive horz. edges may start heading left before going right.
  2677. if (LeftBoundIsForward) EStart = E.Prev;
  2678. else EStart = E.Next;
  2679. if (EStart.Dx === ClipperLib.ClipperBase.horizontal) //ie an adjoining horizontal skip edge
  2680. {
  2681. if (EStart.Bot.X !== E.Bot.X && EStart.Top.X !== E.Bot.X)
  2682. this.ReverseHorizontal(E);
  2683. }
  2684. else if (EStart.Bot.X !== E.Bot.X)
  2685. this.ReverseHorizontal(E);
  2686. }
  2687. EStart = E;
  2688. if (LeftBoundIsForward)
  2689. {
  2690. while (Result.Top.Y === Result.Next.Bot.Y && Result.Next.OutIdx !== ClipperLib.ClipperBase.Skip)
  2691. Result = Result.Next;
  2692. if (Result.Dx === ClipperLib.ClipperBase.horizontal && Result.Next.OutIdx !== ClipperLib.ClipperBase.Skip)
  2693. {
  2694. //nb: at the top of a bound, horizontals are added to the bound
  2695. //only when the preceding edge attaches to the horizontal's left vertex
  2696. //unless a Skip edge is encountered when that becomes the top divide
  2697. Horz = Result;
  2698. while (Horz.Prev.Dx === ClipperLib.ClipperBase.horizontal)
  2699. Horz = Horz.Prev;
  2700. if (Horz.Prev.Top.X > Result.Next.Top.X)
  2701. Result = Horz.Prev;
  2702. }
  2703. while (E !== Result)
  2704. {
  2705. E.NextInLML = E.Next;
  2706. if (E.Dx === ClipperLib.ClipperBase.horizontal && E !== EStart && E.Bot.X !== E.Prev.Top.X)
  2707. this.ReverseHorizontal(E);
  2708. E = E.Next;
  2709. }
  2710. if (E.Dx === ClipperLib.ClipperBase.horizontal && E !== EStart && E.Bot.X !== E.Prev.Top.X)
  2711. this.ReverseHorizontal(E);
  2712. Result = Result.Next;
  2713. //move to the edge just beyond current bound
  2714. }
  2715. else
  2716. {
  2717. while (Result.Top.Y === Result.Prev.Bot.Y && Result.Prev.OutIdx !== ClipperLib.ClipperBase.Skip)
  2718. Result = Result.Prev;
  2719. if (Result.Dx === ClipperLib.ClipperBase.horizontal && Result.Prev.OutIdx !== ClipperLib.ClipperBase.Skip)
  2720. {
  2721. Horz = Result;
  2722. while (Horz.Next.Dx === ClipperLib.ClipperBase.horizontal)
  2723. Horz = Horz.Next;
  2724. if (Horz.Next.Top.X === Result.Prev.Top.X || Horz.Next.Top.X > Result.Prev.Top.X)
  2725. {
  2726. Result = Horz.Next;
  2727. }
  2728. }
  2729. while (E !== Result)
  2730. {
  2731. E.NextInLML = E.Prev;
  2732. if (E.Dx === ClipperLib.ClipperBase.horizontal && E !== EStart && E.Bot.X !== E.Next.Top.X)
  2733. this.ReverseHorizontal(E);
  2734. E = E.Prev;
  2735. }
  2736. if (E.Dx === ClipperLib.ClipperBase.horizontal && E !== EStart && E.Bot.X !== E.Next.Top.X)
  2737. this.ReverseHorizontal(E);
  2738. Result = Result.Prev;
  2739. //move to the edge just beyond current bound
  2740. }
  2741. return Result;
  2742. };
  2743. ClipperLib.ClipperBase.prototype.AddPath = function (pg, polyType, Closed)
  2744. {
  2745. if (ClipperLib.use_lines)
  2746. {
  2747. if (!Closed && polyType === ClipperLib.PolyType.ptClip)
  2748. ClipperLib.Error("AddPath: Open paths must be subject.");
  2749. }
  2750. else
  2751. {
  2752. if (!Closed)
  2753. ClipperLib.Error("AddPath: Open paths have been disabled.");
  2754. }
  2755. var highI = pg.length - 1;
  2756. if (Closed)
  2757. while (highI > 0 && (ClipperLib.IntPoint.op_Equality(pg[highI], pg[0])))
  2758. --highI;
  2759. while (highI > 0 && (ClipperLib.IntPoint.op_Equality(pg[highI], pg[highI - 1])))
  2760. --highI;
  2761. if ((Closed && highI < 2) || (!Closed && highI < 1))
  2762. return false;
  2763. //create a new edge array ...
  2764. var edges = new Array();
  2765. for (var i = 0; i <= highI; i++)
  2766. edges.push(new ClipperLib.TEdge());
  2767. var IsFlat = true;
  2768. //1. Basic (first) edge initialization ...
  2769. //edges[1].Curr = pg[1];
  2770. edges[1].Curr.X = pg[1].X;
  2771. edges[1].Curr.Y = pg[1].Y;
  2772. if (ClipperLib.use_xyz) edges[1].Curr.Z = pg[1].Z;
  2773. var $1 = {
  2774. Value: this.m_UseFullRange
  2775. };
  2776. this.RangeTest(pg[0], $1);
  2777. this.m_UseFullRange = $1.Value;
  2778. $1.Value = this.m_UseFullRange;
  2779. this.RangeTest(pg[highI], $1);
  2780. this.m_UseFullRange = $1.Value;
  2781. this.InitEdge(edges[0], edges[1], edges[highI], pg[0]);
  2782. this.InitEdge(edges[highI], edges[0], edges[highI - 1], pg[highI]);
  2783. for (var i = highI - 1; i >= 1; --i)
  2784. {
  2785. $1.Value = this.m_UseFullRange;
  2786. this.RangeTest(pg[i], $1);
  2787. this.m_UseFullRange = $1.Value;
  2788. this.InitEdge(edges[i], edges[i + 1], edges[i - 1], pg[i]);
  2789. }
  2790. var eStart = edges[0];
  2791. //2. Remove duplicate vertices, and (when closed) collinear edges ...
  2792. var E = eStart,
  2793. eLoopStop = eStart;
  2794. for (;;)
  2795. {
  2796. //console.log(E.Next, eStart);
  2797. //nb: allows matching start and end points when not Closed ...
  2798. if (E.Curr === E.Next.Curr && (Closed || E.Next !== eStart))
  2799. {
  2800. if (E === E.Next)
  2801. break;
  2802. if (E === eStart)
  2803. eStart = E.Next;
  2804. E = this.RemoveEdge(E);
  2805. eLoopStop = E;
  2806. continue;
  2807. }
  2808. if (E.Prev === E.Next)
  2809. break;
  2810. else if (Closed && ClipperLib.ClipperBase.SlopesEqual4(E.Prev.Curr, E.Curr, E.Next.Curr, this.m_UseFullRange) && (!this.PreserveCollinear || !this.Pt2IsBetweenPt1AndPt3(E.Prev.Curr, E.Curr, E.Next.Curr)))
  2811. {
  2812. //Collinear edges are allowed for open paths but in closed paths
  2813. //the default is to merge adjacent collinear edges into a single edge.
  2814. //However, if the PreserveCollinear property is enabled, only overlapping
  2815. //collinear edges (ie spikes) will be removed from closed paths.
  2816. if (E === eStart)
  2817. eStart = E.Next;
  2818. E = this.RemoveEdge(E);
  2819. E = E.Prev;
  2820. eLoopStop = E;
  2821. continue;
  2822. }
  2823. E = E.Next;
  2824. if ((E === eLoopStop) || (!Closed && E.Next === eStart)) break;
  2825. }
  2826. if ((!Closed && (E === E.Next)) || (Closed && (E.Prev === E.Next)))
  2827. return false;
  2828. if (!Closed)
  2829. {
  2830. this.m_HasOpenPaths = true;
  2831. eStart.Prev.OutIdx = ClipperLib.ClipperBase.Skip;
  2832. }
  2833. //3. Do second stage of edge initialization ...
  2834. E = eStart;
  2835. do {
  2836. this.InitEdge2(E, polyType);
  2837. E = E.Next;
  2838. if (IsFlat && E.Curr.Y !== eStart.Curr.Y)
  2839. IsFlat = false;
  2840. }
  2841. while (E !== eStart)
  2842. //4. Finally, add edge bounds to LocalMinima list ...
  2843. //Totally flat paths must be handled differently when adding them
  2844. //to LocalMinima list to avoid endless loops etc ...
  2845. if (IsFlat)
  2846. {
  2847. if (Closed)
  2848. return false;
  2849. E.Prev.OutIdx = ClipperLib.ClipperBase.Skip;
  2850. var locMin = new ClipperLib.LocalMinima();
  2851. locMin.Next = null;
  2852. locMin.Y = E.Bot.Y;
  2853. locMin.LeftBound = null;
  2854. locMin.RightBound = E;
  2855. locMin.RightBound.Side = ClipperLib.EdgeSide.esRight;
  2856. locMin.RightBound.WindDelta = 0;
  2857. for (;;)
  2858. {
  2859. if (E.Bot.X !== E.Prev.Top.X) this.ReverseHorizontal(E);
  2860. if (E.Next.OutIdx === ClipperLib.ClipperBase.Skip) break;
  2861. E.NextInLML = E.Next;
  2862. E = E.Next;
  2863. }
  2864. this.InsertLocalMinima(locMin);
  2865. this.m_edges.push(edges);
  2866. return true;
  2867. }
  2868. this.m_edges.push(edges);
  2869. var leftBoundIsForward;
  2870. var EMin = null;
  2871. //workaround to avoid an endless loop in the while loop below when
  2872. //open paths have matching start and end points ...
  2873. if (ClipperLib.IntPoint.op_Equality(E.Prev.Bot, E.Prev.Top))
  2874. E = E.Next;
  2875. for (;;)
  2876. {
  2877. E = this.FindNextLocMin(E);
  2878. if (E === EMin)
  2879. break;
  2880. else if (EMin === null)
  2881. EMin = E;
  2882. //E and E.Prev now share a local minima (left aligned if horizontal).
  2883. //Compare their slopes to find which starts which bound ...
  2884. var locMin = new ClipperLib.LocalMinima();
  2885. locMin.Next = null;
  2886. locMin.Y = E.Bot.Y;
  2887. if (E.Dx < E.Prev.Dx)
  2888. {
  2889. locMin.LeftBound = E.Prev;
  2890. locMin.RightBound = E;
  2891. leftBoundIsForward = false;
  2892. //Q.nextInLML = Q.prev
  2893. }
  2894. else
  2895. {
  2896. locMin.LeftBound = E;
  2897. locMin.RightBound = E.Prev;
  2898. leftBoundIsForward = true;
  2899. //Q.nextInLML = Q.next
  2900. }
  2901. locMin.LeftBound.Side = ClipperLib.EdgeSide.esLeft;
  2902. locMin.RightBound.Side = ClipperLib.EdgeSide.esRight;
  2903. if (!Closed)
  2904. locMin.LeftBound.WindDelta = 0;
  2905. else if (locMin.LeftBound.Next === locMin.RightBound)
  2906. locMin.LeftBound.WindDelta = -1;
  2907. else
  2908. locMin.LeftBound.WindDelta = 1;
  2909. locMin.RightBound.WindDelta = -locMin.LeftBound.WindDelta;
  2910. E = this.ProcessBound(locMin.LeftBound, leftBoundIsForward);
  2911. if (E.OutIdx === ClipperLib.ClipperBase.Skip)
  2912. E = this.ProcessBound(E, leftBoundIsForward);
  2913. var E2 = this.ProcessBound(locMin.RightBound, !leftBoundIsForward);
  2914. if (E2.OutIdx === ClipperLib.ClipperBase.Skip) E2 = this.ProcessBound(E2, !leftBoundIsForward);
  2915. if (locMin.LeftBound.OutIdx === ClipperLib.ClipperBase.Skip)
  2916. locMin.LeftBound = null;
  2917. else if (locMin.RightBound.OutIdx === ClipperLib.ClipperBase.Skip)
  2918. locMin.RightBound = null;
  2919. this.InsertLocalMinima(locMin);
  2920. if (!leftBoundIsForward)
  2921. E = E2;
  2922. }
  2923. return true;
  2924. };
  2925. ClipperLib.ClipperBase.prototype.AddPaths = function (ppg, polyType, closed)
  2926. {
  2927. // console.log("-------------------------------------------");
  2928. // console.log(JSON.stringify(ppg));
  2929. var result = false;
  2930. for (var i = 0, ilen = ppg.length; i < ilen; ++i)
  2931. if (this.AddPath(ppg[i], polyType, closed))
  2932. result = true;
  2933. return result;
  2934. };
  2935. ClipperLib.ClipperBase.prototype.Pt2IsBetweenPt1AndPt3 = function (pt1, pt2, pt3)
  2936. {
  2937. if ((ClipperLib.IntPoint.op_Equality(pt1, pt3)) || (ClipperLib.IntPoint.op_Equality(pt1, pt2)) || (ClipperLib.IntPoint.op_Equality(pt3, pt2)))
  2938. //if ((pt1 == pt3) || (pt1 == pt2) || (pt3 == pt2))
  2939. return false;
  2940. else if (pt1.X !== pt3.X)
  2941. return (pt2.X > pt1.X) === (pt2.X < pt3.X);
  2942. else
  2943. return (pt2.Y > pt1.Y) === (pt2.Y < pt3.Y);
  2944. };
  2945. ClipperLib.ClipperBase.prototype.RemoveEdge = function (e)
  2946. {
  2947. //removes e from double_linked_list (but without removing from memory)
  2948. e.Prev.Next = e.Next;
  2949. e.Next.Prev = e.Prev;
  2950. var result = e.Next;
  2951. e.Prev = null; //flag as removed (see ClipperBase.Clear)
  2952. return result;
  2953. };
  2954. ClipperLib.ClipperBase.prototype.SetDx = function (e)
  2955. {
  2956. e.Delta.X = (e.Top.X - e.Bot.X);
  2957. e.Delta.Y = (e.Top.Y - e.Bot.Y);
  2958. if (e.Delta.Y === 0) e.Dx = ClipperLib.ClipperBase.horizontal;
  2959. else e.Dx = (e.Delta.X) / (e.Delta.Y);
  2960. };
  2961. ClipperLib.ClipperBase.prototype.InsertLocalMinima = function (newLm)
  2962. {
  2963. if (this.m_MinimaList === null)
  2964. {
  2965. this.m_MinimaList = newLm;
  2966. }
  2967. else if (newLm.Y >= this.m_MinimaList.Y)
  2968. {
  2969. newLm.Next = this.m_MinimaList;
  2970. this.m_MinimaList = newLm;
  2971. }
  2972. else
  2973. {
  2974. var tmpLm = this.m_MinimaList;
  2975. while (tmpLm.Next !== null && (newLm.Y < tmpLm.Next.Y))
  2976. tmpLm = tmpLm.Next;
  2977. newLm.Next = tmpLm.Next;
  2978. tmpLm.Next = newLm;
  2979. }
  2980. };
  2981. ClipperLib.ClipperBase.prototype.PopLocalMinima = function (Y, current)
  2982. {
  2983. current.v = this.m_CurrentLM;
  2984. if (this.m_CurrentLM !== null && this.m_CurrentLM.Y === Y)
  2985. {
  2986. this.m_CurrentLM = this.m_CurrentLM.Next;
  2987. return true;
  2988. }
  2989. return false;
  2990. };
  2991. ClipperLib.ClipperBase.prototype.ReverseHorizontal = function (e)
  2992. {
  2993. //swap horizontal edges' top and bottom x's so they follow the natural
  2994. //progression of the bounds - ie so their xbots will align with the
  2995. //adjoining lower edge. [Helpful in the ProcessHorizontal() method.]
  2996. var tmp = e.Top.X;
  2997. e.Top.X = e.Bot.X;
  2998. e.Bot.X = tmp;
  2999. if (ClipperLib.use_xyz)
  3000. {
  3001. tmp = e.Top.Z;
  3002. e.Top.Z = e.Bot.Z;
  3003. e.Bot.Z = tmp;
  3004. }
  3005. };
  3006. ClipperLib.ClipperBase.prototype.Reset = function ()
  3007. {
  3008. this.m_CurrentLM = this.m_MinimaList;
  3009. if (this.m_CurrentLM === null) //ie nothing to process
  3010. return;
  3011. //reset all edges ...
  3012. this.m_Scanbeam = null;
  3013. var lm = this.m_MinimaList;
  3014. while (lm !== null)
  3015. {
  3016. this.InsertScanbeam(lm.Y);
  3017. var e = lm.LeftBound;
  3018. if (e !== null)
  3019. {
  3020. //e.Curr = e.Bot;
  3021. e.Curr.X = e.Bot.X;
  3022. e.Curr.Y = e.Bot.Y;
  3023. if (ClipperLib.use_xyz) e.Curr.Z = e.Bot.Z;
  3024. e.OutIdx = ClipperLib.ClipperBase.Unassigned;
  3025. }
  3026. e = lm.RightBound;
  3027. if (e !== null)
  3028. {
  3029. //e.Curr = e.Bot;
  3030. e.Curr.X = e.Bot.X;
  3031. e.Curr.Y = e.Bot.Y;
  3032. if (ClipperLib.use_xyz) e.Curr.Z = e.Bot.Z;
  3033. e.OutIdx = ClipperLib.ClipperBase.Unassigned;
  3034. }
  3035. lm = lm.Next;
  3036. }
  3037. this.m_ActiveEdges = null;
  3038. };
  3039. ClipperLib.ClipperBase.prototype.InsertScanbeam = function (Y)
  3040. {
  3041. //single-linked list: sorted descending, ignoring dups.
  3042. if (this.m_Scanbeam === null)
  3043. {
  3044. this.m_Scanbeam = new ClipperLib.Scanbeam();
  3045. this.m_Scanbeam.Next = null;
  3046. this.m_Scanbeam.Y = Y;
  3047. }
  3048. else if (Y > this.m_Scanbeam.Y)
  3049. {
  3050. var newSb = new ClipperLib.Scanbeam();
  3051. newSb.Y = Y;
  3052. newSb.Next = this.m_Scanbeam;
  3053. this.m_Scanbeam = newSb;
  3054. }
  3055. else
  3056. {
  3057. var sb2 = this.m_Scanbeam;
  3058. while (sb2.Next !== null && Y <= sb2.Next.Y)
  3059. {
  3060. sb2 = sb2.Next;
  3061. }
  3062. if (Y === sb2.Y)
  3063. {
  3064. return;
  3065. } //ie ignores duplicates
  3066. var newSb1 = new ClipperLib.Scanbeam();
  3067. newSb1.Y = Y;
  3068. newSb1.Next = sb2.Next;
  3069. sb2.Next = newSb1;
  3070. }
  3071. };
  3072. ClipperLib.ClipperBase.prototype.PopScanbeam = function (Y)
  3073. {
  3074. if (this.m_Scanbeam === null)
  3075. {
  3076. Y.v = 0;
  3077. return false;
  3078. }
  3079. Y.v = this.m_Scanbeam.Y;
  3080. this.m_Scanbeam = this.m_Scanbeam.Next;
  3081. return true;
  3082. };
  3083. ClipperLib.ClipperBase.prototype.LocalMinimaPending = function ()
  3084. {
  3085. return (this.m_CurrentLM !== null);
  3086. };
  3087. ClipperLib.ClipperBase.prototype.CreateOutRec = function ()
  3088. {
  3089. var result = new ClipperLib.OutRec();
  3090. result.Idx = ClipperLib.ClipperBase.Unassigned;
  3091. result.IsHole = false;
  3092. result.IsOpen = false;
  3093. result.FirstLeft = null;
  3094. result.Pts = null;
  3095. result.BottomPt = null;
  3096. result.PolyNode = null;
  3097. this.m_PolyOuts.push(result);
  3098. result.Idx = this.m_PolyOuts.length - 1;
  3099. return result;
  3100. };
  3101. ClipperLib.ClipperBase.prototype.DisposeOutRec = function (index)
  3102. {
  3103. var outRec = this.m_PolyOuts[index];
  3104. outRec.Pts = null;
  3105. outRec = null;
  3106. this.m_PolyOuts[index] = null;
  3107. };
  3108. ClipperLib.ClipperBase.prototype.UpdateEdgeIntoAEL = function (e)
  3109. {
  3110. if (e.NextInLML === null)
  3111. {
  3112. ClipperLib.Error("UpdateEdgeIntoAEL: invalid call");
  3113. }
  3114. var AelPrev = e.PrevInAEL;
  3115. var AelNext = e.NextInAEL;
  3116. e.NextInLML.OutIdx = e.OutIdx;
  3117. if (AelPrev !== null)
  3118. {
  3119. AelPrev.NextInAEL = e.NextInLML;
  3120. }
  3121. else
  3122. {
  3123. this.m_ActiveEdges = e.NextInLML;
  3124. }
  3125. if (AelNext !== null)
  3126. {
  3127. AelNext.PrevInAEL = e.NextInLML;
  3128. }
  3129. e.NextInLML.Side = e.Side;
  3130. e.NextInLML.WindDelta = e.WindDelta;
  3131. e.NextInLML.WindCnt = e.WindCnt;
  3132. e.NextInLML.WindCnt2 = e.WindCnt2;
  3133. e = e.NextInLML;
  3134. e.Curr.X = e.Bot.X;
  3135. e.Curr.Y = e.Bot.Y;
  3136. e.PrevInAEL = AelPrev;
  3137. e.NextInAEL = AelNext;
  3138. if (!ClipperLib.ClipperBase.IsHorizontal(e))
  3139. {
  3140. this.InsertScanbeam(e.Top.Y);
  3141. }
  3142. return e;
  3143. };
  3144. ClipperLib.ClipperBase.prototype.SwapPositionsInAEL = function (edge1, edge2)
  3145. {
  3146. //check that one or other edge hasn't already been removed from AEL ...
  3147. if (edge1.NextInAEL === edge1.PrevInAEL || edge2.NextInAEL === edge2.PrevInAEL)
  3148. {
  3149. return;
  3150. }
  3151. if (edge1.NextInAEL === edge2)
  3152. {
  3153. var next = edge2.NextInAEL;
  3154. if (next !== null)
  3155. {
  3156. next.PrevInAEL = edge1;
  3157. }
  3158. var prev = edge1.PrevInAEL;
  3159. if (prev !== null)
  3160. {
  3161. prev.NextInAEL = edge2;
  3162. }
  3163. edge2.PrevInAEL = prev;
  3164. edge2.NextInAEL = edge1;
  3165. edge1.PrevInAEL = edge2;
  3166. edge1.NextInAEL = next;
  3167. }
  3168. else if (edge2.NextInAEL === edge1)
  3169. {
  3170. var next1 = edge1.NextInAEL;
  3171. if (next1 !== null)
  3172. {
  3173. next1.PrevInAEL = edge2;
  3174. }
  3175. var prev1 = edge2.PrevInAEL;
  3176. if (prev1 !== null)
  3177. {
  3178. prev1.NextInAEL = edge1;
  3179. }
  3180. edge1.PrevInAEL = prev1;
  3181. edge1.NextInAEL = edge2;
  3182. edge2.PrevInAEL = edge1;
  3183. edge2.NextInAEL = next1;
  3184. }
  3185. else
  3186. {
  3187. var next2 = edge1.NextInAEL;
  3188. var prev2 = edge1.PrevInAEL;
  3189. edge1.NextInAEL = edge2.NextInAEL;
  3190. if (edge1.NextInAEL !== null)
  3191. {
  3192. edge1.NextInAEL.PrevInAEL = edge1;
  3193. }
  3194. edge1.PrevInAEL = edge2.PrevInAEL;
  3195. if (edge1.PrevInAEL !== null)
  3196. {
  3197. edge1.PrevInAEL.NextInAEL = edge1;
  3198. }
  3199. edge2.NextInAEL = next2;
  3200. if (edge2.NextInAEL !== null)
  3201. {
  3202. edge2.NextInAEL.PrevInAEL = edge2;
  3203. }
  3204. edge2.PrevInAEL = prev2;
  3205. if (edge2.PrevInAEL !== null)
  3206. {
  3207. edge2.PrevInAEL.NextInAEL = edge2;
  3208. }
  3209. }
  3210. if (edge1.PrevInAEL === null)
  3211. {
  3212. this.m_ActiveEdges = edge1;
  3213. }
  3214. else
  3215. {
  3216. if (edge2.PrevInAEL === null)
  3217. {
  3218. this.m_ActiveEdges = edge2;
  3219. }
  3220. }
  3221. };
  3222. ClipperLib.ClipperBase.prototype.DeleteFromAEL = function (e)
  3223. {
  3224. var AelPrev = e.PrevInAEL;
  3225. var AelNext = e.NextInAEL;
  3226. if (AelPrev === null && AelNext === null && e !== this.m_ActiveEdges)
  3227. {
  3228. return;
  3229. } //already deleted
  3230. if (AelPrev !== null)
  3231. {
  3232. AelPrev.NextInAEL = AelNext;
  3233. }
  3234. else
  3235. {
  3236. this.m_ActiveEdges = AelNext;
  3237. }
  3238. if (AelNext !== null)
  3239. {
  3240. AelNext.PrevInAEL = AelPrev;
  3241. }
  3242. e.NextInAEL = null;
  3243. e.PrevInAEL = null;
  3244. }
  3245. // public Clipper(int InitOptions = 0)
  3246. /**
  3247. * @suppress {missingProperties}
  3248. */
  3249. ClipperLib.Clipper = function (InitOptions)
  3250. {
  3251. if (typeof (InitOptions) === "undefined") InitOptions = 0;
  3252. this.m_PolyOuts = null;
  3253. this.m_ClipType = ClipperLib.ClipType.ctIntersection;
  3254. this.m_Scanbeam = null;
  3255. this.m_Maxima = null;
  3256. this.m_ActiveEdges = null;
  3257. this.m_SortedEdges = null;
  3258. this.m_IntersectList = null;
  3259. this.m_IntersectNodeComparer = null;
  3260. this.m_ExecuteLocked = false;
  3261. this.m_ClipFillType = ClipperLib.PolyFillType.pftEvenOdd;
  3262. this.m_SubjFillType = ClipperLib.PolyFillType.pftEvenOdd;
  3263. this.m_Joins = null;
  3264. this.m_GhostJoins = null;
  3265. this.m_UsingPolyTree = false;
  3266. this.ReverseSolution = false;
  3267. this.StrictlySimple = false;
  3268. ClipperLib.ClipperBase.call(this);
  3269. this.m_Scanbeam = null;
  3270. this.m_Maxima = null;
  3271. this.m_ActiveEdges = null;
  3272. this.m_SortedEdges = null;
  3273. this.m_IntersectList = new Array();
  3274. this.m_IntersectNodeComparer = ClipperLib.MyIntersectNodeSort.Compare;
  3275. this.m_ExecuteLocked = false;
  3276. this.m_UsingPolyTree = false;
  3277. this.m_PolyOuts = new Array();
  3278. this.m_Joins = new Array();
  3279. this.m_GhostJoins = new Array();
  3280. this.ReverseSolution = (1 & InitOptions) !== 0;
  3281. this.StrictlySimple = (2 & InitOptions) !== 0;
  3282. this.PreserveCollinear = (4 & InitOptions) !== 0;
  3283. if (ClipperLib.use_xyz)
  3284. {
  3285. this.ZFillFunction = null; // function (IntPoint vert1, IntPoint vert2, ref IntPoint intersectPt);
  3286. }
  3287. };
  3288. ClipperLib.Clipper.ioReverseSolution = 1;
  3289. ClipperLib.Clipper.ioStrictlySimple = 2;
  3290. ClipperLib.Clipper.ioPreserveCollinear = 4;
  3291. ClipperLib.Clipper.prototype.Clear = function ()
  3292. {
  3293. if (this.m_edges.length === 0)
  3294. return;
  3295. //avoids problems with ClipperBase destructor
  3296. this.DisposeAllPolyPts();
  3297. ClipperLib.ClipperBase.prototype.Clear.call(this);
  3298. };
  3299. ClipperLib.Clipper.prototype.InsertMaxima = function (X)
  3300. {
  3301. //double-linked list: sorted ascending, ignoring dups.
  3302. var newMax = new ClipperLib.Maxima();
  3303. newMax.X = X;
  3304. if (this.m_Maxima === null)
  3305. {
  3306. this.m_Maxima = newMax;
  3307. this.m_Maxima.Next = null;
  3308. this.m_Maxima.Prev = null;
  3309. }
  3310. else if (X < this.m_Maxima.X)
  3311. {
  3312. newMax.Next = this.m_Maxima;
  3313. newMax.Prev = null;
  3314. this.m_Maxima = newMax;
  3315. }
  3316. else
  3317. {
  3318. var m = this.m_Maxima;
  3319. while (m.Next !== null && X >= m.Next.X)
  3320. {
  3321. m = m.Next;
  3322. }
  3323. if (X === m.X)
  3324. {
  3325. return;
  3326. } //ie ignores duplicates (& CG to clean up newMax)
  3327. //insert newMax between m and m.Next ...
  3328. newMax.Next = m.Next;
  3329. newMax.Prev = m;
  3330. if (m.Next !== null)
  3331. {
  3332. m.Next.Prev = newMax;
  3333. }
  3334. m.Next = newMax;
  3335. }
  3336. };
  3337. // ************************************
  3338. ClipperLib.Clipper.prototype.Execute = function ()
  3339. {
  3340. var a = arguments,
  3341. alen = a.length,
  3342. ispolytree = a[1] instanceof ClipperLib.PolyTree;
  3343. if (alen === 4 && !ispolytree) // function (clipType, solution, subjFillType, clipFillType)
  3344. {
  3345. var clipType = a[0],
  3346. solution = a[1],
  3347. subjFillType = a[2],
  3348. clipFillType = a[3];
  3349. if (this.m_ExecuteLocked)
  3350. return false;
  3351. if (this.m_HasOpenPaths)
  3352. ClipperLib.Error("Error: PolyTree struct is needed for open path clipping.");
  3353. this.m_ExecuteLocked = true;
  3354. ClipperLib.Clear(solution);
  3355. this.m_SubjFillType = subjFillType;
  3356. this.m_ClipFillType = clipFillType;
  3357. this.m_ClipType = clipType;
  3358. this.m_UsingPolyTree = false;
  3359. try
  3360. {
  3361. var succeeded = this.ExecuteInternal();
  3362. //build the return polygons ...
  3363. if (succeeded) this.BuildResult(solution);
  3364. }
  3365. finally
  3366. {
  3367. this.DisposeAllPolyPts();
  3368. this.m_ExecuteLocked = false;
  3369. }
  3370. return succeeded;
  3371. }
  3372. else if (alen === 4 && ispolytree) // function (clipType, polytree, subjFillType, clipFillType)
  3373. {
  3374. var clipType = a[0],
  3375. polytree = a[1],
  3376. subjFillType = a[2],
  3377. clipFillType = a[3];
  3378. if (this.m_ExecuteLocked)
  3379. return false;
  3380. this.m_ExecuteLocked = true;
  3381. this.m_SubjFillType = subjFillType;
  3382. this.m_ClipFillType = clipFillType;
  3383. this.m_ClipType = clipType;
  3384. this.m_UsingPolyTree = true;
  3385. try
  3386. {
  3387. var succeeded = this.ExecuteInternal();
  3388. //build the return polygons ...
  3389. if (succeeded) this.BuildResult2(polytree);
  3390. }
  3391. finally
  3392. {
  3393. this.DisposeAllPolyPts();
  3394. this.m_ExecuteLocked = false;
  3395. }
  3396. return succeeded;
  3397. }
  3398. else if (alen === 2 && !ispolytree) // function (clipType, solution)
  3399. {
  3400. var clipType = a[0],
  3401. solution = a[1];
  3402. return this.Execute(clipType, solution, ClipperLib.PolyFillType.pftEvenOdd, ClipperLib.PolyFillType.pftEvenOdd);
  3403. }
  3404. else if (alen === 2 && ispolytree) // function (clipType, polytree)
  3405. {
  3406. var clipType = a[0],
  3407. polytree = a[1];
  3408. return this.Execute(clipType, polytree, ClipperLib.PolyFillType.pftEvenOdd, ClipperLib.PolyFillType.pftEvenOdd);
  3409. }
  3410. };
  3411. ClipperLib.Clipper.prototype.FixHoleLinkage = function (outRec)
  3412. {
  3413. //skip if an outermost polygon or
  3414. //already already points to the correct FirstLeft ...
  3415. if (outRec.FirstLeft === null || (outRec.IsHole !== outRec.FirstLeft.IsHole && outRec.FirstLeft.Pts !== null))
  3416. return;
  3417. var orfl = outRec.FirstLeft;
  3418. while (orfl !== null && ((orfl.IsHole === outRec.IsHole) || orfl.Pts === null))
  3419. orfl = orfl.FirstLeft;
  3420. outRec.FirstLeft = orfl;
  3421. };
  3422. ClipperLib.Clipper.prototype.ExecuteInternal = function ()
  3423. {
  3424. try
  3425. {
  3426. this.Reset();
  3427. this.m_SortedEdges = null;
  3428. this.m_Maxima = null;
  3429. var botY = {},
  3430. topY = {};
  3431. if (!this.PopScanbeam(botY))
  3432. {
  3433. return false;
  3434. }
  3435. this.InsertLocalMinimaIntoAEL(botY.v);
  3436. while (this.PopScanbeam(topY) || this.LocalMinimaPending())
  3437. {
  3438. this.ProcessHorizontals();
  3439. this.m_GhostJoins.length = 0;
  3440. if (!this.ProcessIntersections(topY.v))
  3441. {
  3442. return false;
  3443. }
  3444. this.ProcessEdgesAtTopOfScanbeam(topY.v);
  3445. botY.v = topY.v;
  3446. this.InsertLocalMinimaIntoAEL(botY.v);
  3447. }
  3448. //fix orientations ...
  3449. var outRec, i, ilen;
  3450. //fix orientations ...
  3451. for (i = 0, ilen = this.m_PolyOuts.length; i < ilen; i++)
  3452. {
  3453. outRec = this.m_PolyOuts[i];
  3454. if (outRec.Pts === null || outRec.IsOpen) continue;
  3455. if ((outRec.IsHole ^ this.ReverseSolution) == (this.Area$1(outRec) > 0))
  3456. this.ReversePolyPtLinks(outRec.Pts);
  3457. }
  3458. this.JoinCommonEdges();
  3459. for (i = 0, ilen = this.m_PolyOuts.length; i < ilen; i++)
  3460. {
  3461. outRec = this.m_PolyOuts[i];
  3462. if (outRec.Pts === null)
  3463. continue;
  3464. else if (outRec.IsOpen)
  3465. this.FixupOutPolyline(outRec);
  3466. else
  3467. this.FixupOutPolygon(outRec);
  3468. }
  3469. if (this.StrictlySimple) this.DoSimplePolygons();
  3470. return true;
  3471. }
  3472. //catch { return false; }
  3473. finally
  3474. {
  3475. this.m_Joins.length = 0;
  3476. this.m_GhostJoins.length = 0;
  3477. }
  3478. };
  3479. ClipperLib.Clipper.prototype.DisposeAllPolyPts = function ()
  3480. {
  3481. for (var i = 0, ilen = this.m_PolyOuts.length; i < ilen; ++i)
  3482. this.DisposeOutRec(i);
  3483. ClipperLib.Clear(this.m_PolyOuts);
  3484. };
  3485. ClipperLib.Clipper.prototype.AddJoin = function (Op1, Op2, OffPt)
  3486. {
  3487. var j = new ClipperLib.Join();
  3488. j.OutPt1 = Op1;
  3489. j.OutPt2 = Op2;
  3490. //j.OffPt = OffPt;
  3491. j.OffPt.X = OffPt.X;
  3492. j.OffPt.Y = OffPt.Y;
  3493. if (ClipperLib.use_xyz) j.OffPt.Z = OffPt.Z;
  3494. this.m_Joins.push(j);
  3495. };
  3496. ClipperLib.Clipper.prototype.AddGhostJoin = function (Op, OffPt)
  3497. {
  3498. var j = new ClipperLib.Join();
  3499. j.OutPt1 = Op;
  3500. //j.OffPt = OffPt;
  3501. j.OffPt.X = OffPt.X;
  3502. j.OffPt.Y = OffPt.Y;
  3503. if (ClipperLib.use_xyz) j.OffPt.Z = OffPt.Z;
  3504. this.m_GhostJoins.push(j);
  3505. };
  3506. //if (ClipperLib.use_xyz)
  3507. //{
  3508. ClipperLib.Clipper.prototype.SetZ = function (pt, e1, e2)
  3509. {
  3510. if (this.ZFillFunction !== null)
  3511. {
  3512. if (pt.Z !== 0 || this.ZFillFunction === null) return;
  3513. else if (ClipperLib.IntPoint.op_Equality(pt, e1.Bot)) pt.Z = e1.Bot.Z;
  3514. else if (ClipperLib.IntPoint.op_Equality(pt, e1.Top)) pt.Z = e1.Top.Z;
  3515. else if (ClipperLib.IntPoint.op_Equality(pt, e2.Bot)) pt.Z = e2.Bot.Z;
  3516. else if (ClipperLib.IntPoint.op_Equality(pt, e2.Top)) pt.Z = e2.Top.Z;
  3517. else this.ZFillFunction(e1.Bot, e1.Top, e2.Bot, e2.Top, pt);
  3518. }
  3519. };
  3520. //}
  3521. ClipperLib.Clipper.prototype.InsertLocalMinimaIntoAEL = function (botY)
  3522. {
  3523. var lm = {};
  3524. var lb;
  3525. var rb;
  3526. while (this.PopLocalMinima(botY, lm))
  3527. {
  3528. lb = lm.v.LeftBound;
  3529. rb = lm.v.RightBound;
  3530. var Op1 = null;
  3531. if (lb === null)
  3532. {
  3533. this.InsertEdgeIntoAEL(rb, null);
  3534. this.SetWindingCount(rb);
  3535. if (this.IsContributing(rb))
  3536. Op1 = this.AddOutPt(rb, rb.Bot);
  3537. }
  3538. else if (rb === null)
  3539. {
  3540. this.InsertEdgeIntoAEL(lb, null);
  3541. this.SetWindingCount(lb);
  3542. if (this.IsContributing(lb))
  3543. Op1 = this.AddOutPt(lb, lb.Bot);
  3544. this.InsertScanbeam(lb.Top.Y);
  3545. }
  3546. else
  3547. {
  3548. this.InsertEdgeIntoAEL(lb, null);
  3549. this.InsertEdgeIntoAEL(rb, lb);
  3550. this.SetWindingCount(lb);
  3551. rb.WindCnt = lb.WindCnt;
  3552. rb.WindCnt2 = lb.WindCnt2;
  3553. if (this.IsContributing(lb))
  3554. Op1 = this.AddLocalMinPoly(lb, rb, lb.Bot);
  3555. this.InsertScanbeam(lb.Top.Y);
  3556. }
  3557. if (rb !== null)
  3558. {
  3559. if (ClipperLib.ClipperBase.IsHorizontal(rb))
  3560. {
  3561. if (rb.NextInLML !== null)
  3562. {
  3563. this.InsertScanbeam(rb.NextInLML.Top.Y);
  3564. }
  3565. this.AddEdgeToSEL(rb);
  3566. }
  3567. else
  3568. {
  3569. this.InsertScanbeam(rb.Top.Y);
  3570. }
  3571. }
  3572. if (lb === null || rb === null) continue;
  3573. //if output polygons share an Edge with a horizontal rb, they'll need joining later ...
  3574. if (Op1 !== null && ClipperLib.ClipperBase.IsHorizontal(rb) && this.m_GhostJoins.length > 0 && rb.WindDelta !== 0)
  3575. {
  3576. for (var i = 0, ilen = this.m_GhostJoins.length; i < ilen; i++)
  3577. {
  3578. //if the horizontal Rb and a 'ghost' horizontal overlap, then convert
  3579. //the 'ghost' join to a real join ready for later ...
  3580. var j = this.m_GhostJoins[i];
  3581. if (this.HorzSegmentsOverlap(j.OutPt1.Pt.X, j.OffPt.X, rb.Bot.X, rb.Top.X))
  3582. this.AddJoin(j.OutPt1, Op1, j.OffPt);
  3583. }
  3584. }
  3585. if (lb.OutIdx >= 0 && lb.PrevInAEL !== null &&
  3586. lb.PrevInAEL.Curr.X === lb.Bot.X &&
  3587. lb.PrevInAEL.OutIdx >= 0 &&
  3588. ClipperLib.ClipperBase.SlopesEqual5(lb.PrevInAEL.Curr, lb.PrevInAEL.Top, lb.Curr, lb.Top, this.m_UseFullRange) &&
  3589. lb.WindDelta !== 0 && lb.PrevInAEL.WindDelta !== 0)
  3590. {
  3591. var Op2 = this.AddOutPt(lb.PrevInAEL, lb.Bot);
  3592. this.AddJoin(Op1, Op2, lb.Top);
  3593. }
  3594. if (lb.NextInAEL !== rb)
  3595. {
  3596. if (rb.OutIdx >= 0 && rb.PrevInAEL.OutIdx >= 0 &&
  3597. ClipperLib.ClipperBase.SlopesEqual5(rb.PrevInAEL.Curr, rb.PrevInAEL.Top, rb.Curr, rb.Top, this.m_UseFullRange) &&
  3598. rb.WindDelta !== 0 && rb.PrevInAEL.WindDelta !== 0)
  3599. {
  3600. var Op2 = this.AddOutPt(rb.PrevInAEL, rb.Bot);
  3601. this.AddJoin(Op1, Op2, rb.Top);
  3602. }
  3603. var e = lb.NextInAEL;
  3604. if (e !== null)
  3605. while (e !== rb)
  3606. {
  3607. //nb: For calculating winding counts etc, IntersectEdges() assumes
  3608. //that param1 will be to the right of param2 ABOVE the intersection ...
  3609. this.IntersectEdges(rb, e, lb.Curr);
  3610. //order important here
  3611. e = e.NextInAEL;
  3612. }
  3613. }
  3614. }
  3615. };
  3616. ClipperLib.Clipper.prototype.InsertEdgeIntoAEL = function (edge, startEdge)
  3617. {
  3618. if (this.m_ActiveEdges === null)
  3619. {
  3620. edge.PrevInAEL = null;
  3621. edge.NextInAEL = null;
  3622. this.m_ActiveEdges = edge;
  3623. }
  3624. else if (startEdge === null && this.E2InsertsBeforeE1(this.m_ActiveEdges, edge))
  3625. {
  3626. edge.PrevInAEL = null;
  3627. edge.NextInAEL = this.m_ActiveEdges;
  3628. this.m_ActiveEdges.PrevInAEL = edge;
  3629. this.m_ActiveEdges = edge;
  3630. }
  3631. else
  3632. {
  3633. if (startEdge === null)
  3634. startEdge = this.m_ActiveEdges;
  3635. while (startEdge.NextInAEL !== null && !this.E2InsertsBeforeE1(startEdge.NextInAEL, edge))
  3636. startEdge = startEdge.NextInAEL;
  3637. edge.NextInAEL = startEdge.NextInAEL;
  3638. if (startEdge.NextInAEL !== null)
  3639. startEdge.NextInAEL.PrevInAEL = edge;
  3640. edge.PrevInAEL = startEdge;
  3641. startEdge.NextInAEL = edge;
  3642. }
  3643. };
  3644. ClipperLib.Clipper.prototype.E2InsertsBeforeE1 = function (e1, e2)
  3645. {
  3646. if (e2.Curr.X === e1.Curr.X)
  3647. {
  3648. if (e2.Top.Y > e1.Top.Y)
  3649. return e2.Top.X < ClipperLib.Clipper.TopX(e1, e2.Top.Y);
  3650. else
  3651. return e1.Top.X > ClipperLib.Clipper.TopX(e2, e1.Top.Y);
  3652. }
  3653. else
  3654. return e2.Curr.X < e1.Curr.X;
  3655. };
  3656. ClipperLib.Clipper.prototype.IsEvenOddFillType = function (edge)
  3657. {
  3658. if (edge.PolyTyp === ClipperLib.PolyType.ptSubject)
  3659. return this.m_SubjFillType === ClipperLib.PolyFillType.pftEvenOdd;
  3660. else
  3661. return this.m_ClipFillType === ClipperLib.PolyFillType.pftEvenOdd;
  3662. };
  3663. ClipperLib.Clipper.prototype.IsEvenOddAltFillType = function (edge)
  3664. {
  3665. if (edge.PolyTyp === ClipperLib.PolyType.ptSubject)
  3666. return this.m_ClipFillType === ClipperLib.PolyFillType.pftEvenOdd;
  3667. else
  3668. return this.m_SubjFillType === ClipperLib.PolyFillType.pftEvenOdd;
  3669. };
  3670. ClipperLib.Clipper.prototype.IsContributing = function (edge)
  3671. {
  3672. var pft, pft2;
  3673. if (edge.PolyTyp === ClipperLib.PolyType.ptSubject)
  3674. {
  3675. pft = this.m_SubjFillType;
  3676. pft2 = this.m_ClipFillType;
  3677. }
  3678. else
  3679. {
  3680. pft = this.m_ClipFillType;
  3681. pft2 = this.m_SubjFillType;
  3682. }
  3683. switch (pft)
  3684. {
  3685. case ClipperLib.PolyFillType.pftEvenOdd:
  3686. if (edge.WindDelta === 0 && edge.WindCnt !== 1)
  3687. return false;
  3688. break;
  3689. case ClipperLib.PolyFillType.pftNonZero:
  3690. if (Math.abs(edge.WindCnt) !== 1)
  3691. return false;
  3692. break;
  3693. case ClipperLib.PolyFillType.pftPositive:
  3694. if (edge.WindCnt !== 1)
  3695. return false;
  3696. break;
  3697. default:
  3698. if (edge.WindCnt !== -1)
  3699. return false;
  3700. break;
  3701. }
  3702. switch (this.m_ClipType)
  3703. {
  3704. case ClipperLib.ClipType.ctIntersection:
  3705. switch (pft2)
  3706. {
  3707. case ClipperLib.PolyFillType.pftEvenOdd:
  3708. case ClipperLib.PolyFillType.pftNonZero:
  3709. return (edge.WindCnt2 !== 0);
  3710. case ClipperLib.PolyFillType.pftPositive:
  3711. return (edge.WindCnt2 > 0);
  3712. default:
  3713. return (edge.WindCnt2 < 0);
  3714. }
  3715. case ClipperLib.ClipType.ctUnion:
  3716. switch (pft2)
  3717. {
  3718. case ClipperLib.PolyFillType.pftEvenOdd:
  3719. case ClipperLib.PolyFillType.pftNonZero:
  3720. return (edge.WindCnt2 === 0);
  3721. case ClipperLib.PolyFillType.pftPositive:
  3722. return (edge.WindCnt2 <= 0);
  3723. default:
  3724. return (edge.WindCnt2 >= 0);
  3725. }
  3726. case ClipperLib.ClipType.ctDifference:
  3727. if (edge.PolyTyp === ClipperLib.PolyType.ptSubject)
  3728. switch (pft2)
  3729. {
  3730. case ClipperLib.PolyFillType.pftEvenOdd:
  3731. case ClipperLib.PolyFillType.pftNonZero:
  3732. return (edge.WindCnt2 === 0);
  3733. case ClipperLib.PolyFillType.pftPositive:
  3734. return (edge.WindCnt2 <= 0);
  3735. default:
  3736. return (edge.WindCnt2 >= 0);
  3737. }
  3738. else
  3739. switch (pft2)
  3740. {
  3741. case ClipperLib.PolyFillType.pftEvenOdd:
  3742. case ClipperLib.PolyFillType.pftNonZero:
  3743. return (edge.WindCnt2 !== 0);
  3744. case ClipperLib.PolyFillType.pftPositive:
  3745. return (edge.WindCnt2 > 0);
  3746. default:
  3747. return (edge.WindCnt2 < 0);
  3748. }
  3749. case ClipperLib.ClipType.ctXor:
  3750. if (edge.WindDelta === 0)
  3751. switch (pft2)
  3752. {
  3753. case ClipperLib.PolyFillType.pftEvenOdd:
  3754. case ClipperLib.PolyFillType.pftNonZero:
  3755. return (edge.WindCnt2 === 0);
  3756. case ClipperLib.PolyFillType.pftPositive:
  3757. return (edge.WindCnt2 <= 0);
  3758. default:
  3759. return (edge.WindCnt2 >= 0);
  3760. }
  3761. else
  3762. return true;
  3763. }
  3764. return true;
  3765. };
  3766. ClipperLib.Clipper.prototype.SetWindingCount = function (edge)
  3767. {
  3768. var e = edge.PrevInAEL;
  3769. //find the edge of the same polytype that immediately preceeds 'edge' in AEL
  3770. while (e !== null && ((e.PolyTyp !== edge.PolyTyp) || (e.WindDelta === 0)))
  3771. e = e.PrevInAEL;
  3772. if (e === null)
  3773. {
  3774. var pft = (edge.PolyTyp === ClipperLib.PolyType.ptSubject ? this.m_SubjFillType : this.m_ClipFillType);
  3775. if (edge.WindDelta === 0)
  3776. {
  3777. edge.WindCnt = (pft === ClipperLib.PolyFillType.pftNegative ? -1 : 1);
  3778. }
  3779. else
  3780. {
  3781. edge.WindCnt = edge.WindDelta;
  3782. }
  3783. edge.WindCnt2 = 0;
  3784. e = this.m_ActiveEdges;
  3785. //ie get ready to calc WindCnt2
  3786. }
  3787. else if (edge.WindDelta === 0 && this.m_ClipType !== ClipperLib.ClipType.ctUnion)
  3788. {
  3789. edge.WindCnt = 1;
  3790. edge.WindCnt2 = e.WindCnt2;
  3791. e = e.NextInAEL;
  3792. //ie get ready to calc WindCnt2
  3793. }
  3794. else if (this.IsEvenOddFillType(edge))
  3795. {
  3796. //EvenOdd filling ...
  3797. if (edge.WindDelta === 0)
  3798. {
  3799. //are we inside a subj polygon ...
  3800. var Inside = true;
  3801. var e2 = e.PrevInAEL;
  3802. while (e2 !== null)
  3803. {
  3804. if (e2.PolyTyp === e.PolyTyp && e2.WindDelta !== 0)
  3805. Inside = !Inside;
  3806. e2 = e2.PrevInAEL;
  3807. }
  3808. edge.WindCnt = (Inside ? 0 : 1);
  3809. }
  3810. else
  3811. {
  3812. edge.WindCnt = edge.WindDelta;
  3813. }
  3814. edge.WindCnt2 = e.WindCnt2;
  3815. e = e.NextInAEL;
  3816. //ie get ready to calc WindCnt2
  3817. }
  3818. else
  3819. {
  3820. //nonZero, Positive or Negative filling ...
  3821. if (e.WindCnt * e.WindDelta < 0)
  3822. {
  3823. //prev edge is 'decreasing' WindCount (WC) toward zero
  3824. //so we're outside the previous polygon ...
  3825. if (Math.abs(e.WindCnt) > 1)
  3826. {
  3827. //outside prev poly but still inside another.
  3828. //when reversing direction of prev poly use the same WC
  3829. if (e.WindDelta * edge.WindDelta < 0)
  3830. edge.WindCnt = e.WindCnt;
  3831. else
  3832. edge.WindCnt = e.WindCnt + edge.WindDelta;
  3833. }
  3834. else
  3835. edge.WindCnt = (edge.WindDelta === 0 ? 1 : edge.WindDelta);
  3836. }
  3837. else
  3838. {
  3839. //prev edge is 'increasing' WindCount (WC) away from zero
  3840. //so we're inside the previous polygon ...
  3841. if (edge.WindDelta === 0)
  3842. edge.WindCnt = (e.WindCnt < 0 ? e.WindCnt - 1 : e.WindCnt + 1);
  3843. else if (e.WindDelta * edge.WindDelta < 0)
  3844. edge.WindCnt = e.WindCnt;
  3845. else
  3846. edge.WindCnt = e.WindCnt + edge.WindDelta;
  3847. }
  3848. edge.WindCnt2 = e.WindCnt2;
  3849. e = e.NextInAEL;
  3850. //ie get ready to calc WindCnt2
  3851. }
  3852. //update WindCnt2 ...
  3853. if (this.IsEvenOddAltFillType(edge))
  3854. {
  3855. //EvenOdd filling ...
  3856. while (e !== edge)
  3857. {
  3858. if (e.WindDelta !== 0)
  3859. edge.WindCnt2 = (edge.WindCnt2 === 0 ? 1 : 0);
  3860. e = e.NextInAEL;
  3861. }
  3862. }
  3863. else
  3864. {
  3865. //nonZero, Positive or Negative filling ...
  3866. while (e !== edge)
  3867. {
  3868. edge.WindCnt2 += e.WindDelta;
  3869. e = e.NextInAEL;
  3870. }
  3871. }
  3872. };
  3873. ClipperLib.Clipper.prototype.AddEdgeToSEL = function (edge)
  3874. {
  3875. //SEL pointers in PEdge are use to build transient lists of horizontal edges.
  3876. //However, since we don't need to worry about processing order, all additions
  3877. //are made to the front of the list ...
  3878. if (this.m_SortedEdges === null)
  3879. {
  3880. this.m_SortedEdges = edge;
  3881. edge.PrevInSEL = null;
  3882. edge.NextInSEL = null;
  3883. }
  3884. else
  3885. {
  3886. edge.NextInSEL = this.m_SortedEdges;
  3887. edge.PrevInSEL = null;
  3888. this.m_SortedEdges.PrevInSEL = edge;
  3889. this.m_SortedEdges = edge;
  3890. }
  3891. };
  3892. ClipperLib.Clipper.prototype.PopEdgeFromSEL = function (e)
  3893. {
  3894. //Pop edge from front of SEL (ie SEL is a FILO list)
  3895. e.v = this.m_SortedEdges;
  3896. if (e.v === null)
  3897. {
  3898. return false;
  3899. }
  3900. var oldE = e.v;
  3901. this.m_SortedEdges = e.v.NextInSEL;
  3902. if (this.m_SortedEdges !== null)
  3903. {
  3904. this.m_SortedEdges.PrevInSEL = null;
  3905. }
  3906. oldE.NextInSEL = null;
  3907. oldE.PrevInSEL = null;
  3908. return true;
  3909. };
  3910. ClipperLib.Clipper.prototype.CopyAELToSEL = function ()
  3911. {
  3912. var e = this.m_ActiveEdges;
  3913. this.m_SortedEdges = e;
  3914. while (e !== null)
  3915. {
  3916. e.PrevInSEL = e.PrevInAEL;
  3917. e.NextInSEL = e.NextInAEL;
  3918. e = e.NextInAEL;
  3919. }
  3920. };
  3921. ClipperLib.Clipper.prototype.SwapPositionsInSEL = function (edge1, edge2)
  3922. {
  3923. if (edge1.NextInSEL === null && edge1.PrevInSEL === null)
  3924. return;
  3925. if (edge2.NextInSEL === null && edge2.PrevInSEL === null)
  3926. return;
  3927. if (edge1.NextInSEL === edge2)
  3928. {
  3929. var next = edge2.NextInSEL;
  3930. if (next !== null)
  3931. next.PrevInSEL = edge1;
  3932. var prev = edge1.PrevInSEL;
  3933. if (prev !== null)
  3934. prev.NextInSEL = edge2;
  3935. edge2.PrevInSEL = prev;
  3936. edge2.NextInSEL = edge1;
  3937. edge1.PrevInSEL = edge2;
  3938. edge1.NextInSEL = next;
  3939. }
  3940. else if (edge2.NextInSEL === edge1)
  3941. {
  3942. var next = edge1.NextInSEL;
  3943. if (next !== null)
  3944. next.PrevInSEL = edge2;
  3945. var prev = edge2.PrevInSEL;
  3946. if (prev !== null)
  3947. prev.NextInSEL = edge1;
  3948. edge1.PrevInSEL = prev;
  3949. edge1.NextInSEL = edge2;
  3950. edge2.PrevInSEL = edge1;
  3951. edge2.NextInSEL = next;
  3952. }
  3953. else
  3954. {
  3955. var next = edge1.NextInSEL;
  3956. var prev = edge1.PrevInSEL;
  3957. edge1.NextInSEL = edge2.NextInSEL;
  3958. if (edge1.NextInSEL !== null)
  3959. edge1.NextInSEL.PrevInSEL = edge1;
  3960. edge1.PrevInSEL = edge2.PrevInSEL;
  3961. if (edge1.PrevInSEL !== null)
  3962. edge1.PrevInSEL.NextInSEL = edge1;
  3963. edge2.NextInSEL = next;
  3964. if (edge2.NextInSEL !== null)
  3965. edge2.NextInSEL.PrevInSEL = edge2;
  3966. edge2.PrevInSEL = prev;
  3967. if (edge2.PrevInSEL !== null)
  3968. edge2.PrevInSEL.NextInSEL = edge2;
  3969. }
  3970. if (edge1.PrevInSEL === null)
  3971. this.m_SortedEdges = edge1;
  3972. else if (edge2.PrevInSEL === null)
  3973. this.m_SortedEdges = edge2;
  3974. };
  3975. ClipperLib.Clipper.prototype.AddLocalMaxPoly = function (e1, e2, pt)
  3976. {
  3977. this.AddOutPt(e1, pt);
  3978. if (e2.WindDelta === 0) this.AddOutPt(e2, pt);
  3979. if (e1.OutIdx === e2.OutIdx)
  3980. {
  3981. e1.OutIdx = -1;
  3982. e2.OutIdx = -1;
  3983. }
  3984. else if (e1.OutIdx < e2.OutIdx)
  3985. this.AppendPolygon(e1, e2);
  3986. else
  3987. this.AppendPolygon(e2, e1);
  3988. };
  3989. ClipperLib.Clipper.prototype.AddLocalMinPoly = function (e1, e2, pt)
  3990. {
  3991. var result;
  3992. var e, prevE;
  3993. if (ClipperLib.ClipperBase.IsHorizontal(e2) || (e1.Dx > e2.Dx))
  3994. {
  3995. result = this.AddOutPt(e1, pt);
  3996. e2.OutIdx = e1.OutIdx;
  3997. e1.Side = ClipperLib.EdgeSide.esLeft;
  3998. e2.Side = ClipperLib.EdgeSide.esRight;
  3999. e = e1;
  4000. if (e.PrevInAEL === e2)
  4001. prevE = e2.PrevInAEL;
  4002. else
  4003. prevE = e.PrevInAEL;
  4004. }
  4005. else
  4006. {
  4007. result = this.AddOutPt(e2, pt);
  4008. e1.OutIdx = e2.OutIdx;
  4009. e1.Side = ClipperLib.EdgeSide.esRight;
  4010. e2.Side = ClipperLib.EdgeSide.esLeft;
  4011. e = e2;
  4012. if (e.PrevInAEL === e1)
  4013. prevE = e1.PrevInAEL;
  4014. else
  4015. prevE = e.PrevInAEL;
  4016. }
  4017. if (prevE !== null && prevE.OutIdx >= 0 && prevE.Top.Y < pt.Y && e.Top.Y < pt.Y)
  4018. {
  4019. var xPrev = ClipperLib.Clipper.TopX(prevE, pt.Y);
  4020. var xE = ClipperLib.Clipper.TopX(e, pt.Y);
  4021. if ((xPrev === xE) && (e.WindDelta !== 0) && (prevE.WindDelta !== 0) && ClipperLib.ClipperBase.SlopesEqual5(new ClipperLib.IntPoint2(xPrev, pt.Y), prevE.Top, new ClipperLib.IntPoint2(xE, pt.Y), e.Top, this.m_UseFullRange))
  4022. {
  4023. var outPt = this.AddOutPt(prevE, pt);
  4024. this.AddJoin(result, outPt, e.Top);
  4025. }
  4026. }
  4027. return result;
  4028. };
  4029. ClipperLib.Clipper.prototype.AddOutPt = function (e, pt)
  4030. {
  4031. if (e.OutIdx < 0)
  4032. {
  4033. var outRec = this.CreateOutRec();
  4034. outRec.IsOpen = (e.WindDelta === 0);
  4035. var newOp = new ClipperLib.OutPt();
  4036. outRec.Pts = newOp;
  4037. newOp.Idx = outRec.Idx;
  4038. //newOp.Pt = pt;
  4039. newOp.Pt.X = pt.X;
  4040. newOp.Pt.Y = pt.Y;
  4041. if (ClipperLib.use_xyz) newOp.Pt.Z = pt.Z;
  4042. newOp.Next = newOp;
  4043. newOp.Prev = newOp;
  4044. if (!outRec.IsOpen)
  4045. this.SetHoleState(e, outRec);
  4046. e.OutIdx = outRec.Idx;
  4047. //nb: do this after SetZ !
  4048. return newOp;
  4049. }
  4050. else
  4051. {
  4052. var outRec = this.m_PolyOuts[e.OutIdx];
  4053. //OutRec.Pts is the 'Left-most' point & OutRec.Pts.Prev is the 'Right-most'
  4054. var op = outRec.Pts;
  4055. var ToFront = (e.Side === ClipperLib.EdgeSide.esLeft);
  4056. if (ToFront && ClipperLib.IntPoint.op_Equality(pt, op.Pt))
  4057. return op;
  4058. else if (!ToFront && ClipperLib.IntPoint.op_Equality(pt, op.Prev.Pt))
  4059. return op.Prev;
  4060. var newOp = new ClipperLib.OutPt();
  4061. newOp.Idx = outRec.Idx;
  4062. //newOp.Pt = pt;
  4063. newOp.Pt.X = pt.X;
  4064. newOp.Pt.Y = pt.Y;
  4065. if (ClipperLib.use_xyz) newOp.Pt.Z = pt.Z;
  4066. newOp.Next = op;
  4067. newOp.Prev = op.Prev;
  4068. newOp.Prev.Next = newOp;
  4069. op.Prev = newOp;
  4070. if (ToFront)
  4071. outRec.Pts = newOp;
  4072. return newOp;
  4073. }
  4074. };
  4075. ClipperLib.Clipper.prototype.GetLastOutPt = function (e)
  4076. {
  4077. var outRec = this.m_PolyOuts[e.OutIdx];
  4078. if (e.Side === ClipperLib.EdgeSide.esLeft)
  4079. {
  4080. return outRec.Pts;
  4081. }
  4082. else
  4083. {
  4084. return outRec.Pts.Prev;
  4085. }
  4086. };
  4087. ClipperLib.Clipper.prototype.SwapPoints = function (pt1, pt2)
  4088. {
  4089. var tmp = new ClipperLib.IntPoint1(pt1.Value);
  4090. //pt1.Value = pt2.Value;
  4091. pt1.Value.X = pt2.Value.X;
  4092. pt1.Value.Y = pt2.Value.Y;
  4093. if (ClipperLib.use_xyz) pt1.Value.Z = pt2.Value.Z;
  4094. //pt2.Value = tmp;
  4095. pt2.Value.X = tmp.X;
  4096. pt2.Value.Y = tmp.Y;
  4097. if (ClipperLib.use_xyz) pt2.Value.Z = tmp.Z;
  4098. };
  4099. ClipperLib.Clipper.prototype.HorzSegmentsOverlap = function (seg1a, seg1b, seg2a, seg2b)
  4100. {
  4101. var tmp;
  4102. if (seg1a > seg1b)
  4103. {
  4104. tmp = seg1a;
  4105. seg1a = seg1b;
  4106. seg1b = tmp;
  4107. }
  4108. if (seg2a > seg2b)
  4109. {
  4110. tmp = seg2a;
  4111. seg2a = seg2b;
  4112. seg2b = tmp;
  4113. }
  4114. return (seg1a < seg2b) && (seg2a < seg1b);
  4115. }
  4116. ClipperLib.Clipper.prototype.SetHoleState = function (e, outRec)
  4117. {
  4118. var e2 = e.PrevInAEL;
  4119. var eTmp = null;
  4120. while (e2 !== null)
  4121. {
  4122. if (e2.OutIdx >= 0 && e2.WindDelta !== 0)
  4123. {
  4124. if (eTmp === null)
  4125. eTmp = e2;
  4126. else if (eTmp.OutIdx === e2.OutIdx)
  4127. eTmp = null; //paired
  4128. }
  4129. e2 = e2.PrevInAEL;
  4130. }
  4131. if (eTmp === null)
  4132. {
  4133. outRec.FirstLeft = null;
  4134. outRec.IsHole = false;
  4135. }
  4136. else
  4137. {
  4138. outRec.FirstLeft = this.m_PolyOuts[eTmp.OutIdx];
  4139. outRec.IsHole = !outRec.FirstLeft.IsHole;
  4140. }
  4141. };
  4142. ClipperLib.Clipper.prototype.GetDx = function (pt1, pt2)
  4143. {
  4144. if (pt1.Y === pt2.Y)
  4145. return ClipperLib.ClipperBase.horizontal;
  4146. else
  4147. return (pt2.X - pt1.X) / (pt2.Y - pt1.Y);
  4148. };
  4149. ClipperLib.Clipper.prototype.FirstIsBottomPt = function (btmPt1, btmPt2)
  4150. {
  4151. var p = btmPt1.Prev;
  4152. while ((ClipperLib.IntPoint.op_Equality(p.Pt, btmPt1.Pt)) && (p !== btmPt1))
  4153. p = p.Prev;
  4154. var dx1p = Math.abs(this.GetDx(btmPt1.Pt, p.Pt));
  4155. p = btmPt1.Next;
  4156. while ((ClipperLib.IntPoint.op_Equality(p.Pt, btmPt1.Pt)) && (p !== btmPt1))
  4157. p = p.Next;
  4158. var dx1n = Math.abs(this.GetDx(btmPt1.Pt, p.Pt));
  4159. p = btmPt2.Prev;
  4160. while ((ClipperLib.IntPoint.op_Equality(p.Pt, btmPt2.Pt)) && (p !== btmPt2))
  4161. p = p.Prev;
  4162. var dx2p = Math.abs(this.GetDx(btmPt2.Pt, p.Pt));
  4163. p = btmPt2.Next;
  4164. while ((ClipperLib.IntPoint.op_Equality(p.Pt, btmPt2.Pt)) && (p !== btmPt2))
  4165. p = p.Next;
  4166. var dx2n = Math.abs(this.GetDx(btmPt2.Pt, p.Pt));
  4167. if (Math.max(dx1p, dx1n) === Math.max(dx2p, dx2n) && Math.min(dx1p, dx1n) === Math.min(dx2p, dx2n))
  4168. {
  4169. return this.Area(btmPt1) > 0; //if otherwise identical use orientation
  4170. }
  4171. else
  4172. {
  4173. return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n);
  4174. }
  4175. };
  4176. ClipperLib.Clipper.prototype.GetBottomPt = function (pp)
  4177. {
  4178. var dups = null;
  4179. var p = pp.Next;
  4180. while (p !== pp)
  4181. {
  4182. if (p.Pt.Y > pp.Pt.Y)
  4183. {
  4184. pp = p;
  4185. dups = null;
  4186. }
  4187. else if (p.Pt.Y === pp.Pt.Y && p.Pt.X <= pp.Pt.X)
  4188. {
  4189. if (p.Pt.X < pp.Pt.X)
  4190. {
  4191. dups = null;
  4192. pp = p;
  4193. }
  4194. else
  4195. {
  4196. if (p.Next !== pp && p.Prev !== pp)
  4197. dups = p;
  4198. }
  4199. }
  4200. p = p.Next;
  4201. }
  4202. if (dups !== null)
  4203. {
  4204. //there appears to be at least 2 vertices at bottomPt so ...
  4205. while (dups !== p)
  4206. {
  4207. if (!this.FirstIsBottomPt(p, dups))
  4208. pp = dups;
  4209. dups = dups.Next;
  4210. while (ClipperLib.IntPoint.op_Inequality(dups.Pt, pp.Pt))
  4211. dups = dups.Next;
  4212. }
  4213. }
  4214. return pp;
  4215. };
  4216. ClipperLib.Clipper.prototype.GetLowermostRec = function (outRec1, outRec2)
  4217. {
  4218. //work out which polygon fragment has the correct hole state ...
  4219. if (outRec1.BottomPt === null)
  4220. outRec1.BottomPt = this.GetBottomPt(outRec1.Pts);
  4221. if (outRec2.BottomPt === null)
  4222. outRec2.BottomPt = this.GetBottomPt(outRec2.Pts);
  4223. var bPt1 = outRec1.BottomPt;
  4224. var bPt2 = outRec2.BottomPt;
  4225. if (bPt1.Pt.Y > bPt2.Pt.Y)
  4226. return outRec1;
  4227. else if (bPt1.Pt.Y < bPt2.Pt.Y)
  4228. return outRec2;
  4229. else if (bPt1.Pt.X < bPt2.Pt.X)
  4230. return outRec1;
  4231. else if (bPt1.Pt.X > bPt2.Pt.X)
  4232. return outRec2;
  4233. else if (bPt1.Next === bPt1)
  4234. return outRec2;
  4235. else if (bPt2.Next === bPt2)
  4236. return outRec1;
  4237. else if (this.FirstIsBottomPt(bPt1, bPt2))
  4238. return outRec1;
  4239. else
  4240. return outRec2;
  4241. };
  4242. ClipperLib.Clipper.prototype.OutRec1RightOfOutRec2 = function (outRec1, outRec2)
  4243. {
  4244. do {
  4245. outRec1 = outRec1.FirstLeft;
  4246. if (outRec1 === outRec2)
  4247. return true;
  4248. }
  4249. while (outRec1 !== null)
  4250. return false;
  4251. };
  4252. ClipperLib.Clipper.prototype.GetOutRec = function (idx)
  4253. {
  4254. var outrec = this.m_PolyOuts[idx];
  4255. while (outrec !== this.m_PolyOuts[outrec.Idx])
  4256. outrec = this.m_PolyOuts[outrec.Idx];
  4257. return outrec;
  4258. };
  4259. ClipperLib.Clipper.prototype.AppendPolygon = function (e1, e2)
  4260. {
  4261. //get the start and ends of both output polygons ...
  4262. var outRec1 = this.m_PolyOuts[e1.OutIdx];
  4263. var outRec2 = this.m_PolyOuts[e2.OutIdx];
  4264. var holeStateRec;
  4265. if (this.OutRec1RightOfOutRec2(outRec1, outRec2))
  4266. holeStateRec = outRec2;
  4267. else if (this.OutRec1RightOfOutRec2(outRec2, outRec1))
  4268. holeStateRec = outRec1;
  4269. else
  4270. holeStateRec = this.GetLowermostRec(outRec1, outRec2);
  4271. //get the start and ends of both output polygons and
  4272. //join E2 poly onto E1 poly and delete pointers to E2 ...
  4273. var p1_lft = outRec1.Pts;
  4274. var p1_rt = p1_lft.Prev;
  4275. var p2_lft = outRec2.Pts;
  4276. var p2_rt = p2_lft.Prev;
  4277. //join e2 poly onto e1 poly and delete pointers to e2 ...
  4278. if (e1.Side === ClipperLib.EdgeSide.esLeft)
  4279. {
  4280. if (e2.Side === ClipperLib.EdgeSide.esLeft)
  4281. {
  4282. //z y x a b c
  4283. this.ReversePolyPtLinks(p2_lft);
  4284. p2_lft.Next = p1_lft;
  4285. p1_lft.Prev = p2_lft;
  4286. p1_rt.Next = p2_rt;
  4287. p2_rt.Prev = p1_rt;
  4288. outRec1.Pts = p2_rt;
  4289. }
  4290. else
  4291. {
  4292. //x y z a b c
  4293. p2_rt.Next = p1_lft;
  4294. p1_lft.Prev = p2_rt;
  4295. p2_lft.Prev = p1_rt;
  4296. p1_rt.Next = p2_lft;
  4297. outRec1.Pts = p2_lft;
  4298. }
  4299. }
  4300. else
  4301. {
  4302. if (e2.Side === ClipperLib.EdgeSide.esRight)
  4303. {
  4304. //a b c z y x
  4305. this.ReversePolyPtLinks(p2_lft);
  4306. p1_rt.Next = p2_rt;
  4307. p2_rt.Prev = p1_rt;
  4308. p2_lft.Next = p1_lft;
  4309. p1_lft.Prev = p2_lft;
  4310. }
  4311. else
  4312. {
  4313. //a b c x y z
  4314. p1_rt.Next = p2_lft;
  4315. p2_lft.Prev = p1_rt;
  4316. p1_lft.Prev = p2_rt;
  4317. p2_rt.Next = p1_lft;
  4318. }
  4319. }
  4320. outRec1.BottomPt = null;
  4321. if (holeStateRec === outRec2)
  4322. {
  4323. if (outRec2.FirstLeft !== outRec1)
  4324. outRec1.FirstLeft = outRec2.FirstLeft;
  4325. outRec1.IsHole = outRec2.IsHole;
  4326. }
  4327. outRec2.Pts = null;
  4328. outRec2.BottomPt = null;
  4329. outRec2.FirstLeft = outRec1;
  4330. var OKIdx = e1.OutIdx;
  4331. var ObsoleteIdx = e2.OutIdx;
  4332. e1.OutIdx = -1;
  4333. //nb: safe because we only get here via AddLocalMaxPoly
  4334. e2.OutIdx = -1;
  4335. var e = this.m_ActiveEdges;
  4336. while (e !== null)
  4337. {
  4338. if (e.OutIdx === ObsoleteIdx)
  4339. {
  4340. e.OutIdx = OKIdx;
  4341. e.Side = e1.Side;
  4342. break;
  4343. }
  4344. e = e.NextInAEL;
  4345. }
  4346. outRec2.Idx = outRec1.Idx;
  4347. };
  4348. ClipperLib.Clipper.prototype.ReversePolyPtLinks = function (pp)
  4349. {
  4350. if (pp === null)
  4351. return;
  4352. var pp1;
  4353. var pp2;
  4354. pp1 = pp;
  4355. do {
  4356. pp2 = pp1.Next;
  4357. pp1.Next = pp1.Prev;
  4358. pp1.Prev = pp2;
  4359. pp1 = pp2;
  4360. }
  4361. while (pp1 !== pp)
  4362. };
  4363. ClipperLib.Clipper.SwapSides = function (edge1, edge2)
  4364. {
  4365. var side = edge1.Side;
  4366. edge1.Side = edge2.Side;
  4367. edge2.Side = side;
  4368. };
  4369. ClipperLib.Clipper.SwapPolyIndexes = function (edge1, edge2)
  4370. {
  4371. var outIdx = edge1.OutIdx;
  4372. edge1.OutIdx = edge2.OutIdx;
  4373. edge2.OutIdx = outIdx;
  4374. };
  4375. ClipperLib.Clipper.prototype.IntersectEdges = function (e1, e2, pt)
  4376. {
  4377. //e1 will be to the left of e2 BELOW the intersection. Therefore e1 is before
  4378. //e2 in AEL except when e1 is being inserted at the intersection point ...
  4379. var e1Contributing = (e1.OutIdx >= 0);
  4380. var e2Contributing = (e2.OutIdx >= 0);
  4381. if (ClipperLib.use_xyz)
  4382. this.SetZ(pt, e1, e2);
  4383. if (ClipperLib.use_lines)
  4384. {
  4385. //if either edge is on an OPEN path ...
  4386. if (e1.WindDelta === 0 || e2.WindDelta === 0)
  4387. {
  4388. //ignore subject-subject open path intersections UNLESS they
  4389. //are both open paths, AND they are both 'contributing maximas' ...
  4390. if (e1.WindDelta === 0 && e2.WindDelta === 0) return;
  4391. //if intersecting a subj line with a subj poly ...
  4392. else if (e1.PolyTyp === e2.PolyTyp &&
  4393. e1.WindDelta !== e2.WindDelta && this.m_ClipType === ClipperLib.ClipType.ctUnion)
  4394. {
  4395. if (e1.WindDelta === 0)
  4396. {
  4397. if (e2Contributing)
  4398. {
  4399. this.AddOutPt(e1, pt);
  4400. if (e1Contributing)
  4401. e1.OutIdx = -1;
  4402. }
  4403. }
  4404. else
  4405. {
  4406. if (e1Contributing)
  4407. {
  4408. this.AddOutPt(e2, pt);
  4409. if (e2Contributing)
  4410. e2.OutIdx = -1;
  4411. }
  4412. }
  4413. }
  4414. else if (e1.PolyTyp !== e2.PolyTyp)
  4415. {
  4416. if ((e1.WindDelta === 0) && Math.abs(e2.WindCnt) === 1 &&
  4417. (this.m_ClipType !== ClipperLib.ClipType.ctUnion || e2.WindCnt2 === 0))
  4418. {
  4419. this.AddOutPt(e1, pt);
  4420. if (e1Contributing)
  4421. e1.OutIdx = -1;
  4422. }
  4423. else if ((e2.WindDelta === 0) && (Math.abs(e1.WindCnt) === 1) &&
  4424. (this.m_ClipType !== ClipperLib.ClipType.ctUnion || e1.WindCnt2 === 0))
  4425. {
  4426. this.AddOutPt(e2, pt);
  4427. if (e2Contributing)
  4428. e2.OutIdx = -1;
  4429. }
  4430. }
  4431. return;
  4432. }
  4433. }
  4434. //update winding counts...
  4435. //assumes that e1 will be to the Right of e2 ABOVE the intersection
  4436. if (e1.PolyTyp === e2.PolyTyp)
  4437. {
  4438. if (this.IsEvenOddFillType(e1))
  4439. {
  4440. var oldE1WindCnt = e1.WindCnt;
  4441. e1.WindCnt = e2.WindCnt;
  4442. e2.WindCnt = oldE1WindCnt;
  4443. }
  4444. else
  4445. {
  4446. if (e1.WindCnt + e2.WindDelta === 0)
  4447. e1.WindCnt = -e1.WindCnt;
  4448. else
  4449. e1.WindCnt += e2.WindDelta;
  4450. if (e2.WindCnt - e1.WindDelta === 0)
  4451. e2.WindCnt = -e2.WindCnt;
  4452. else
  4453. e2.WindCnt -= e1.WindDelta;
  4454. }
  4455. }
  4456. else
  4457. {
  4458. if (!this.IsEvenOddFillType(e2))
  4459. e1.WindCnt2 += e2.WindDelta;
  4460. else
  4461. e1.WindCnt2 = (e1.WindCnt2 === 0) ? 1 : 0;
  4462. if (!this.IsEvenOddFillType(e1))
  4463. e2.WindCnt2 -= e1.WindDelta;
  4464. else
  4465. e2.WindCnt2 = (e2.WindCnt2 === 0) ? 1 : 0;
  4466. }
  4467. var e1FillType, e2FillType, e1FillType2, e2FillType2;
  4468. if (e1.PolyTyp === ClipperLib.PolyType.ptSubject)
  4469. {
  4470. e1FillType = this.m_SubjFillType;
  4471. e1FillType2 = this.m_ClipFillType;
  4472. }
  4473. else
  4474. {
  4475. e1FillType = this.m_ClipFillType;
  4476. e1FillType2 = this.m_SubjFillType;
  4477. }
  4478. if (e2.PolyTyp === ClipperLib.PolyType.ptSubject)
  4479. {
  4480. e2FillType = this.m_SubjFillType;
  4481. e2FillType2 = this.m_ClipFillType;
  4482. }
  4483. else
  4484. {
  4485. e2FillType = this.m_ClipFillType;
  4486. e2FillType2 = this.m_SubjFillType;
  4487. }
  4488. var e1Wc, e2Wc;
  4489. switch (e1FillType)
  4490. {
  4491. case ClipperLib.PolyFillType.pftPositive:
  4492. e1Wc = e1.WindCnt;
  4493. break;
  4494. case ClipperLib.PolyFillType.pftNegative:
  4495. e1Wc = -e1.WindCnt;
  4496. break;
  4497. default:
  4498. e1Wc = Math.abs(e1.WindCnt);
  4499. break;
  4500. }
  4501. switch (e2FillType)
  4502. {
  4503. case ClipperLib.PolyFillType.pftPositive:
  4504. e2Wc = e2.WindCnt;
  4505. break;
  4506. case ClipperLib.PolyFillType.pftNegative:
  4507. e2Wc = -e2.WindCnt;
  4508. break;
  4509. default:
  4510. e2Wc = Math.abs(e2.WindCnt);
  4511. break;
  4512. }
  4513. if (e1Contributing && e2Contributing)
  4514. {
  4515. if ((e1Wc !== 0 && e1Wc !== 1) || (e2Wc !== 0 && e2Wc !== 1) ||
  4516. (e1.PolyTyp !== e2.PolyTyp && this.m_ClipType !== ClipperLib.ClipType.ctXor))
  4517. {
  4518. this.AddLocalMaxPoly(e1, e2, pt);
  4519. }
  4520. else
  4521. {
  4522. this.AddOutPt(e1, pt);
  4523. this.AddOutPt(e2, pt);
  4524. ClipperLib.Clipper.SwapSides(e1, e2);
  4525. ClipperLib.Clipper.SwapPolyIndexes(e1, e2);
  4526. }
  4527. }
  4528. else if (e1Contributing)
  4529. {
  4530. if (e2Wc === 0 || e2Wc === 1)
  4531. {
  4532. this.AddOutPt(e1, pt);
  4533. ClipperLib.Clipper.SwapSides(e1, e2);
  4534. ClipperLib.Clipper.SwapPolyIndexes(e1, e2);
  4535. }
  4536. }
  4537. else if (e2Contributing)
  4538. {
  4539. if (e1Wc === 0 || e1Wc === 1)
  4540. {
  4541. this.AddOutPt(e2, pt);
  4542. ClipperLib.Clipper.SwapSides(e1, e2);
  4543. ClipperLib.Clipper.SwapPolyIndexes(e1, e2);
  4544. }
  4545. }
  4546. else if ((e1Wc === 0 || e1Wc === 1) && (e2Wc === 0 || e2Wc === 1))
  4547. {
  4548. //neither edge is currently contributing ...
  4549. var e1Wc2, e2Wc2;
  4550. switch (e1FillType2)
  4551. {
  4552. case ClipperLib.PolyFillType.pftPositive:
  4553. e1Wc2 = e1.WindCnt2;
  4554. break;
  4555. case ClipperLib.PolyFillType.pftNegative:
  4556. e1Wc2 = -e1.WindCnt2;
  4557. break;
  4558. default:
  4559. e1Wc2 = Math.abs(e1.WindCnt2);
  4560. break;
  4561. }
  4562. switch (e2FillType2)
  4563. {
  4564. case ClipperLib.PolyFillType.pftPositive:
  4565. e2Wc2 = e2.WindCnt2;
  4566. break;
  4567. case ClipperLib.PolyFillType.pftNegative:
  4568. e2Wc2 = -e2.WindCnt2;
  4569. break;
  4570. default:
  4571. e2Wc2 = Math.abs(e2.WindCnt2);
  4572. break;
  4573. }
  4574. if (e1.PolyTyp !== e2.PolyTyp)
  4575. {
  4576. this.AddLocalMinPoly(e1, e2, pt);
  4577. }
  4578. else if (e1Wc === 1 && e2Wc === 1)
  4579. switch (this.m_ClipType)
  4580. {
  4581. case ClipperLib.ClipType.ctIntersection:
  4582. if (e1Wc2 > 0 && e2Wc2 > 0)
  4583. this.AddLocalMinPoly(e1, e2, pt);
  4584. break;
  4585. case ClipperLib.ClipType.ctUnion:
  4586. if (e1Wc2 <= 0 && e2Wc2 <= 0)
  4587. this.AddLocalMinPoly(e1, e2, pt);
  4588. break;
  4589. case ClipperLib.ClipType.ctDifference:
  4590. if (((e1.PolyTyp === ClipperLib.PolyType.ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) ||
  4591. ((e1.PolyTyp === ClipperLib.PolyType.ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0)))
  4592. this.AddLocalMinPoly(e1, e2, pt);
  4593. break;
  4594. case ClipperLib.ClipType.ctXor:
  4595. this.AddLocalMinPoly(e1, e2, pt);
  4596. break;
  4597. }
  4598. else
  4599. ClipperLib.Clipper.SwapSides(e1, e2);
  4600. }
  4601. };
  4602. ClipperLib.Clipper.prototype.DeleteFromSEL = function (e)
  4603. {
  4604. var SelPrev = e.PrevInSEL;
  4605. var SelNext = e.NextInSEL;
  4606. if (SelPrev === null && SelNext === null && (e !== this.m_SortedEdges))
  4607. return;
  4608. //already deleted
  4609. if (SelPrev !== null)
  4610. SelPrev.NextInSEL = SelNext;
  4611. else
  4612. this.m_SortedEdges = SelNext;
  4613. if (SelNext !== null)
  4614. SelNext.PrevInSEL = SelPrev;
  4615. e.NextInSEL = null;
  4616. e.PrevInSEL = null;
  4617. };
  4618. ClipperLib.Clipper.prototype.ProcessHorizontals = function ()
  4619. {
  4620. var horzEdge = {}; //m_SortedEdges;
  4621. while (this.PopEdgeFromSEL(horzEdge))
  4622. {
  4623. this.ProcessHorizontal(horzEdge.v);
  4624. }
  4625. };
  4626. ClipperLib.Clipper.prototype.GetHorzDirection = function (HorzEdge, $var)
  4627. {
  4628. if (HorzEdge.Bot.X < HorzEdge.Top.X)
  4629. {
  4630. $var.Left = HorzEdge.Bot.X;
  4631. $var.Right = HorzEdge.Top.X;
  4632. $var.Dir = ClipperLib.Direction.dLeftToRight;
  4633. }
  4634. else
  4635. {
  4636. $var.Left = HorzEdge.Top.X;
  4637. $var.Right = HorzEdge.Bot.X;
  4638. $var.Dir = ClipperLib.Direction.dRightToLeft;
  4639. }
  4640. };
  4641. ClipperLib.Clipper.prototype.ProcessHorizontal = function (horzEdge)
  4642. {
  4643. var $var = {
  4644. Dir: null,
  4645. Left: null,
  4646. Right: null
  4647. };
  4648. this.GetHorzDirection(horzEdge, $var);
  4649. var dir = $var.Dir;
  4650. var horzLeft = $var.Left;
  4651. var horzRight = $var.Right;
  4652. var IsOpen = horzEdge.WindDelta === 0;
  4653. var eLastHorz = horzEdge,
  4654. eMaxPair = null;
  4655. while (eLastHorz.NextInLML !== null && ClipperLib.ClipperBase.IsHorizontal(eLastHorz.NextInLML))
  4656. eLastHorz = eLastHorz.NextInLML;
  4657. if (eLastHorz.NextInLML === null)
  4658. eMaxPair = this.GetMaximaPair(eLastHorz);
  4659. var currMax = this.m_Maxima;
  4660. if (currMax !== null)
  4661. {
  4662. //get the first maxima in range (X) ...
  4663. if (dir === ClipperLib.Direction.dLeftToRight)
  4664. {
  4665. while (currMax !== null && currMax.X <= horzEdge.Bot.X)
  4666. {
  4667. currMax = currMax.Next;
  4668. }
  4669. if (currMax !== null && currMax.X >= eLastHorz.Top.X)
  4670. {
  4671. currMax = null;
  4672. }
  4673. }
  4674. else
  4675. {
  4676. while (currMax.Next !== null && currMax.Next.X < horzEdge.Bot.X)
  4677. {
  4678. currMax = currMax.Next;
  4679. }
  4680. if (currMax.X <= eLastHorz.Top.X)
  4681. {
  4682. currMax = null;
  4683. }
  4684. }
  4685. }
  4686. var op1 = null;
  4687. for (;;) //loop through consec. horizontal edges
  4688. {
  4689. var IsLastHorz = (horzEdge === eLastHorz);
  4690. var e = this.GetNextInAEL(horzEdge, dir);
  4691. while (e !== null)
  4692. {
  4693. //this code block inserts extra coords into horizontal edges (in output
  4694. //polygons) whereever maxima touch these horizontal edges. This helps
  4695. //'simplifying' polygons (ie if the Simplify property is set).
  4696. if (currMax !== null)
  4697. {
  4698. if (dir === ClipperLib.Direction.dLeftToRight)
  4699. {
  4700. while (currMax !== null && currMax.X < e.Curr.X)
  4701. {
  4702. if (horzEdge.OutIdx >= 0 && !IsOpen)
  4703. {
  4704. this.AddOutPt(horzEdge, new ClipperLib.IntPoint2(currMax.X, horzEdge.Bot.Y));
  4705. }
  4706. currMax = currMax.Next;
  4707. }
  4708. }
  4709. else
  4710. {
  4711. while (currMax !== null && currMax.X > e.Curr.X)
  4712. {
  4713. if (horzEdge.OutIdx >= 0 && !IsOpen)
  4714. {
  4715. this.AddOutPt(horzEdge, new ClipperLib.IntPoint2(currMax.X, horzEdge.Bot.Y));
  4716. }
  4717. currMax = currMax.Prev;
  4718. }
  4719. }
  4720. }
  4721. if ((dir === ClipperLib.Direction.dLeftToRight && e.Curr.X > horzRight) || (dir === ClipperLib.Direction.dRightToLeft && e.Curr.X < horzLeft))
  4722. {
  4723. break;
  4724. }
  4725. //Also break if we've got to the end of an intermediate horizontal edge ...
  4726. //nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal.
  4727. if (e.Curr.X === horzEdge.Top.X && horzEdge.NextInLML !== null && e.Dx < horzEdge.NextInLML.Dx)
  4728. break;
  4729. if (horzEdge.OutIdx >= 0 && !IsOpen) //note: may be done multiple times
  4730. {
  4731. if (ClipperLib.use_xyz)
  4732. {
  4733. if (dir === ClipperLib.Direction.dLeftToRight)
  4734. this.SetZ(e.Curr, horzEdge, e);
  4735. else this.SetZ(e.Curr, e, horzEdge);
  4736. }
  4737. op1 = this.AddOutPt(horzEdge, e.Curr);
  4738. var eNextHorz = this.m_SortedEdges;
  4739. while (eNextHorz !== null)
  4740. {
  4741. if (eNextHorz.OutIdx >= 0 && this.HorzSegmentsOverlap(horzEdge.Bot.X, horzEdge.Top.X, eNextHorz.Bot.X, eNextHorz.Top.X))
  4742. {
  4743. var op2 = this.GetLastOutPt(eNextHorz);
  4744. this.AddJoin(op2, op1, eNextHorz.Top);
  4745. }
  4746. eNextHorz = eNextHorz.NextInSEL;
  4747. }
  4748. this.AddGhostJoin(op1, horzEdge.Bot);
  4749. }
  4750. //OK, so far we're still in range of the horizontal Edge but make sure
  4751. //we're at the last of consec. horizontals when matching with eMaxPair
  4752. if (e === eMaxPair && IsLastHorz)
  4753. {
  4754. if (horzEdge.OutIdx >= 0)
  4755. {
  4756. this.AddLocalMaxPoly(horzEdge, eMaxPair, horzEdge.Top);
  4757. }
  4758. this.DeleteFromAEL(horzEdge);
  4759. this.DeleteFromAEL(eMaxPair);
  4760. return;
  4761. }
  4762. if (dir === ClipperLib.Direction.dLeftToRight)
  4763. {
  4764. var Pt = new ClipperLib.IntPoint2(e.Curr.X, horzEdge.Curr.Y);
  4765. this.IntersectEdges(horzEdge, e, Pt);
  4766. }
  4767. else
  4768. {
  4769. var Pt = new ClipperLib.IntPoint2(e.Curr.X, horzEdge.Curr.Y);
  4770. this.IntersectEdges(e, horzEdge, Pt);
  4771. }
  4772. var eNext = this.GetNextInAEL(e, dir);
  4773. this.SwapPositionsInAEL(horzEdge, e);
  4774. e = eNext;
  4775. } //end while(e !== null)
  4776. //Break out of loop if HorzEdge.NextInLML is not also horizontal ...
  4777. if (horzEdge.NextInLML === null || !ClipperLib.ClipperBase.IsHorizontal(horzEdge.NextInLML))
  4778. {
  4779. break;
  4780. }
  4781. horzEdge = this.UpdateEdgeIntoAEL(horzEdge);
  4782. if (horzEdge.OutIdx >= 0)
  4783. {
  4784. this.AddOutPt(horzEdge, horzEdge.Bot);
  4785. }
  4786. $var = {
  4787. Dir: dir,
  4788. Left: horzLeft,
  4789. Right: horzRight
  4790. };
  4791. this.GetHorzDirection(horzEdge, $var);
  4792. dir = $var.Dir;
  4793. horzLeft = $var.Left;
  4794. horzRight = $var.Right;
  4795. } //end for (;;)
  4796. if (horzEdge.OutIdx >= 0 && op1 === null)
  4797. {
  4798. op1 = this.GetLastOutPt(horzEdge);
  4799. var eNextHorz = this.m_SortedEdges;
  4800. while (eNextHorz !== null)
  4801. {
  4802. if (eNextHorz.OutIdx >= 0 && this.HorzSegmentsOverlap(horzEdge.Bot.X, horzEdge.Top.X, eNextHorz.Bot.X, eNextHorz.Top.X))
  4803. {
  4804. var op2 = this.GetLastOutPt(eNextHorz);
  4805. this.AddJoin(op2, op1, eNextHorz.Top);
  4806. }
  4807. eNextHorz = eNextHorz.NextInSEL;
  4808. }
  4809. this.AddGhostJoin(op1, horzEdge.Top);
  4810. }
  4811. if (horzEdge.NextInLML !== null)
  4812. {
  4813. if (horzEdge.OutIdx >= 0)
  4814. {
  4815. op1 = this.AddOutPt(horzEdge, horzEdge.Top);
  4816. horzEdge = this.UpdateEdgeIntoAEL(horzEdge);
  4817. if (horzEdge.WindDelta === 0)
  4818. {
  4819. return;
  4820. }
  4821. //nb: HorzEdge is no longer horizontal here
  4822. var ePrev = horzEdge.PrevInAEL;
  4823. var eNext = horzEdge.NextInAEL;
  4824. if (ePrev !== null && ePrev.Curr.X === horzEdge.Bot.X && ePrev.Curr.Y === horzEdge.Bot.Y && ePrev.WindDelta === 0 && (ePrev.OutIdx >= 0 && ePrev.Curr.Y > ePrev.Top.Y && ClipperLib.ClipperBase.SlopesEqual3(horzEdge, ePrev, this.m_UseFullRange)))
  4825. {
  4826. var op2 = this.AddOutPt(ePrev, horzEdge.Bot);
  4827. this.AddJoin(op1, op2, horzEdge.Top);
  4828. }
  4829. else if (eNext !== null && eNext.Curr.X === horzEdge.Bot.X && eNext.Curr.Y === horzEdge.Bot.Y && eNext.WindDelta !== 0 && eNext.OutIdx >= 0 && eNext.Curr.Y > eNext.Top.Y && ClipperLib.ClipperBase.SlopesEqual3(horzEdge, eNext, this.m_UseFullRange))
  4830. {
  4831. var op2 = this.AddOutPt(eNext, horzEdge.Bot);
  4832. this.AddJoin(op1, op2, horzEdge.Top);
  4833. }
  4834. }
  4835. else
  4836. {
  4837. horzEdge = this.UpdateEdgeIntoAEL(horzEdge);
  4838. }
  4839. }
  4840. else
  4841. {
  4842. if (horzEdge.OutIdx >= 0)
  4843. {
  4844. this.AddOutPt(horzEdge, horzEdge.Top);
  4845. }
  4846. this.DeleteFromAEL(horzEdge);
  4847. }
  4848. };
  4849. ClipperLib.Clipper.prototype.GetNextInAEL = function (e, Direction)
  4850. {
  4851. return Direction === ClipperLib.Direction.dLeftToRight ? e.NextInAEL : e.PrevInAEL;
  4852. };
  4853. ClipperLib.Clipper.prototype.IsMinima = function (e)
  4854. {
  4855. return e !== null && (e.Prev.NextInLML !== e) && (e.Next.NextInLML !== e);
  4856. };
  4857. ClipperLib.Clipper.prototype.IsMaxima = function (e, Y)
  4858. {
  4859. return (e !== null && e.Top.Y === Y && e.NextInLML === null);
  4860. };
  4861. ClipperLib.Clipper.prototype.IsIntermediate = function (e, Y)
  4862. {
  4863. return (e.Top.Y === Y && e.NextInLML !== null);
  4864. };
  4865. ClipperLib.Clipper.prototype.GetMaximaPair = function (e)
  4866. {
  4867. if ((ClipperLib.IntPoint.op_Equality(e.Next.Top, e.Top)) && e.Next.NextInLML === null)
  4868. {
  4869. return e.Next;
  4870. }
  4871. else
  4872. {
  4873. if ((ClipperLib.IntPoint.op_Equality(e.Prev.Top, e.Top)) && e.Prev.NextInLML === null)
  4874. {
  4875. return e.Prev;
  4876. }
  4877. else
  4878. {
  4879. return null;
  4880. }
  4881. }
  4882. };
  4883. ClipperLib.Clipper.prototype.GetMaximaPairEx = function (e)
  4884. {
  4885. //as above but returns null if MaxPair isn't in AEL (unless it's horizontal)
  4886. var result = this.GetMaximaPair(e);
  4887. if (result === null || result.OutIdx === ClipperLib.ClipperBase.Skip ||
  4888. ((result.NextInAEL === result.PrevInAEL) && !ClipperLib.ClipperBase.IsHorizontal(result)))
  4889. {
  4890. return null;
  4891. }
  4892. return result;
  4893. };
  4894. ClipperLib.Clipper.prototype.ProcessIntersections = function (topY)
  4895. {
  4896. if (this.m_ActiveEdges === null)
  4897. return true;
  4898. try
  4899. {
  4900. this.BuildIntersectList(topY);
  4901. if (this.m_IntersectList.length === 0)
  4902. return true;
  4903. if (this.m_IntersectList.length === 1 || this.FixupIntersectionOrder())
  4904. this.ProcessIntersectList();
  4905. else
  4906. return false;
  4907. }
  4908. catch ($$e2)
  4909. {
  4910. this.m_SortedEdges = null;
  4911. this.m_IntersectList.length = 0;
  4912. ClipperLib.Error("ProcessIntersections error");
  4913. }
  4914. this.m_SortedEdges = null;
  4915. return true;
  4916. };
  4917. ClipperLib.Clipper.prototype.BuildIntersectList = function (topY)
  4918. {
  4919. if (this.m_ActiveEdges === null)
  4920. return;
  4921. //prepare for sorting ...
  4922. var e = this.m_ActiveEdges;
  4923. //console.log(JSON.stringify(JSON.decycle( e )));
  4924. this.m_SortedEdges = e;
  4925. while (e !== null)
  4926. {
  4927. e.PrevInSEL = e.PrevInAEL;
  4928. e.NextInSEL = e.NextInAEL;
  4929. e.Curr.X = ClipperLib.Clipper.TopX(e, topY);
  4930. e = e.NextInAEL;
  4931. }
  4932. //bubblesort ...
  4933. var isModified = true;
  4934. while (isModified && this.m_SortedEdges !== null)
  4935. {
  4936. isModified = false;
  4937. e = this.m_SortedEdges;
  4938. while (e.NextInSEL !== null)
  4939. {
  4940. var eNext = e.NextInSEL;
  4941. var pt = new ClipperLib.IntPoint0();
  4942. //console.log("e.Curr.X: " + e.Curr.X + " eNext.Curr.X" + eNext.Curr.X);
  4943. if (e.Curr.X > eNext.Curr.X)
  4944. {
  4945. this.IntersectPoint(e, eNext, pt);
  4946. if (pt.Y < topY)
  4947. {
  4948. pt = new ClipperLib.IntPoint2(ClipperLib.Clipper.TopX(e, topY), topY);
  4949. }
  4950. var newNode = new ClipperLib.IntersectNode();
  4951. newNode.Edge1 = e;
  4952. newNode.Edge2 = eNext;
  4953. //newNode.Pt = pt;
  4954. newNode.Pt.X = pt.X;
  4955. newNode.Pt.Y = pt.Y;
  4956. if (ClipperLib.use_xyz) newNode.Pt.Z = pt.Z;
  4957. this.m_IntersectList.push(newNode);
  4958. this.SwapPositionsInSEL(e, eNext);
  4959. isModified = true;
  4960. }
  4961. else
  4962. e = eNext;
  4963. }
  4964. if (e.PrevInSEL !== null)
  4965. e.PrevInSEL.NextInSEL = null;
  4966. else
  4967. break;
  4968. }
  4969. this.m_SortedEdges = null;
  4970. };
  4971. ClipperLib.Clipper.prototype.EdgesAdjacent = function (inode)
  4972. {
  4973. return (inode.Edge1.NextInSEL === inode.Edge2) || (inode.Edge1.PrevInSEL === inode.Edge2);
  4974. };
  4975. ClipperLib.Clipper.IntersectNodeSort = function (node1, node2)
  4976. {
  4977. //the following typecast is safe because the differences in Pt.Y will
  4978. //be limited to the height of the scanbeam.
  4979. return (node2.Pt.Y - node1.Pt.Y);
  4980. };
  4981. ClipperLib.Clipper.prototype.FixupIntersectionOrder = function ()
  4982. {
  4983. //pre-condition: intersections are sorted bottom-most first.
  4984. //Now it's crucial that intersections are made only between adjacent edges,
  4985. //so to ensure this the order of intersections may need adjusting ...
  4986. this.m_IntersectList.sort(this.m_IntersectNodeComparer);
  4987. this.CopyAELToSEL();
  4988. var cnt = this.m_IntersectList.length;
  4989. for (var i = 0; i < cnt; i++)
  4990. {
  4991. if (!this.EdgesAdjacent(this.m_IntersectList[i]))
  4992. {
  4993. var j = i + 1;
  4994. while (j < cnt && !this.EdgesAdjacent(this.m_IntersectList[j]))
  4995. j++;
  4996. if (j === cnt)
  4997. return false;
  4998. var tmp = this.m_IntersectList[i];
  4999. this.m_IntersectList[i] = this.m_IntersectList[j];
  5000. this.m_IntersectList[j] = tmp;
  5001. }
  5002. this.SwapPositionsInSEL(this.m_IntersectList[i].Edge1, this.m_IntersectList[i].Edge2);
  5003. }
  5004. return true;
  5005. };
  5006. ClipperLib.Clipper.prototype.ProcessIntersectList = function ()
  5007. {
  5008. for (var i = 0, ilen = this.m_IntersectList.length; i < ilen; i++)
  5009. {
  5010. var iNode = this.m_IntersectList[i];
  5011. this.IntersectEdges(iNode.Edge1, iNode.Edge2, iNode.Pt);
  5012. this.SwapPositionsInAEL(iNode.Edge1, iNode.Edge2);
  5013. }
  5014. this.m_IntersectList.length = 0;
  5015. };
  5016. /*
  5017. --------------------------------
  5018. Round speedtest: http://jsperf.com/fastest-round
  5019. --------------------------------
  5020. */
  5021. var R1 = function (a)
  5022. {
  5023. return a < 0 ? Math.ceil(a - 0.5) : Math.round(a)
  5024. };
  5025. var R2 = function (a)
  5026. {
  5027. return a < 0 ? Math.ceil(a - 0.5) : Math.floor(a + 0.5)
  5028. };
  5029. var R3 = function (a)
  5030. {
  5031. return a < 0 ? -Math.round(Math.abs(a)) : Math.round(a)
  5032. };
  5033. var R4 = function (a)
  5034. {
  5035. if (a < 0)
  5036. {
  5037. a -= 0.5;
  5038. return a < -2147483648 ? Math.ceil(a) : a | 0;
  5039. }
  5040. else
  5041. {
  5042. a += 0.5;
  5043. return a > 2147483647 ? Math.floor(a) : a | 0;
  5044. }
  5045. };
  5046. if (browser.msie) ClipperLib.Clipper.Round = R1;
  5047. else if (browser.chromium) ClipperLib.Clipper.Round = R3;
  5048. else if (browser.safari) ClipperLib.Clipper.Round = R4;
  5049. else ClipperLib.Clipper.Round = R2; // eg. browser.chrome || browser.firefox || browser.opera
  5050. ClipperLib.Clipper.TopX = function (edge, currentY)
  5051. {
  5052. //if (edge.Bot == edge.Curr) alert ("edge.Bot = edge.Curr");
  5053. //if (edge.Bot == edge.Top) alert ("edge.Bot = edge.Top");
  5054. if (currentY === edge.Top.Y)
  5055. return edge.Top.X;
  5056. return edge.Bot.X + ClipperLib.Clipper.Round(edge.Dx * (currentY - edge.Bot.Y));
  5057. };
  5058. ClipperLib.Clipper.prototype.IntersectPoint = function (edge1, edge2, ip)
  5059. {
  5060. ip.X = 0;
  5061. ip.Y = 0;
  5062. var b1, b2;
  5063. //nb: with very large coordinate values, it's possible for SlopesEqual() to
  5064. //return false but for the edge.Dx value be equal due to double precision rounding.
  5065. if (edge1.Dx === edge2.Dx)
  5066. {
  5067. ip.Y = edge1.Curr.Y;
  5068. ip.X = ClipperLib.Clipper.TopX(edge1, ip.Y);
  5069. return;
  5070. }
  5071. if (edge1.Delta.X === 0)
  5072. {
  5073. ip.X = edge1.Bot.X;
  5074. if (ClipperLib.ClipperBase.IsHorizontal(edge2))
  5075. {
  5076. ip.Y = edge2.Bot.Y;
  5077. }
  5078. else
  5079. {
  5080. b2 = edge2.Bot.Y - (edge2.Bot.X / edge2.Dx);
  5081. ip.Y = ClipperLib.Clipper.Round(ip.X / edge2.Dx + b2);
  5082. }
  5083. }
  5084. else if (edge2.Delta.X === 0)
  5085. {
  5086. ip.X = edge2.Bot.X;
  5087. if (ClipperLib.ClipperBase.IsHorizontal(edge1))
  5088. {
  5089. ip.Y = edge1.Bot.Y;
  5090. }
  5091. else
  5092. {
  5093. b1 = edge1.Bot.Y - (edge1.Bot.X / edge1.Dx);
  5094. ip.Y = ClipperLib.Clipper.Round(ip.X / edge1.Dx + b1);
  5095. }
  5096. }
  5097. else
  5098. {
  5099. b1 = edge1.Bot.X - edge1.Bot.Y * edge1.Dx;
  5100. b2 = edge2.Bot.X - edge2.Bot.Y * edge2.Dx;
  5101. var q = (b2 - b1) / (edge1.Dx - edge2.Dx);
  5102. ip.Y = ClipperLib.Clipper.Round(q);
  5103. if (Math.abs(edge1.Dx) < Math.abs(edge2.Dx))
  5104. ip.X = ClipperLib.Clipper.Round(edge1.Dx * q + b1);
  5105. else
  5106. ip.X = ClipperLib.Clipper.Round(edge2.Dx * q + b2);
  5107. }
  5108. if (ip.Y < edge1.Top.Y || ip.Y < edge2.Top.Y)
  5109. {
  5110. if (edge1.Top.Y > edge2.Top.Y)
  5111. {
  5112. ip.Y = edge1.Top.Y;
  5113. ip.X = ClipperLib.Clipper.TopX(edge2, edge1.Top.Y);
  5114. return ip.X < edge1.Top.X;
  5115. }
  5116. else
  5117. ip.Y = edge2.Top.Y;
  5118. if (Math.abs(edge1.Dx) < Math.abs(edge2.Dx))
  5119. ip.X = ClipperLib.Clipper.TopX(edge1, ip.Y);
  5120. else
  5121. ip.X = ClipperLib.Clipper.TopX(edge2, ip.Y);
  5122. }
  5123. //finally, don't allow 'ip' to be BELOW curr.Y (ie bottom of scanbeam) ...
  5124. if (ip.Y > edge1.Curr.Y)
  5125. {
  5126. ip.Y = edge1.Curr.Y;
  5127. //better to use the more vertical edge to derive X ...
  5128. if (Math.abs(edge1.Dx) > Math.abs(edge2.Dx))
  5129. ip.X = ClipperLib.Clipper.TopX(edge2, ip.Y);
  5130. else
  5131. ip.X = ClipperLib.Clipper.TopX(edge1, ip.Y);
  5132. }
  5133. };
  5134. ClipperLib.Clipper.prototype.ProcessEdgesAtTopOfScanbeam = function (topY)
  5135. {
  5136. var e = this.m_ActiveEdges;
  5137. while (e !== null)
  5138. {
  5139. //1. process maxima, treating them as if they're 'bent' horizontal edges,
  5140. // but exclude maxima with horizontal edges. nb: e can't be a horizontal.
  5141. var IsMaximaEdge = this.IsMaxima(e, topY);
  5142. if (IsMaximaEdge)
  5143. {
  5144. var eMaxPair = this.GetMaximaPairEx(e);
  5145. IsMaximaEdge = (eMaxPair === null || !ClipperLib.ClipperBase.IsHorizontal(eMaxPair));
  5146. }
  5147. if (IsMaximaEdge)
  5148. {
  5149. if (this.StrictlySimple)
  5150. {
  5151. this.InsertMaxima(e.Top.X);
  5152. }
  5153. var ePrev = e.PrevInAEL;
  5154. this.DoMaxima(e);
  5155. if (ePrev === null)
  5156. e = this.m_ActiveEdges;
  5157. else
  5158. e = ePrev.NextInAEL;
  5159. }
  5160. else
  5161. {
  5162. //2. promote horizontal edges, otherwise update Curr.X and Curr.Y ...
  5163. if (this.IsIntermediate(e, topY) && ClipperLib.ClipperBase.IsHorizontal(e.NextInLML))
  5164. {
  5165. e = this.UpdateEdgeIntoAEL(e);
  5166. if (e.OutIdx >= 0)
  5167. this.AddOutPt(e, e.Bot);
  5168. this.AddEdgeToSEL(e);
  5169. }
  5170. else
  5171. {
  5172. e.Curr.X = ClipperLib.Clipper.TopX(e, topY);
  5173. e.Curr.Y = topY;
  5174. }
  5175. if (ClipperLib.use_xyz)
  5176. {
  5177. if (e.Top.Y === topY) e.Curr.Z = e.Top.Z;
  5178. else if (e.Bot.Y === topY) e.Curr.Z = e.Bot.Z;
  5179. else e.Curr.Z = 0;
  5180. }
  5181. //When StrictlySimple and 'e' is being touched by another edge, then
  5182. //make sure both edges have a vertex here ...
  5183. if (this.StrictlySimple)
  5184. {
  5185. var ePrev = e.PrevInAEL;
  5186. if ((e.OutIdx >= 0) && (e.WindDelta !== 0) && ePrev !== null &&
  5187. (ePrev.OutIdx >= 0) && (ePrev.Curr.X === e.Curr.X) &&
  5188. (ePrev.WindDelta !== 0))
  5189. {
  5190. var ip = new ClipperLib.IntPoint1(e.Curr);
  5191. if (ClipperLib.use_xyz)
  5192. {
  5193. this.SetZ(ip, ePrev, e);
  5194. }
  5195. var op = this.AddOutPt(ePrev, ip);
  5196. var op2 = this.AddOutPt(e, ip);
  5197. this.AddJoin(op, op2, ip); //StrictlySimple (type-3) join
  5198. }
  5199. }
  5200. e = e.NextInAEL;
  5201. }
  5202. }
  5203. //3. Process horizontals at the Top of the scanbeam ...
  5204. this.ProcessHorizontals();
  5205. this.m_Maxima = null;
  5206. //4. Promote intermediate vertices ...
  5207. e = this.m_ActiveEdges;
  5208. while (e !== null)
  5209. {
  5210. if (this.IsIntermediate(e, topY))
  5211. {
  5212. var op = null;
  5213. if (e.OutIdx >= 0)
  5214. op = this.AddOutPt(e, e.Top);
  5215. e = this.UpdateEdgeIntoAEL(e);
  5216. //if output polygons share an edge, they'll need joining later ...
  5217. var ePrev = e.PrevInAEL;
  5218. var eNext = e.NextInAEL;
  5219. if (ePrev !== null && ePrev.Curr.X === e.Bot.X && ePrev.Curr.Y === e.Bot.Y && op !== null && ePrev.OutIdx >= 0 && ePrev.Curr.Y === ePrev.Top.Y && ClipperLib.ClipperBase.SlopesEqual5(e.Curr, e.Top, ePrev.Curr, ePrev.Top, this.m_UseFullRange) && (e.WindDelta !== 0) && (ePrev.WindDelta !== 0))
  5220. {
  5221. var op2 = this.AddOutPt(ePrev2, e.Bot);
  5222. this.AddJoin(op, op2, e.Top);
  5223. }
  5224. else if (eNext !== null && eNext.Curr.X === e.Bot.X && eNext.Curr.Y === e.Bot.Y && op !== null && eNext.OutIdx >= 0 && eNext.Curr.Y === eNext.Top.Y && ClipperLib.ClipperBase.SlopesEqual5(e.Curr, e.Top, eNext.Curr, eNext.Top, this.m_UseFullRange) && (e.WindDelta !== 0) && (eNext.WindDelta !== 0))
  5225. {
  5226. var op2 = this.AddOutPt(eNext, e.Bot);
  5227. this.AddJoin(op, op2, e.Top);
  5228. }
  5229. }
  5230. e = e.NextInAEL;
  5231. }
  5232. };
  5233. ClipperLib.Clipper.prototype.DoMaxima = function (e)
  5234. {
  5235. var eMaxPair = this.GetMaximaPairEx(e);
  5236. if (eMaxPair === null)
  5237. {
  5238. if (e.OutIdx >= 0)
  5239. this.AddOutPt(e, e.Top);
  5240. this.DeleteFromAEL(e);
  5241. return;
  5242. }
  5243. var eNext = e.NextInAEL;
  5244. while (eNext !== null && eNext !== eMaxPair)
  5245. {
  5246. this.IntersectEdges(e, eNext, e.Top);
  5247. this.SwapPositionsInAEL(e, eNext);
  5248. eNext = e.NextInAEL;
  5249. }
  5250. if (e.OutIdx === -1 && eMaxPair.OutIdx === -1)
  5251. {
  5252. this.DeleteFromAEL(e);
  5253. this.DeleteFromAEL(eMaxPair);
  5254. }
  5255. else if (e.OutIdx >= 0 && eMaxPair.OutIdx >= 0)
  5256. {
  5257. if (e.OutIdx >= 0) this.AddLocalMaxPoly(e, eMaxPair, e.Top);
  5258. this.DeleteFromAEL(e);
  5259. this.DeleteFromAEL(eMaxPair);
  5260. }
  5261. else if (ClipperLib.use_lines && e.WindDelta === 0)
  5262. {
  5263. if (e.OutIdx >= 0)
  5264. {
  5265. this.AddOutPt(e, e.Top);
  5266. e.OutIdx = ClipperLib.ClipperBase.Unassigned;
  5267. }
  5268. this.DeleteFromAEL(e);
  5269. if (eMaxPair.OutIdx >= 0)
  5270. {
  5271. this.AddOutPt(eMaxPair, e.Top);
  5272. eMaxPair.OutIdx = ClipperLib.ClipperBase.Unassigned;
  5273. }
  5274. this.DeleteFromAEL(eMaxPair);
  5275. }
  5276. else
  5277. ClipperLib.Error("DoMaxima error");
  5278. };
  5279. ClipperLib.Clipper.ReversePaths = function (polys)
  5280. {
  5281. for (var i = 0, len = polys.length; i < len; i++)
  5282. polys[i].reverse();
  5283. };
  5284. ClipperLib.Clipper.Orientation = function (poly)
  5285. {
  5286. return ClipperLib.Clipper.Area(poly) >= 0;
  5287. };
  5288. ClipperLib.Clipper.prototype.PointCount = function (pts)
  5289. {
  5290. if (pts === null)
  5291. return 0;
  5292. var result = 0;
  5293. var p = pts;
  5294. do {
  5295. result++;
  5296. p = p.Next;
  5297. }
  5298. while (p !== pts)
  5299. return result;
  5300. };
  5301. ClipperLib.Clipper.prototype.BuildResult = function (polyg)
  5302. {
  5303. ClipperLib.Clear(polyg);
  5304. for (var i = 0, ilen = this.m_PolyOuts.length; i < ilen; i++)
  5305. {
  5306. var outRec = this.m_PolyOuts[i];
  5307. if (outRec.Pts === null)
  5308. continue;
  5309. var p = outRec.Pts.Prev;
  5310. var cnt = this.PointCount(p);
  5311. if (cnt < 2)
  5312. continue;
  5313. var pg = new Array(cnt);
  5314. for (var j = 0; j < cnt; j++)
  5315. {
  5316. pg[j] = p.Pt;
  5317. p = p.Prev;
  5318. }
  5319. polyg.push(pg);
  5320. }
  5321. };
  5322. ClipperLib.Clipper.prototype.BuildResult2 = function (polytree)
  5323. {
  5324. polytree.Clear();
  5325. //add each output polygon/contour to polytree ...
  5326. //polytree.m_AllPolys.set_Capacity(this.m_PolyOuts.length);
  5327. for (var i = 0, ilen = this.m_PolyOuts.length; i < ilen; i++)
  5328. {
  5329. var outRec = this.m_PolyOuts[i];
  5330. var cnt = this.PointCount(outRec.Pts);
  5331. if ((outRec.IsOpen && cnt < 2) || (!outRec.IsOpen && cnt < 3))
  5332. continue;
  5333. this.FixHoleLinkage(outRec);
  5334. var pn = new ClipperLib.PolyNode();
  5335. polytree.m_AllPolys.push(pn);
  5336. outRec.PolyNode = pn;
  5337. pn.m_polygon.length = cnt;
  5338. var op = outRec.Pts.Prev;
  5339. for (var j = 0; j < cnt; j++)
  5340. {
  5341. pn.m_polygon[j] = op.Pt;
  5342. op = op.Prev;
  5343. }
  5344. }
  5345. //fixup PolyNode links etc ...
  5346. //polytree.m_Childs.set_Capacity(this.m_PolyOuts.length);
  5347. for (var i = 0, ilen = this.m_PolyOuts.length; i < ilen; i++)
  5348. {
  5349. var outRec = this.m_PolyOuts[i];
  5350. if (outRec.PolyNode === null)
  5351. continue;
  5352. else if (outRec.IsOpen)
  5353. {
  5354. outRec.PolyNode.IsOpen = true;
  5355. polytree.AddChild(outRec.PolyNode);
  5356. }
  5357. else if (outRec.FirstLeft !== null && outRec.FirstLeft.PolyNode !== null)
  5358. outRec.FirstLeft.PolyNode.AddChild(outRec.PolyNode);
  5359. else
  5360. polytree.AddChild(outRec.PolyNode);
  5361. }
  5362. };
  5363. ClipperLib.Clipper.prototype.FixupOutPolyline = function (outRec)
  5364. {
  5365. var pp = outRec.Pts;
  5366. var lastPP = pp.Prev;
  5367. while (pp !== lastPP)
  5368. {
  5369. pp = pp.Next;
  5370. if (ClipperLib.IntPoint.op_Equality(pp.Pt, pp.Prev.Pt))
  5371. {
  5372. if (pp === lastPP)
  5373. {
  5374. lastPP = pp.Prev;
  5375. }
  5376. var tmpPP = pp.Prev;
  5377. tmpPP.Next = pp.Next;
  5378. pp.Next.Prev = tmpPP;
  5379. pp = tmpPP;
  5380. }
  5381. }
  5382. if (pp === pp.Prev)
  5383. {
  5384. outRec.Pts = null;
  5385. }
  5386. };
  5387. ClipperLib.Clipper.prototype.FixupOutPolygon = function (outRec)
  5388. {
  5389. //FixupOutPolygon() - removes duplicate points and simplifies consecutive
  5390. //parallel edges by removing the middle vertex.
  5391. var lastOK = null;
  5392. outRec.BottomPt = null;
  5393. var pp = outRec.Pts;
  5394. var preserveCol = this.PreserveCollinear || this.StrictlySimple;
  5395. for (;;)
  5396. {
  5397. if (pp.Prev === pp || pp.Prev === pp.Next)
  5398. {
  5399. outRec.Pts = null;
  5400. return;
  5401. }
  5402. //test for duplicate points and collinear edges ...
  5403. if ((ClipperLib.IntPoint.op_Equality(pp.Pt, pp.Next.Pt)) || (ClipperLib.IntPoint.op_Equality(pp.Pt, pp.Prev.Pt)) || (ClipperLib.ClipperBase.SlopesEqual4(pp.Prev.Pt, pp.Pt, pp.Next.Pt, this.m_UseFullRange) && (!preserveCol || !this.Pt2IsBetweenPt1AndPt3(pp.Prev.Pt, pp.Pt, pp.Next.Pt))))
  5404. {
  5405. lastOK = null;
  5406. pp.Prev.Next = pp.Next;
  5407. pp.Next.Prev = pp.Prev;
  5408. pp = pp.Prev;
  5409. }
  5410. else if (pp === lastOK)
  5411. break;
  5412. else
  5413. {
  5414. if (lastOK === null)
  5415. lastOK = pp;
  5416. pp = pp.Next;
  5417. }
  5418. }
  5419. outRec.Pts = pp;
  5420. };
  5421. ClipperLib.Clipper.prototype.DupOutPt = function (outPt, InsertAfter)
  5422. {
  5423. var result = new ClipperLib.OutPt();
  5424. //result.Pt = outPt.Pt;
  5425. result.Pt.X = outPt.Pt.X;
  5426. result.Pt.Y = outPt.Pt.Y;
  5427. if (ClipperLib.use_xyz) result.Pt.Z = outPt.Pt.Z;
  5428. result.Idx = outPt.Idx;
  5429. if (InsertAfter)
  5430. {
  5431. result.Next = outPt.Next;
  5432. result.Prev = outPt;
  5433. outPt.Next.Prev = result;
  5434. outPt.Next = result;
  5435. }
  5436. else
  5437. {
  5438. result.Prev = outPt.Prev;
  5439. result.Next = outPt;
  5440. outPt.Prev.Next = result;
  5441. outPt.Prev = result;
  5442. }
  5443. return result;
  5444. };
  5445. ClipperLib.Clipper.prototype.GetOverlap = function (a1, a2, b1, b2, $val)
  5446. {
  5447. if (a1 < a2)
  5448. {
  5449. if (b1 < b2)
  5450. {
  5451. $val.Left = Math.max(a1, b1);
  5452. $val.Right = Math.min(a2, b2);
  5453. }
  5454. else
  5455. {
  5456. $val.Left = Math.max(a1, b2);
  5457. $val.Right = Math.min(a2, b1);
  5458. }
  5459. }
  5460. else
  5461. {
  5462. if (b1 < b2)
  5463. {
  5464. $val.Left = Math.max(a2, b1);
  5465. $val.Right = Math.min(a1, b2);
  5466. }
  5467. else
  5468. {
  5469. $val.Left = Math.max(a2, b2);
  5470. $val.Right = Math.min(a1, b1);
  5471. }
  5472. }
  5473. return $val.Left < $val.Right;
  5474. };
  5475. ClipperLib.Clipper.prototype.JoinHorz = function (op1, op1b, op2, op2b, Pt, DiscardLeft)
  5476. {
  5477. var Dir1 = (op1.Pt.X > op1b.Pt.X ? ClipperLib.Direction.dRightToLeft : ClipperLib.Direction.dLeftToRight);
  5478. var Dir2 = (op2.Pt.X > op2b.Pt.X ? ClipperLib.Direction.dRightToLeft : ClipperLib.Direction.dLeftToRight);
  5479. if (Dir1 === Dir2)
  5480. return false;
  5481. //When DiscardLeft, we want Op1b to be on the Left of Op1, otherwise we
  5482. //want Op1b to be on the Right. (And likewise with Op2 and Op2b.)
  5483. //So, to facilitate this while inserting Op1b and Op2b ...
  5484. //when DiscardLeft, make sure we're AT or RIGHT of Pt before adding Op1b,
  5485. //otherwise make sure we're AT or LEFT of Pt. (Likewise with Op2b.)
  5486. if (Dir1 === ClipperLib.Direction.dLeftToRight)
  5487. {
  5488. while (op1.Next.Pt.X <= Pt.X &&
  5489. op1.Next.Pt.X >= op1.Pt.X && op1.Next.Pt.Y === Pt.Y)
  5490. op1 = op1.Next;
  5491. if (DiscardLeft && (op1.Pt.X !== Pt.X))
  5492. op1 = op1.Next;
  5493. op1b = this.DupOutPt(op1, !DiscardLeft);
  5494. if (ClipperLib.IntPoint.op_Inequality(op1b.Pt, Pt))
  5495. {
  5496. op1 = op1b;
  5497. //op1.Pt = Pt;
  5498. op1.Pt.X = Pt.X;
  5499. op1.Pt.Y = Pt.Y;
  5500. if (ClipperLib.use_xyz) op1.Pt.Z = Pt.Z;
  5501. op1b = this.DupOutPt(op1, !DiscardLeft);
  5502. }
  5503. }
  5504. else
  5505. {
  5506. while (op1.Next.Pt.X >= Pt.X &&
  5507. op1.Next.Pt.X <= op1.Pt.X && op1.Next.Pt.Y === Pt.Y)
  5508. op1 = op1.Next;
  5509. if (!DiscardLeft && (op1.Pt.X !== Pt.X))
  5510. op1 = op1.Next;
  5511. op1b = this.DupOutPt(op1, DiscardLeft);
  5512. if (ClipperLib.IntPoint.op_Inequality(op1b.Pt, Pt))
  5513. {
  5514. op1 = op1b;
  5515. //op1.Pt = Pt;
  5516. op1.Pt.X = Pt.X;
  5517. op1.Pt.Y = Pt.Y;
  5518. if (ClipperLib.use_xyz) op1.Pt.Z = Pt.Z;
  5519. op1b = this.DupOutPt(op1, DiscardLeft);
  5520. }
  5521. }
  5522. if (Dir2 === ClipperLib.Direction.dLeftToRight)
  5523. {
  5524. while (op2.Next.Pt.X <= Pt.X &&
  5525. op2.Next.Pt.X >= op2.Pt.X && op2.Next.Pt.Y === Pt.Y)
  5526. op2 = op2.Next;
  5527. if (DiscardLeft && (op2.Pt.X !== Pt.X))
  5528. op2 = op2.Next;
  5529. op2b = this.DupOutPt(op2, !DiscardLeft);
  5530. if (ClipperLib.IntPoint.op_Inequality(op2b.Pt, Pt))
  5531. {
  5532. op2 = op2b;
  5533. //op2.Pt = Pt;
  5534. op2.Pt.X = Pt.X;
  5535. op2.Pt.Y = Pt.Y;
  5536. if (ClipperLib.use_xyz) op2.Pt.Z = Pt.Z;
  5537. op2b = this.DupOutPt(op2, !DiscardLeft);
  5538. }
  5539. }
  5540. else
  5541. {
  5542. while (op2.Next.Pt.X >= Pt.X &&
  5543. op2.Next.Pt.X <= op2.Pt.X && op2.Next.Pt.Y === Pt.Y)
  5544. op2 = op2.Next;
  5545. if (!DiscardLeft && (op2.Pt.X !== Pt.X))
  5546. op2 = op2.Next;
  5547. op2b = this.DupOutPt(op2, DiscardLeft);
  5548. if (ClipperLib.IntPoint.op_Inequality(op2b.Pt, Pt))
  5549. {
  5550. op2 = op2b;
  5551. //op2.Pt = Pt;
  5552. op2.Pt.X = Pt.X;
  5553. op2.Pt.Y = Pt.Y;
  5554. if (ClipperLib.use_xyz) op2.Pt.Z = Pt.Z;
  5555. op2b = this.DupOutPt(op2, DiscardLeft);
  5556. }
  5557. }
  5558. if ((Dir1 === ClipperLib.Direction.dLeftToRight) === DiscardLeft)
  5559. {
  5560. op1.Prev = op2;
  5561. op2.Next = op1;
  5562. op1b.Next = op2b;
  5563. op2b.Prev = op1b;
  5564. }
  5565. else
  5566. {
  5567. op1.Next = op2;
  5568. op2.Prev = op1;
  5569. op1b.Prev = op2b;
  5570. op2b.Next = op1b;
  5571. }
  5572. return true;
  5573. };
  5574. ClipperLib.Clipper.prototype.JoinPoints = function (j, outRec1, outRec2)
  5575. {
  5576. var op1 = j.OutPt1,
  5577. op1b = new ClipperLib.OutPt();
  5578. var op2 = j.OutPt2,
  5579. op2b = new ClipperLib.OutPt();
  5580. //There are 3 kinds of joins for output polygons ...
  5581. //1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are vertices anywhere
  5582. //along (horizontal) collinear edges (& Join.OffPt is on the same horizontal).
  5583. //2. Non-horizontal joins where Join.OutPt1 & Join.OutPt2 are at the same
  5584. //location at the Bottom of the overlapping segment (& Join.OffPt is above).
  5585. //3. StrictlySimple joins where edges touch but are not collinear and where
  5586. //Join.OutPt1, Join.OutPt2 & Join.OffPt all share the same point.
  5587. var isHorizontal = (j.OutPt1.Pt.Y === j.OffPt.Y);
  5588. if (isHorizontal && (ClipperLib.IntPoint.op_Equality(j.OffPt, j.OutPt1.Pt)) && (ClipperLib.IntPoint.op_Equality(j.OffPt, j.OutPt2.Pt)))
  5589. {
  5590. //Strictly Simple join ...
  5591. if (outRec1 !== outRec2) return false;
  5592. op1b = j.OutPt1.Next;
  5593. while (op1b !== op1 && (ClipperLib.IntPoint.op_Equality(op1b.Pt, j.OffPt)))
  5594. op1b = op1b.Next;
  5595. var reverse1 = (op1b.Pt.Y > j.OffPt.Y);
  5596. op2b = j.OutPt2.Next;
  5597. while (op2b !== op2 && (ClipperLib.IntPoint.op_Equality(op2b.Pt, j.OffPt)))
  5598. op2b = op2b.Next;
  5599. var reverse2 = (op2b.Pt.Y > j.OffPt.Y);
  5600. if (reverse1 === reverse2)
  5601. return false;
  5602. if (reverse1)
  5603. {
  5604. op1b = this.DupOutPt(op1, false);
  5605. op2b = this.DupOutPt(op2, true);
  5606. op1.Prev = op2;
  5607. op2.Next = op1;
  5608. op1b.Next = op2b;
  5609. op2b.Prev = op1b;
  5610. j.OutPt1 = op1;
  5611. j.OutPt2 = op1b;
  5612. return true;
  5613. }
  5614. else
  5615. {
  5616. op1b = this.DupOutPt(op1, true);
  5617. op2b = this.DupOutPt(op2, false);
  5618. op1.Next = op2;
  5619. op2.Prev = op1;
  5620. op1b.Prev = op2b;
  5621. op2b.Next = op1b;
  5622. j.OutPt1 = op1;
  5623. j.OutPt2 = op1b;
  5624. return true;
  5625. }
  5626. }
  5627. else if (isHorizontal)
  5628. {
  5629. //treat horizontal joins differently to non-horizontal joins since with
  5630. //them we're not yet sure where the overlapping is. OutPt1.Pt & OutPt2.Pt
  5631. //may be anywhere along the horizontal edge.
  5632. op1b = op1;
  5633. while (op1.Prev.Pt.Y === op1.Pt.Y && op1.Prev !== op1b && op1.Prev !== op2)
  5634. op1 = op1.Prev;
  5635. while (op1b.Next.Pt.Y === op1b.Pt.Y && op1b.Next !== op1 && op1b.Next !== op2)
  5636. op1b = op1b.Next;
  5637. if (op1b.Next === op1 || op1b.Next === op2)
  5638. return false;
  5639. //a flat 'polygon'
  5640. op2b = op2;
  5641. while (op2.Prev.Pt.Y === op2.Pt.Y && op2.Prev !== op2b && op2.Prev !== op1b)
  5642. op2 = op2.Prev;
  5643. while (op2b.Next.Pt.Y === op2b.Pt.Y && op2b.Next !== op2 && op2b.Next !== op1)
  5644. op2b = op2b.Next;
  5645. if (op2b.Next === op2 || op2b.Next === op1)
  5646. return false;
  5647. //a flat 'polygon'
  5648. //Op1 -. Op1b & Op2 -. Op2b are the extremites of the horizontal edges
  5649. var $val = {
  5650. Left: null,
  5651. Right: null
  5652. };
  5653. if (!this.GetOverlap(op1.Pt.X, op1b.Pt.X, op2.Pt.X, op2b.Pt.X, $val))
  5654. return false;
  5655. var Left = $val.Left;
  5656. var Right = $val.Right;
  5657. //DiscardLeftSide: when overlapping edges are joined, a spike will created
  5658. //which needs to be cleaned up. However, we don't want Op1 or Op2 caught up
  5659. //on the discard Side as either may still be needed for other joins ...
  5660. var Pt = new ClipperLib.IntPoint0();
  5661. var DiscardLeftSide;
  5662. if (op1.Pt.X >= Left && op1.Pt.X <= Right)
  5663. {
  5664. //Pt = op1.Pt;
  5665. Pt.X = op1.Pt.X;
  5666. Pt.Y = op1.Pt.Y;
  5667. if (ClipperLib.use_xyz) Pt.Z = op1.Pt.Z;
  5668. DiscardLeftSide = (op1.Pt.X > op1b.Pt.X);
  5669. }
  5670. else if (op2.Pt.X >= Left && op2.Pt.X <= Right)
  5671. {
  5672. //Pt = op2.Pt;
  5673. Pt.X = op2.Pt.X;
  5674. Pt.Y = op2.Pt.Y;
  5675. if (ClipperLib.use_xyz) Pt.Z = op2.Pt.Z;
  5676. DiscardLeftSide = (op2.Pt.X > op2b.Pt.X);
  5677. }
  5678. else if (op1b.Pt.X >= Left && op1b.Pt.X <= Right)
  5679. {
  5680. //Pt = op1b.Pt;
  5681. Pt.X = op1b.Pt.X;
  5682. Pt.Y = op1b.Pt.Y;
  5683. if (ClipperLib.use_xyz) Pt.Z = op1b.Pt.Z;
  5684. DiscardLeftSide = op1b.Pt.X > op1.Pt.X;
  5685. }
  5686. else
  5687. {
  5688. //Pt = op2b.Pt;
  5689. Pt.X = op2b.Pt.X;
  5690. Pt.Y = op2b.Pt.Y;
  5691. if (ClipperLib.use_xyz) Pt.Z = op2b.Pt.Z;
  5692. DiscardLeftSide = (op2b.Pt.X > op2.Pt.X);
  5693. }
  5694. j.OutPt1 = op1;
  5695. j.OutPt2 = op2;
  5696. return this.JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide);
  5697. }
  5698. else
  5699. {
  5700. //nb: For non-horizontal joins ...
  5701. // 1. Jr.OutPt1.Pt.Y == Jr.OutPt2.Pt.Y
  5702. // 2. Jr.OutPt1.Pt > Jr.OffPt.Y
  5703. //make sure the polygons are correctly oriented ...
  5704. op1b = op1.Next;
  5705. while ((ClipperLib.IntPoint.op_Equality(op1b.Pt, op1.Pt)) && (op1b !== op1))
  5706. op1b = op1b.Next;
  5707. var Reverse1 = ((op1b.Pt.Y > op1.Pt.Y) || !ClipperLib.ClipperBase.SlopesEqual4(op1.Pt, op1b.Pt, j.OffPt, this.m_UseFullRange));
  5708. if (Reverse1)
  5709. {
  5710. op1b = op1.Prev;
  5711. while ((ClipperLib.IntPoint.op_Equality(op1b.Pt, op1.Pt)) && (op1b !== op1))
  5712. op1b = op1b.Prev;
  5713. if ((op1b.Pt.Y > op1.Pt.Y) || !ClipperLib.ClipperBase.SlopesEqual4(op1.Pt, op1b.Pt, j.OffPt, this.m_UseFullRange))
  5714. return false;
  5715. }
  5716. op2b = op2.Next;
  5717. while ((ClipperLib.IntPoint.op_Equality(op2b.Pt, op2.Pt)) && (op2b !== op2))
  5718. op2b = op2b.Next;
  5719. var Reverse2 = ((op2b.Pt.Y > op2.Pt.Y) || !ClipperLib.ClipperBase.SlopesEqual4(op2.Pt, op2b.Pt, j.OffPt, this.m_UseFullRange));
  5720. if (Reverse2)
  5721. {
  5722. op2b = op2.Prev;
  5723. while ((ClipperLib.IntPoint.op_Equality(op2b.Pt, op2.Pt)) && (op2b !== op2))
  5724. op2b = op2b.Prev;
  5725. if ((op2b.Pt.Y > op2.Pt.Y) || !ClipperLib.ClipperBase.SlopesEqual4(op2.Pt, op2b.Pt, j.OffPt, this.m_UseFullRange))
  5726. return false;
  5727. }
  5728. if ((op1b === op1) || (op2b === op2) || (op1b === op2b) ||
  5729. ((outRec1 === outRec2) && (Reverse1 === Reverse2)))
  5730. return false;
  5731. if (Reverse1)
  5732. {
  5733. op1b = this.DupOutPt(op1, false);
  5734. op2b = this.DupOutPt(op2, true);
  5735. op1.Prev = op2;
  5736. op2.Next = op1;
  5737. op1b.Next = op2b;
  5738. op2b.Prev = op1b;
  5739. j.OutPt1 = op1;
  5740. j.OutPt2 = op1b;
  5741. return true;
  5742. }
  5743. else
  5744. {
  5745. op1b = this.DupOutPt(op1, true);
  5746. op2b = this.DupOutPt(op2, false);
  5747. op1.Next = op2;
  5748. op2.Prev = op1;
  5749. op1b.Prev = op2b;
  5750. op2b.Next = op1b;
  5751. j.OutPt1 = op1;
  5752. j.OutPt2 = op1b;
  5753. return true;
  5754. }
  5755. }
  5756. };
  5757. ClipperLib.Clipper.GetBounds = function (paths)
  5758. {
  5759. var i = 0,
  5760. cnt = paths.length;
  5761. while (i < cnt && paths[i].length === 0) i++;
  5762. if (i === cnt) return new ClipperLib.IntRect(0, 0, 0, 0);
  5763. var result = new ClipperLib.IntRect();
  5764. result.left = paths[i][0].X;
  5765. result.right = result.left;
  5766. result.top = paths[i][0].Y;
  5767. result.bottom = result.top;
  5768. for (; i < cnt; i++)
  5769. for (var j = 0, jlen = paths[i].length; j < jlen; j++)
  5770. {
  5771. if (paths[i][j].X < result.left) result.left = paths[i][j].X;
  5772. else if (paths[i][j].X > result.right) result.right = paths[i][j].X;
  5773. if (paths[i][j].Y < result.top) result.top = paths[i][j].Y;
  5774. else if (paths[i][j].Y > result.bottom) result.bottom = paths[i][j].Y;
  5775. }
  5776. return result;
  5777. }
  5778. ClipperLib.Clipper.prototype.GetBounds2 = function (ops)
  5779. {
  5780. var opStart = ops;
  5781. var result = new ClipperLib.IntRect();
  5782. result.left = ops.Pt.X;
  5783. result.right = ops.Pt.X;
  5784. result.top = ops.Pt.Y;
  5785. result.bottom = ops.Pt.Y;
  5786. ops = ops.Next;
  5787. while (ops !== opStart)
  5788. {
  5789. if (ops.Pt.X < result.left)
  5790. result.left = ops.Pt.X;
  5791. if (ops.Pt.X > result.right)
  5792. result.right = ops.Pt.X;
  5793. if (ops.Pt.Y < result.top)
  5794. result.top = ops.Pt.Y;
  5795. if (ops.Pt.Y > result.bottom)
  5796. result.bottom = ops.Pt.Y;
  5797. ops = ops.Next;
  5798. }
  5799. return result;
  5800. };
  5801. ClipperLib.Clipper.PointInPolygon = function (pt, path)
  5802. {
  5803. //returns 0 if false, +1 if true, -1 if pt ON polygon boundary
  5804. //See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos
  5805. //http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf
  5806. var result = 0,
  5807. cnt = path.length;
  5808. if (cnt < 3)
  5809. return 0;
  5810. var ip = path[0];
  5811. for (var i = 1; i <= cnt; ++i)
  5812. {
  5813. var ipNext = (i === cnt ? path[0] : path[i]);
  5814. if (ipNext.Y === pt.Y)
  5815. {
  5816. if ((ipNext.X === pt.X) || (ip.Y === pt.Y && ((ipNext.X > pt.X) === (ip.X < pt.X))))
  5817. return -1;
  5818. }
  5819. if ((ip.Y < pt.Y) !== (ipNext.Y < pt.Y))
  5820. {
  5821. if (ip.X >= pt.X)
  5822. {
  5823. if (ipNext.X > pt.X)
  5824. result = 1 - result;
  5825. else
  5826. {
  5827. var d = (ip.X - pt.X) * (ipNext.Y - pt.Y) - (ipNext.X - pt.X) * (ip.Y - pt.Y);
  5828. if (d === 0)
  5829. return -1;
  5830. else if ((d > 0) === (ipNext.Y > ip.Y))
  5831. result = 1 - result;
  5832. }
  5833. }
  5834. else
  5835. {
  5836. if (ipNext.X > pt.X)
  5837. {
  5838. var d = (ip.X - pt.X) * (ipNext.Y - pt.Y) - (ipNext.X - pt.X) * (ip.Y - pt.Y);
  5839. if (d === 0)
  5840. return -1;
  5841. else if ((d > 0) === (ipNext.Y > ip.Y))
  5842. result = 1 - result;
  5843. }
  5844. }
  5845. }
  5846. ip = ipNext;
  5847. }
  5848. return result;
  5849. };
  5850. ClipperLib.Clipper.prototype.PointInPolygon = function (pt, op)
  5851. {
  5852. //returns 0 if false, +1 if true, -1 if pt ON polygon boundary
  5853. var result = 0;
  5854. var startOp = op;
  5855. var ptx = pt.X,
  5856. pty = pt.Y;
  5857. var poly0x = op.Pt.X,
  5858. poly0y = op.Pt.Y;
  5859. do {
  5860. op = op.Next;
  5861. var poly1x = op.Pt.X,
  5862. poly1y = op.Pt.Y;
  5863. if (poly1y === pty)
  5864. {
  5865. if ((poly1x === ptx) || (poly0y === pty && ((poly1x > ptx) === (poly0x < ptx))))
  5866. return -1;
  5867. }
  5868. if ((poly0y < pty) !== (poly1y < pty))
  5869. {
  5870. if (poly0x >= ptx)
  5871. {
  5872. if (poly1x > ptx)
  5873. result = 1 - result;
  5874. else
  5875. {
  5876. var d = (poly0x - ptx) * (poly1y - pty) - (poly1x - ptx) * (poly0y - pty);
  5877. if (d === 0)
  5878. return -1;
  5879. if ((d > 0) === (poly1y > poly0y))
  5880. result = 1 - result;
  5881. }
  5882. }
  5883. else
  5884. {
  5885. if (poly1x > ptx)
  5886. {
  5887. var d = (poly0x - ptx) * (poly1y - pty) - (poly1x - ptx) * (poly0y - pty);
  5888. if (d === 0)
  5889. return -1;
  5890. if ((d > 0) === (poly1y > poly0y))
  5891. result = 1 - result;
  5892. }
  5893. }
  5894. }
  5895. poly0x = poly1x;
  5896. poly0y = poly1y;
  5897. } while (startOp !== op);
  5898. return result;
  5899. };
  5900. ClipperLib.Clipper.prototype.Poly2ContainsPoly1 = function (outPt1, outPt2)
  5901. {
  5902. var op = outPt1;
  5903. do {
  5904. //nb: PointInPolygon returns 0 if false, +1 if true, -1 if pt on polygon
  5905. var res = this.PointInPolygon(op.Pt, outPt2);
  5906. if (res >= 0)
  5907. return res > 0;
  5908. op = op.Next;
  5909. }
  5910. while (op !== outPt1)
  5911. return true;
  5912. };
  5913. ClipperLib.Clipper.prototype.FixupFirstLefts1 = function (OldOutRec, NewOutRec)
  5914. {
  5915. var outRec, firstLeft;
  5916. for (var i = 0, ilen = this.m_PolyOuts.length; i < ilen; i++)
  5917. {
  5918. outRec = this.m_PolyOuts[i];
  5919. firstLeft = ClipperLib.Clipper.ParseFirstLeft(outRec.FirstLeft);
  5920. if (outRec.Pts !== null && firstLeft === OldOutRec)
  5921. {
  5922. if (this.Poly2ContainsPoly1(outRec.Pts, NewOutRec.Pts))
  5923. outRec.FirstLeft = NewOutRec;
  5924. }
  5925. }
  5926. }
  5927. ClipperLib.Clipper.prototype.FixupFirstLefts2 = function (innerOutRec, outerOutRec)
  5928. {
  5929. //A polygon has split into two such that one is now the inner of the other.
  5930. //It's possible that these polygons now wrap around other polygons, so check
  5931. //every polygon that's also contained by OuterOutRec's FirstLeft container
  5932. //(including nil) to see if they've become inner to the new inner polygon ...
  5933. var orfl = outerOutRec.FirstLeft;
  5934. var outRec, firstLeft;
  5935. for (var i = 0, ilen = this.m_PolyOuts.length; i < ilen; i++)
  5936. {
  5937. outRec = this.m_PolyOuts[i];
  5938. if (outRec.Pts === null || outRec === outerOutRec || outRec === innerOutRec)
  5939. continue;
  5940. firstLeft = ClipperLib.Clipper.ParseFirstLeft(outRec.FirstLeft);
  5941. if (firstLeft !== orfl && firstLeft !== innerOutRec && firstLeft !== outerOutRec)
  5942. continue;
  5943. if (this.Poly2ContainsPoly1(outRec.Pts, innerOutRec.Pts))
  5944. outRec.FirstLeft = innerOutRec;
  5945. else if (this.Poly2ContainsPoly1(outRec.Pts, outerOutRec.Pts))
  5946. outRec.FirstLeft = outerOutRec;
  5947. else if (outRec.FirstLeft === innerOutRec || outRec.FirstLeft === outerOutRec)
  5948. outRec.FirstLeft = orfl;
  5949. }
  5950. }
  5951. ClipperLib.Clipper.prototype.FixupFirstLefts3 = function (OldOutRec, NewOutRec)
  5952. {
  5953. //same as FixupFirstLefts1 but doesn't call Poly2ContainsPoly1()
  5954. var outRec;
  5955. var firstLeft;
  5956. for (var i = 0, ilen = this.m_PolyOuts.length; i < ilen; i++)
  5957. {
  5958. outRec = this.m_PolyOuts[i];
  5959. firstLeft = ClipperLib.Clipper.ParseFirstLeft(outRec.FirstLeft);
  5960. if (outRec.Pts !== null && firstLeft === OldOutRec)
  5961. outRec.FirstLeft = NewOutRec;
  5962. }
  5963. }
  5964. ClipperLib.Clipper.ParseFirstLeft = function (FirstLeft)
  5965. {
  5966. while (FirstLeft !== null && FirstLeft.Pts === null)
  5967. FirstLeft = FirstLeft.FirstLeft;
  5968. return FirstLeft;
  5969. };
  5970. ClipperLib.Clipper.prototype.JoinCommonEdges = function ()
  5971. {
  5972. for (var i = 0, ilen = this.m_Joins.length; i < ilen; i++)
  5973. {
  5974. var join = this.m_Joins[i];
  5975. var outRec1 = this.GetOutRec(join.OutPt1.Idx);
  5976. var outRec2 = this.GetOutRec(join.OutPt2.Idx);
  5977. if (outRec1.Pts === null || outRec2.Pts === null)
  5978. continue;
  5979. if (outRec1.IsOpen || outRec2.IsOpen)
  5980. {
  5981. continue;
  5982. }
  5983. //get the polygon fragment with the correct hole state (FirstLeft)
  5984. //before calling JoinPoints() ...
  5985. var holeStateRec;
  5986. if (outRec1 === outRec2)
  5987. holeStateRec = outRec1;
  5988. else if (this.OutRec1RightOfOutRec2(outRec1, outRec2))
  5989. holeStateRec = outRec2;
  5990. else if (this.OutRec1RightOfOutRec2(outRec2, outRec1))
  5991. holeStateRec = outRec1;
  5992. else
  5993. holeStateRec = this.GetLowermostRec(outRec1, outRec2);
  5994. if (!this.JoinPoints(join, outRec1, outRec2)) continue;
  5995. if (outRec1 === outRec2)
  5996. {
  5997. //instead of joining two polygons, we've just created a new one by
  5998. //splitting one polygon into two.
  5999. outRec1.Pts = join.OutPt1;
  6000. outRec1.BottomPt = null;
  6001. outRec2 = this.CreateOutRec();
  6002. outRec2.Pts = join.OutPt2;
  6003. //update all OutRec2.Pts Idx's ...
  6004. this.UpdateOutPtIdxs(outRec2);
  6005. if (this.Poly2ContainsPoly1(outRec2.Pts, outRec1.Pts))
  6006. {
  6007. //outRec1 contains outRec2 ...
  6008. outRec2.IsHole = !outRec1.IsHole;
  6009. outRec2.FirstLeft = outRec1;
  6010. if (this.m_UsingPolyTree)
  6011. this.FixupFirstLefts2(outRec2, outRec1);
  6012. if ((outRec2.IsHole ^ this.ReverseSolution) == (this.Area$1(outRec2) > 0))
  6013. this.ReversePolyPtLinks(outRec2.Pts);
  6014. }
  6015. else if (this.Poly2ContainsPoly1(outRec1.Pts, outRec2.Pts))
  6016. {
  6017. //outRec2 contains outRec1 ...
  6018. outRec2.IsHole = outRec1.IsHole;
  6019. outRec1.IsHole = !outRec2.IsHole;
  6020. outRec2.FirstLeft = outRec1.FirstLeft;
  6021. outRec1.FirstLeft = outRec2;
  6022. if (this.m_UsingPolyTree)
  6023. this.FixupFirstLefts2(outRec1, outRec2);
  6024. if ((outRec1.IsHole ^ this.ReverseSolution) == (this.Area$1(outRec1) > 0))
  6025. this.ReversePolyPtLinks(outRec1.Pts);
  6026. }
  6027. else
  6028. {
  6029. //the 2 polygons are completely separate ...
  6030. outRec2.IsHole = outRec1.IsHole;
  6031. outRec2.FirstLeft = outRec1.FirstLeft;
  6032. //fixup FirstLeft pointers that may need reassigning to OutRec2
  6033. if (this.m_UsingPolyTree)
  6034. this.FixupFirstLefts1(outRec1, outRec2);
  6035. }
  6036. }
  6037. else
  6038. {
  6039. //joined 2 polygons together ...
  6040. outRec2.Pts = null;
  6041. outRec2.BottomPt = null;
  6042. outRec2.Idx = outRec1.Idx;
  6043. outRec1.IsHole = holeStateRec.IsHole;
  6044. if (holeStateRec === outRec2)
  6045. outRec1.FirstLeft = outRec2.FirstLeft;
  6046. outRec2.FirstLeft = outRec1;
  6047. //fixup FirstLeft pointers that may need reassigning to OutRec1
  6048. if (this.m_UsingPolyTree)
  6049. this.FixupFirstLefts3(outRec2, outRec1);
  6050. }
  6051. }
  6052. };
  6053. ClipperLib.Clipper.prototype.UpdateOutPtIdxs = function (outrec)
  6054. {
  6055. var op = outrec.Pts;
  6056. do {
  6057. op.Idx = outrec.Idx;
  6058. op = op.Prev;
  6059. }
  6060. while (op !== outrec.Pts)
  6061. };
  6062. ClipperLib.Clipper.prototype.DoSimplePolygons = function ()
  6063. {
  6064. var i = 0;
  6065. while (i < this.m_PolyOuts.length)
  6066. {
  6067. var outrec = this.m_PolyOuts[i++];
  6068. var op = outrec.Pts;
  6069. if (op === null || outrec.IsOpen)
  6070. continue;
  6071. do //for each Pt in Polygon until duplicate found do ...
  6072. {
  6073. var op2 = op.Next;
  6074. while (op2 !== outrec.Pts)
  6075. {
  6076. if ((ClipperLib.IntPoint.op_Equality(op.Pt, op2.Pt)) && op2.Next !== op && op2.Prev !== op)
  6077. {
  6078. //split the polygon into two ...
  6079. var op3 = op.Prev;
  6080. var op4 = op2.Prev;
  6081. op.Prev = op4;
  6082. op4.Next = op;
  6083. op2.Prev = op3;
  6084. op3.Next = op2;
  6085. outrec.Pts = op;
  6086. var outrec2 = this.CreateOutRec();
  6087. outrec2.Pts = op2;
  6088. this.UpdateOutPtIdxs(outrec2);
  6089. if (this.Poly2ContainsPoly1(outrec2.Pts, outrec.Pts))
  6090. {
  6091. //OutRec2 is contained by OutRec1 ...
  6092. outrec2.IsHole = !outrec.IsHole;
  6093. outrec2.FirstLeft = outrec;
  6094. if (this.m_UsingPolyTree) this.FixupFirstLefts2(outrec2, outrec);
  6095. }
  6096. else if (this.Poly2ContainsPoly1(outrec.Pts, outrec2.Pts))
  6097. {
  6098. //OutRec1 is contained by OutRec2 ...
  6099. outrec2.IsHole = outrec.IsHole;
  6100. outrec.IsHole = !outrec2.IsHole;
  6101. outrec2.FirstLeft = outrec.FirstLeft;
  6102. outrec.FirstLeft = outrec2;
  6103. if (this.m_UsingPolyTree) this.FixupFirstLefts2(outrec, outrec2);
  6104. }
  6105. else
  6106. {
  6107. //the 2 polygons are separate ...
  6108. outrec2.IsHole = outrec.IsHole;
  6109. outrec2.FirstLeft = outrec.FirstLeft;
  6110. if (this.m_UsingPolyTree) this.FixupFirstLefts1(outrec, outrec2);
  6111. }
  6112. op2 = op;
  6113. //ie get ready for the next iteration
  6114. }
  6115. op2 = op2.Next;
  6116. }
  6117. op = op.Next;
  6118. }
  6119. while (op !== outrec.Pts)
  6120. }
  6121. };
  6122. ClipperLib.Clipper.Area = function (poly)
  6123. {
  6124. if (!Array.isArray(poly))
  6125. return 0;
  6126. var cnt = poly.length;
  6127. if (cnt < 3)
  6128. return 0;
  6129. var a = 0;
  6130. for (var i = 0, j = cnt - 1; i < cnt; ++i)
  6131. {
  6132. a += (poly[j].X + poly[i].X) * (poly[j].Y - poly[i].Y);
  6133. j = i;
  6134. }
  6135. return -a * 0.5;
  6136. };
  6137. ClipperLib.Clipper.prototype.Area = function (op)
  6138. {
  6139. var opFirst = op;
  6140. if (op === null) return 0;
  6141. var a = 0;
  6142. do {
  6143. a = a + (op.Prev.Pt.X + op.Pt.X) * (op.Prev.Pt.Y - op.Pt.Y);
  6144. op = op.Next;
  6145. } while (op !== opFirst); // && typeof op !== 'undefined');
  6146. return a * 0.5;
  6147. }
  6148. ClipperLib.Clipper.prototype.Area$1 = function (outRec)
  6149. {
  6150. return this.Area(outRec.Pts);
  6151. };
  6152. ClipperLib.Clipper.SimplifyPolygon = function (poly, fillType)
  6153. {
  6154. var result = new Array();
  6155. var c = new ClipperLib.Clipper(0);
  6156. c.StrictlySimple = true;
  6157. c.AddPath(poly, ClipperLib.PolyType.ptSubject, true);
  6158. c.Execute(ClipperLib.ClipType.ctUnion, result, fillType, fillType);
  6159. return result;
  6160. };
  6161. ClipperLib.Clipper.SimplifyPolygons = function (polys, fillType)
  6162. {
  6163. if (typeof (fillType) === "undefined") fillType = ClipperLib.PolyFillType.pftEvenOdd;
  6164. var result = new Array();
  6165. var c = new ClipperLib.Clipper(0);
  6166. c.StrictlySimple = true;
  6167. c.AddPaths(polys, ClipperLib.PolyType.ptSubject, true);
  6168. c.Execute(ClipperLib.ClipType.ctUnion, result, fillType, fillType);
  6169. return result;
  6170. };
  6171. ClipperLib.Clipper.DistanceSqrd = function (pt1, pt2)
  6172. {
  6173. var dx = (pt1.X - pt2.X);
  6174. var dy = (pt1.Y - pt2.Y);
  6175. return (dx * dx + dy * dy);
  6176. };
  6177. ClipperLib.Clipper.DistanceFromLineSqrd = function (pt, ln1, ln2)
  6178. {
  6179. //The equation of a line in general form (Ax + By + C = 0)
  6180. //given 2 points (x¹,y¹) & (x²,y²) is ...
  6181. //(y¹ - y²)x + (x² - x¹)y + (y² - y¹)x¹ - (x² - x¹)y¹ = 0
  6182. //A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹
  6183. //perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²)
  6184. //see http://en.wikipedia.org/wiki/Perpendicular_distance
  6185. var A = ln1.Y - ln2.Y;
  6186. var B = ln2.X - ln1.X;
  6187. var C = A * ln1.X + B * ln1.Y;
  6188. C = A * pt.X + B * pt.Y - C;
  6189. return (C * C) / (A * A + B * B);
  6190. };
  6191. ClipperLib.Clipper.SlopesNearCollinear = function (pt1, pt2, pt3, distSqrd)
  6192. {
  6193. //this function is more accurate when the point that's GEOMETRICALLY
  6194. //between the other 2 points is the one that's tested for distance.
  6195. //nb: with 'spikes', either pt1 or pt3 is geometrically between the other pts
  6196. if (Math.abs(pt1.X - pt2.X) > Math.abs(pt1.Y - pt2.Y))
  6197. {
  6198. if ((pt1.X > pt2.X) === (pt1.X < pt3.X))
  6199. return ClipperLib.Clipper.DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd;
  6200. else if ((pt2.X > pt1.X) === (pt2.X < pt3.X))
  6201. return ClipperLib.Clipper.DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd;
  6202. else
  6203. return ClipperLib.Clipper.DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd;
  6204. }
  6205. else
  6206. {
  6207. if ((pt1.Y > pt2.Y) === (pt1.Y < pt3.Y))
  6208. return ClipperLib.Clipper.DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd;
  6209. else if ((pt2.Y > pt1.Y) === (pt2.Y < pt3.Y))
  6210. return ClipperLib.Clipper.DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd;
  6211. else
  6212. return ClipperLib.Clipper.DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd;
  6213. }
  6214. }
  6215. ClipperLib.Clipper.PointsAreClose = function (pt1, pt2, distSqrd)
  6216. {
  6217. var dx = pt1.X - pt2.X;
  6218. var dy = pt1.Y - pt2.Y;
  6219. return ((dx * dx) + (dy * dy) <= distSqrd);
  6220. };
  6221. ClipperLib.Clipper.ExcludeOp = function (op)
  6222. {
  6223. var result = op.Prev;
  6224. result.Next = op.Next;
  6225. op.Next.Prev = result;
  6226. result.Idx = 0;
  6227. return result;
  6228. };
  6229. ClipperLib.Clipper.CleanPolygon = function (path, distance)
  6230. {
  6231. if (typeof (distance) === "undefined") distance = 1.415;
  6232. //distance = proximity in units/pixels below which vertices will be stripped.
  6233. //Default ~= sqrt(2) so when adjacent vertices or semi-adjacent vertices have
  6234. //both x & y coords within 1 unit, then the second vertex will be stripped.
  6235. var cnt = path.length;
  6236. if (cnt === 0)
  6237. return new Array();
  6238. var outPts = new Array(cnt);
  6239. for (var i = 0; i < cnt; ++i)
  6240. outPts[i] = new ClipperLib.OutPt();
  6241. for (var i = 0; i < cnt; ++i)
  6242. {
  6243. outPts[i].Pt = path[i];
  6244. outPts[i].Next = outPts[(i + 1) % cnt];
  6245. outPts[i].Next.Prev = outPts[i];
  6246. outPts[i].Idx = 0;
  6247. }
  6248. var distSqrd = distance * distance;
  6249. var op = outPts[0];
  6250. while (op.Idx === 0 && op.Next !== op.Prev)
  6251. {
  6252. if (ClipperLib.Clipper.PointsAreClose(op.Pt, op.Prev.Pt, distSqrd))
  6253. {
  6254. op = ClipperLib.Clipper.ExcludeOp(op);
  6255. cnt--;
  6256. }
  6257. else if (ClipperLib.Clipper.PointsAreClose(op.Prev.Pt, op.Next.Pt, distSqrd))
  6258. {
  6259. ClipperLib.Clipper.ExcludeOp(op.Next);
  6260. op = ClipperLib.Clipper.ExcludeOp(op);
  6261. cnt -= 2;
  6262. }
  6263. else if (ClipperLib.Clipper.SlopesNearCollinear(op.Prev.Pt, op.Pt, op.Next.Pt, distSqrd))
  6264. {
  6265. op = ClipperLib.Clipper.ExcludeOp(op);
  6266. cnt--;
  6267. }
  6268. else
  6269. {
  6270. op.Idx = 1;
  6271. op = op.Next;
  6272. }
  6273. }
  6274. if (cnt < 3)
  6275. cnt = 0;
  6276. var result = new Array(cnt);
  6277. for (var i = 0; i < cnt; ++i)
  6278. {
  6279. result[i] = new ClipperLib.IntPoint1(op.Pt);
  6280. op = op.Next;
  6281. }
  6282. outPts = null;
  6283. return result;
  6284. };
  6285. ClipperLib.Clipper.CleanPolygons = function (polys, distance)
  6286. {
  6287. var result = new Array(polys.length);
  6288. for (var i = 0, ilen = polys.length; i < ilen; i++)
  6289. result[i] = ClipperLib.Clipper.CleanPolygon(polys[i], distance);
  6290. return result;
  6291. };
  6292. ClipperLib.Clipper.Minkowski = function (pattern, path, IsSum, IsClosed)
  6293. {
  6294. var delta = (IsClosed ? 1 : 0);
  6295. var polyCnt = pattern.length;
  6296. var pathCnt = path.length;
  6297. var result = new Array();
  6298. if (IsSum)
  6299. for (var i = 0; i < pathCnt; i++)
  6300. {
  6301. var p = new Array(polyCnt);
  6302. for (var j = 0, jlen = pattern.length, ip = pattern[j]; j < jlen; j++, ip = pattern[j])
  6303. p[j] = new ClipperLib.IntPoint2(path[i].X + ip.X, path[i].Y + ip.Y);
  6304. result.push(p);
  6305. }
  6306. else
  6307. for (var i = 0; i < pathCnt; i++)
  6308. {
  6309. var p = new Array(polyCnt);
  6310. for (var j = 0, jlen = pattern.length, ip = pattern[j]; j < jlen; j++, ip = pattern[j])
  6311. p[j] = new ClipperLib.IntPoint2(path[i].X - ip.X, path[i].Y - ip.Y);
  6312. result.push(p);
  6313. }
  6314. var quads = new Array();
  6315. for (var i = 0; i < pathCnt - 1 + delta; i++)
  6316. for (var j = 0; j < polyCnt; j++)
  6317. {
  6318. var quad = new Array();
  6319. quad.push(result[i % pathCnt][j % polyCnt]);
  6320. quad.push(result[(i + 1) % pathCnt][j % polyCnt]);
  6321. quad.push(result[(i + 1) % pathCnt][(j + 1) % polyCnt]);
  6322. quad.push(result[i % pathCnt][(j + 1) % polyCnt]);
  6323. if (!ClipperLib.Clipper.Orientation(quad))
  6324. quad.reverse();
  6325. quads.push(quad);
  6326. }
  6327. return quads;
  6328. };
  6329. ClipperLib.Clipper.MinkowskiSum = function (pattern, path_or_paths, pathIsClosed)
  6330. {
  6331. if (!(path_or_paths[0] instanceof Array))
  6332. {
  6333. var path = path_or_paths;
  6334. var paths = ClipperLib.Clipper.Minkowski(pattern, path, true, pathIsClosed);
  6335. var c = new ClipperLib.Clipper();
  6336. c.AddPaths(paths, ClipperLib.PolyType.ptSubject, true);
  6337. c.Execute(ClipperLib.ClipType.ctUnion, paths, ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero);
  6338. return paths;
  6339. }
  6340. else
  6341. {
  6342. var paths = path_or_paths;
  6343. var solution = new ClipperLib.Paths();
  6344. var c = new ClipperLib.Clipper();
  6345. for (var i = 0; i < paths.length; ++i)
  6346. {
  6347. var tmp = ClipperLib.Clipper.Minkowski(pattern, paths[i], true, pathIsClosed);
  6348. c.AddPaths(tmp, ClipperLib.PolyType.ptSubject, true);
  6349. if (pathIsClosed)
  6350. {
  6351. var path = ClipperLib.Clipper.TranslatePath(paths[i], pattern[0]);
  6352. c.AddPath(path, ClipperLib.PolyType.ptClip, true);
  6353. }
  6354. }
  6355. c.Execute(ClipperLib.ClipType.ctUnion, solution,
  6356. ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero);
  6357. return solution;
  6358. }
  6359. }
  6360. ClipperLib.Clipper.TranslatePath = function (path, delta)
  6361. {
  6362. var outPath = new ClipperLib.Path();
  6363. for (var i = 0; i < path.length; i++)
  6364. outPath.push(new ClipperLib.IntPoint2(path[i].X + delta.X, path[i].Y + delta.Y));
  6365. return outPath;
  6366. }
  6367. ClipperLib.Clipper.MinkowskiDiff = function (poly1, poly2)
  6368. {
  6369. var paths = ClipperLib.Clipper.Minkowski(poly1, poly2, false, true);
  6370. var c = new ClipperLib.Clipper();
  6371. c.AddPaths(paths, ClipperLib.PolyType.ptSubject, true);
  6372. c.Execute(ClipperLib.ClipType.ctUnion, paths, ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero);
  6373. return paths;
  6374. }
  6375. ClipperLib.Clipper.PolyTreeToPaths = function (polytree)
  6376. {
  6377. var result = new Array();
  6378. //result.set_Capacity(polytree.get_Total());
  6379. ClipperLib.Clipper.AddPolyNodeToPaths(polytree, ClipperLib.Clipper.NodeType.ntAny, result);
  6380. return result;
  6381. };
  6382. ClipperLib.Clipper.AddPolyNodeToPaths = function (polynode, nt, paths)
  6383. {
  6384. var match = true;
  6385. switch (nt)
  6386. {
  6387. case ClipperLib.Clipper.NodeType.ntOpen:
  6388. return;
  6389. case ClipperLib.Clipper.NodeType.ntClosed:
  6390. match = !polynode.IsOpen;
  6391. break;
  6392. default:
  6393. break;
  6394. }
  6395. if (polynode.m_polygon.length > 0 && match)
  6396. paths.push(polynode.m_polygon);
  6397. for (var $i3 = 0, $t3 = polynode.Childs(), $l3 = $t3.length, pn = $t3[$i3]; $i3 < $l3; $i3++, pn = $t3[$i3])
  6398. ClipperLib.Clipper.AddPolyNodeToPaths(pn, nt, paths);
  6399. };
  6400. ClipperLib.Clipper.OpenPathsFromPolyTree = function (polytree)
  6401. {
  6402. var result = new ClipperLib.Paths();
  6403. //result.set_Capacity(polytree.ChildCount());
  6404. for (var i = 0, ilen = polytree.ChildCount(); i < ilen; i++)
  6405. if (polytree.Childs()[i].IsOpen)
  6406. result.push(polytree.Childs()[i].m_polygon);
  6407. return result;
  6408. };
  6409. ClipperLib.Clipper.ClosedPathsFromPolyTree = function (polytree)
  6410. {
  6411. var result = new ClipperLib.Paths();
  6412. //result.set_Capacity(polytree.Total());
  6413. ClipperLib.Clipper.AddPolyNodeToPaths(polytree, ClipperLib.Clipper.NodeType.ntClosed, result);
  6414. return result;
  6415. };
  6416. Inherit(ClipperLib.Clipper, ClipperLib.ClipperBase);
  6417. ClipperLib.Clipper.NodeType = {
  6418. ntAny: 0,
  6419. ntOpen: 1,
  6420. ntClosed: 2
  6421. };
  6422. /**
  6423. * @constructor
  6424. */
  6425. ClipperLib.ClipperOffset = function (miterLimit, arcTolerance)
  6426. {
  6427. if (typeof (miterLimit) === "undefined") miterLimit = 2;
  6428. if (typeof (arcTolerance) === "undefined") arcTolerance = ClipperLib.ClipperOffset.def_arc_tolerance;
  6429. this.m_destPolys = new ClipperLib.Paths();
  6430. this.m_srcPoly = new ClipperLib.Path();
  6431. this.m_destPoly = new ClipperLib.Path();
  6432. this.m_normals = new Array();
  6433. this.m_delta = 0;
  6434. this.m_sinA = 0;
  6435. this.m_sin = 0;
  6436. this.m_cos = 0;
  6437. this.m_miterLim = 0;
  6438. this.m_StepsPerRad = 0;
  6439. this.m_lowest = new ClipperLib.IntPoint0();
  6440. this.m_polyNodes = new ClipperLib.PolyNode();
  6441. this.MiterLimit = miterLimit;
  6442. this.ArcTolerance = arcTolerance;
  6443. this.m_lowest.X = -1;
  6444. };
  6445. ClipperLib.ClipperOffset.two_pi = 6.28318530717959;
  6446. ClipperLib.ClipperOffset.def_arc_tolerance = 0.25;
  6447. ClipperLib.ClipperOffset.prototype.Clear = function ()
  6448. {
  6449. ClipperLib.Clear(this.m_polyNodes.Childs());
  6450. this.m_lowest.X = -1;
  6451. };
  6452. ClipperLib.ClipperOffset.Round = ClipperLib.Clipper.Round;
  6453. ClipperLib.ClipperOffset.prototype.AddPath = function (path, joinType, endType)
  6454. {
  6455. var highI = path.length - 1;
  6456. if (highI < 0)
  6457. return;
  6458. var newNode = new ClipperLib.PolyNode();
  6459. newNode.m_jointype = joinType;
  6460. newNode.m_endtype = endType;
  6461. //strip duplicate points from path and also get index to the lowest point ...
  6462. if (endType === ClipperLib.EndType.etClosedLine || endType === ClipperLib.EndType.etClosedPolygon)
  6463. while (highI > 0 && ClipperLib.IntPoint.op_Equality(path[0], path[highI]))
  6464. highI--;
  6465. //newNode.m_polygon.set_Capacity(highI + 1);
  6466. newNode.m_polygon.push(path[0]);
  6467. var j = 0,
  6468. k = 0;
  6469. for (var i = 1; i <= highI; i++)
  6470. if (ClipperLib.IntPoint.op_Inequality(newNode.m_polygon[j], path[i]))
  6471. {
  6472. j++;
  6473. newNode.m_polygon.push(path[i]);
  6474. if (path[i].Y > newNode.m_polygon[k].Y || (path[i].Y === newNode.m_polygon[k].Y && path[i].X < newNode.m_polygon[k].X))
  6475. k = j;
  6476. }
  6477. if (endType === ClipperLib.EndType.etClosedPolygon && j < 2) return;
  6478. this.m_polyNodes.AddChild(newNode);
  6479. //if this path's lowest pt is lower than all the others then update m_lowest
  6480. if (endType !== ClipperLib.EndType.etClosedPolygon)
  6481. return;
  6482. if (this.m_lowest.X < 0)
  6483. this.m_lowest = new ClipperLib.IntPoint2(this.m_polyNodes.ChildCount() - 1, k);
  6484. else
  6485. {
  6486. var ip = this.m_polyNodes.Childs()[this.m_lowest.X].m_polygon[this.m_lowest.Y];
  6487. if (newNode.m_polygon[k].Y > ip.Y || (newNode.m_polygon[k].Y === ip.Y && newNode.m_polygon[k].X < ip.X))
  6488. this.m_lowest = new ClipperLib.IntPoint2(this.m_polyNodes.ChildCount() - 1, k);
  6489. }
  6490. };
  6491. ClipperLib.ClipperOffset.prototype.AddPaths = function (paths, joinType, endType)
  6492. {
  6493. for (var i = 0, ilen = paths.length; i < ilen; i++)
  6494. this.AddPath(paths[i], joinType, endType);
  6495. };
  6496. ClipperLib.ClipperOffset.prototype.FixOrientations = function ()
  6497. {
  6498. //fixup orientations of all closed paths if the orientation of the
  6499. //closed path with the lowermost vertex is wrong ...
  6500. if (this.m_lowest.X >= 0 && !ClipperLib.Clipper.Orientation(this.m_polyNodes.Childs()[this.m_lowest.X].m_polygon))
  6501. {
  6502. for (var i = 0; i < this.m_polyNodes.ChildCount(); i++)
  6503. {
  6504. var node = this.m_polyNodes.Childs()[i];
  6505. if (node.m_endtype === ClipperLib.EndType.etClosedPolygon || (node.m_endtype === ClipperLib.EndType.etClosedLine && ClipperLib.Clipper.Orientation(node.m_polygon)))
  6506. node.m_polygon.reverse();
  6507. }
  6508. }
  6509. else
  6510. {
  6511. for (var i = 0; i < this.m_polyNodes.ChildCount(); i++)
  6512. {
  6513. var node = this.m_polyNodes.Childs()[i];
  6514. if (node.m_endtype === ClipperLib.EndType.etClosedLine && !ClipperLib.Clipper.Orientation(node.m_polygon))
  6515. node.m_polygon.reverse();
  6516. }
  6517. }
  6518. };
  6519. ClipperLib.ClipperOffset.GetUnitNormal = function (pt1, pt2)
  6520. {
  6521. var dx = (pt2.X - pt1.X);
  6522. var dy = (pt2.Y - pt1.Y);
  6523. if ((dx === 0) && (dy === 0))
  6524. return new ClipperLib.DoublePoint2(0, 0);
  6525. var f = 1 / Math.sqrt(dx * dx + dy * dy);
  6526. dx *= f;
  6527. dy *= f;
  6528. return new ClipperLib.DoublePoint2(dy, -dx);
  6529. };
  6530. ClipperLib.ClipperOffset.prototype.DoOffset = function (delta)
  6531. {
  6532. this.m_destPolys = new Array();
  6533. this.m_delta = delta;
  6534. //if Zero offset, just copy any CLOSED polygons to m_p and return ...
  6535. if (ClipperLib.ClipperBase.near_zero(delta))
  6536. {
  6537. //this.m_destPolys.set_Capacity(this.m_polyNodes.ChildCount);
  6538. for (var i = 0; i < this.m_polyNodes.ChildCount(); i++)
  6539. {
  6540. var node = this.m_polyNodes.Childs()[i];
  6541. if (node.m_endtype === ClipperLib.EndType.etClosedPolygon)
  6542. this.m_destPolys.push(node.m_polygon);
  6543. }
  6544. return;
  6545. }
  6546. //see offset_triginometry3.svg in the documentation folder ...
  6547. if (this.MiterLimit > 2)
  6548. this.m_miterLim = 2 / (this.MiterLimit * this.MiterLimit);
  6549. else
  6550. this.m_miterLim = 0.5;
  6551. var y;
  6552. if (this.ArcTolerance <= 0)
  6553. y = ClipperLib.ClipperOffset.def_arc_tolerance;
  6554. else if (this.ArcTolerance > Math.abs(delta) * ClipperLib.ClipperOffset.def_arc_tolerance)
  6555. y = Math.abs(delta) * ClipperLib.ClipperOffset.def_arc_tolerance;
  6556. else
  6557. y = this.ArcTolerance;
  6558. //see offset_triginometry2.svg in the documentation folder ...
  6559. var steps = 3.14159265358979 / Math.acos(1 - y / Math.abs(delta));
  6560. this.m_sin = Math.sin(ClipperLib.ClipperOffset.two_pi / steps);
  6561. this.m_cos = Math.cos(ClipperLib.ClipperOffset.two_pi / steps);
  6562. this.m_StepsPerRad = steps / ClipperLib.ClipperOffset.two_pi;
  6563. if (delta < 0)
  6564. this.m_sin = -this.m_sin;
  6565. //this.m_destPolys.set_Capacity(this.m_polyNodes.ChildCount * 2);
  6566. for (var i = 0; i < this.m_polyNodes.ChildCount(); i++)
  6567. {
  6568. var node = this.m_polyNodes.Childs()[i];
  6569. this.m_srcPoly = node.m_polygon;
  6570. var len = this.m_srcPoly.length;
  6571. if (len === 0 || (delta <= 0 && (len < 3 || node.m_endtype !== ClipperLib.EndType.etClosedPolygon)))
  6572. continue;
  6573. this.m_destPoly = new Array();
  6574. if (len === 1)
  6575. {
  6576. if (node.m_jointype === ClipperLib.JoinType.jtRound)
  6577. {
  6578. var X = 1,
  6579. Y = 0;
  6580. for (var j = 1; j <= steps; j++)
  6581. {
  6582. this.m_destPoly.push(new ClipperLib.IntPoint2(ClipperLib.ClipperOffset.Round(this.m_srcPoly[0].X + X * delta), ClipperLib.ClipperOffset.Round(this.m_srcPoly[0].Y + Y * delta)));
  6583. var X2 = X;
  6584. X = X * this.m_cos - this.m_sin * Y;
  6585. Y = X2 * this.m_sin + Y * this.m_cos;
  6586. }
  6587. }
  6588. else
  6589. {
  6590. var X = -1,
  6591. Y = -1;
  6592. for (var j = 0; j < 4; ++j)
  6593. {
  6594. this.m_destPoly.push(new ClipperLib.IntPoint2(ClipperLib.ClipperOffset.Round(this.m_srcPoly[0].X + X * delta), ClipperLib.ClipperOffset.Round(this.m_srcPoly[0].Y + Y * delta)));
  6595. if (X < 0)
  6596. X = 1;
  6597. else if (Y < 0)
  6598. Y = 1;
  6599. else
  6600. X = -1;
  6601. }
  6602. }
  6603. this.m_destPolys.push(this.m_destPoly);
  6604. continue;
  6605. }
  6606. //build m_normals ...
  6607. this.m_normals.length = 0;
  6608. //this.m_normals.set_Capacity(len);
  6609. for (var j = 0; j < len - 1; j++)
  6610. this.m_normals.push(ClipperLib.ClipperOffset.GetUnitNormal(this.m_srcPoly[j], this.m_srcPoly[j + 1]));
  6611. if (node.m_endtype === ClipperLib.EndType.etClosedLine || node.m_endtype === ClipperLib.EndType.etClosedPolygon)
  6612. this.m_normals.push(ClipperLib.ClipperOffset.GetUnitNormal(this.m_srcPoly[len - 1], this.m_srcPoly[0]));
  6613. else
  6614. this.m_normals.push(new ClipperLib.DoublePoint1(this.m_normals[len - 2]));
  6615. if (node.m_endtype === ClipperLib.EndType.etClosedPolygon)
  6616. {
  6617. var k = len - 1;
  6618. for (var j = 0; j < len; j++)
  6619. k = this.OffsetPoint(j, k, node.m_jointype);
  6620. this.m_destPolys.push(this.m_destPoly);
  6621. }
  6622. else if (node.m_endtype === ClipperLib.EndType.etClosedLine)
  6623. {
  6624. var k = len - 1;
  6625. for (var j = 0; j < len; j++)
  6626. k = this.OffsetPoint(j, k, node.m_jointype);
  6627. this.m_destPolys.push(this.m_destPoly);
  6628. this.m_destPoly = new Array();
  6629. //re-build m_normals ...
  6630. var n = this.m_normals[len - 1];
  6631. for (var j = len - 1; j > 0; j--)
  6632. this.m_normals[j] = new ClipperLib.DoublePoint2(-this.m_normals[j - 1].X, -this.m_normals[j - 1].Y);
  6633. this.m_normals[0] = new ClipperLib.DoublePoint2(-n.X, -n.Y);
  6634. k = 0;
  6635. for (var j = len - 1; j >= 0; j--)
  6636. k = this.OffsetPoint(j, k, node.m_jointype);
  6637. this.m_destPolys.push(this.m_destPoly);
  6638. }
  6639. else
  6640. {
  6641. var k = 0;
  6642. for (var j = 1; j < len - 1; ++j)
  6643. k = this.OffsetPoint(j, k, node.m_jointype);
  6644. var pt1;
  6645. if (node.m_endtype === ClipperLib.EndType.etOpenButt)
  6646. {
  6647. var j = len - 1;
  6648. pt1 = new ClipperLib.IntPoint2(ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].X + this.m_normals[j].X * delta), ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].Y + this.m_normals[j].Y * delta));
  6649. this.m_destPoly.push(pt1);
  6650. pt1 = new ClipperLib.IntPoint2(ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].X - this.m_normals[j].X * delta), ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].Y - this.m_normals[j].Y * delta));
  6651. this.m_destPoly.push(pt1);
  6652. }
  6653. else
  6654. {
  6655. var j = len - 1;
  6656. k = len - 2;
  6657. this.m_sinA = 0;
  6658. this.m_normals[j] = new ClipperLib.DoublePoint2(-this.m_normals[j].X, -this.m_normals[j].Y);
  6659. if (node.m_endtype === ClipperLib.EndType.etOpenSquare)
  6660. this.DoSquare(j, k);
  6661. else
  6662. this.DoRound(j, k);
  6663. }
  6664. //re-build m_normals ...
  6665. for (var j = len - 1; j > 0; j--)
  6666. this.m_normals[j] = new ClipperLib.DoublePoint2(-this.m_normals[j - 1].X, -this.m_normals[j - 1].Y);
  6667. this.m_normals[0] = new ClipperLib.DoublePoint2(-this.m_normals[1].X, -this.m_normals[1].Y);
  6668. k = len - 1;
  6669. for (var j = k - 1; j > 0; --j)
  6670. k = this.OffsetPoint(j, k, node.m_jointype);
  6671. if (node.m_endtype === ClipperLib.EndType.etOpenButt)
  6672. {
  6673. pt1 = new ClipperLib.IntPoint2(ClipperLib.ClipperOffset.Round(this.m_srcPoly[0].X - this.m_normals[0].X * delta), ClipperLib.ClipperOffset.Round(this.m_srcPoly[0].Y - this.m_normals[0].Y * delta));
  6674. this.m_destPoly.push(pt1);
  6675. pt1 = new ClipperLib.IntPoint2(ClipperLib.ClipperOffset.Round(this.m_srcPoly[0].X + this.m_normals[0].X * delta), ClipperLib.ClipperOffset.Round(this.m_srcPoly[0].Y + this.m_normals[0].Y * delta));
  6676. this.m_destPoly.push(pt1);
  6677. }
  6678. else
  6679. {
  6680. k = 1;
  6681. this.m_sinA = 0;
  6682. if (node.m_endtype === ClipperLib.EndType.etOpenSquare)
  6683. this.DoSquare(0, 1);
  6684. else
  6685. this.DoRound(0, 1);
  6686. }
  6687. this.m_destPolys.push(this.m_destPoly);
  6688. }
  6689. }
  6690. };
  6691. ClipperLib.ClipperOffset.prototype.Execute = function ()
  6692. {
  6693. var a = arguments,
  6694. ispolytree = a[0] instanceof ClipperLib.PolyTree;
  6695. if (!ispolytree) // function (solution, delta)
  6696. {
  6697. var solution = a[0],
  6698. delta = a[1];
  6699. ClipperLib.Clear(solution);
  6700. this.FixOrientations();
  6701. this.DoOffset(delta);
  6702. //now clean up 'corners' ...
  6703. var clpr = new ClipperLib.Clipper(0);
  6704. clpr.AddPaths(this.m_destPolys, ClipperLib.PolyType.ptSubject, true);
  6705. if (delta > 0)
  6706. {
  6707. clpr.Execute(ClipperLib.ClipType.ctUnion, solution, ClipperLib.PolyFillType.pftPositive, ClipperLib.PolyFillType.pftPositive);
  6708. }
  6709. else
  6710. {
  6711. var r = ClipperLib.Clipper.GetBounds(this.m_destPolys);
  6712. var outer = new ClipperLib.Path();
  6713. outer.push(new ClipperLib.IntPoint2(r.left - 10, r.bottom + 10));
  6714. outer.push(new ClipperLib.IntPoint2(r.right + 10, r.bottom + 10));
  6715. outer.push(new ClipperLib.IntPoint2(r.right + 10, r.top - 10));
  6716. outer.push(new ClipperLib.IntPoint2(r.left - 10, r.top - 10));
  6717. clpr.AddPath(outer, ClipperLib.PolyType.ptSubject, true);
  6718. clpr.ReverseSolution = true;
  6719. clpr.Execute(ClipperLib.ClipType.ctUnion, solution, ClipperLib.PolyFillType.pftNegative, ClipperLib.PolyFillType.pftNegative);
  6720. if (solution.length > 0)
  6721. solution.splice(0, 1);
  6722. }
  6723. //console.log(JSON.stringify(solution));
  6724. }
  6725. else // function (polytree, delta)
  6726. {
  6727. var solution = a[0],
  6728. delta = a[1];
  6729. solution.Clear();
  6730. this.FixOrientations();
  6731. this.DoOffset(delta);
  6732. //now clean up 'corners' ...
  6733. var clpr = new ClipperLib.Clipper(0);
  6734. clpr.AddPaths(this.m_destPolys, ClipperLib.PolyType.ptSubject, true);
  6735. if (delta > 0)
  6736. {
  6737. clpr.Execute(ClipperLib.ClipType.ctUnion, solution, ClipperLib.PolyFillType.pftPositive, ClipperLib.PolyFillType.pftPositive);
  6738. }
  6739. else
  6740. {
  6741. var r = ClipperLib.Clipper.GetBounds(this.m_destPolys);
  6742. var outer = new ClipperLib.Path();
  6743. outer.push(new ClipperLib.IntPoint2(r.left - 10, r.bottom + 10));
  6744. outer.push(new ClipperLib.IntPoint2(r.right + 10, r.bottom + 10));
  6745. outer.push(new ClipperLib.IntPoint2(r.right + 10, r.top - 10));
  6746. outer.push(new ClipperLib.IntPoint2(r.left - 10, r.top - 10));
  6747. clpr.AddPath(outer, ClipperLib.PolyType.ptSubject, true);
  6748. clpr.ReverseSolution = true;
  6749. clpr.Execute(ClipperLib.ClipType.ctUnion, solution, ClipperLib.PolyFillType.pftNegative, ClipperLib.PolyFillType.pftNegative);
  6750. //remove the outer PolyNode rectangle ...
  6751. if (solution.ChildCount() === 1 && solution.Childs()[0].ChildCount() > 0)
  6752. {
  6753. var outerNode = solution.Childs()[0];
  6754. //solution.Childs.set_Capacity(outerNode.ChildCount);
  6755. solution.Childs()[0] = outerNode.Childs()[0];
  6756. solution.Childs()[0].m_Parent = solution;
  6757. for (var i = 1; i < outerNode.ChildCount(); i++)
  6758. solution.AddChild(outerNode.Childs()[i]);
  6759. }
  6760. else
  6761. solution.Clear();
  6762. }
  6763. }
  6764. };
  6765. ClipperLib.ClipperOffset.prototype.OffsetPoint = function (j, k, jointype)
  6766. {
  6767. //cross product ...
  6768. this.m_sinA = (this.m_normals[k].X * this.m_normals[j].Y - this.m_normals[j].X * this.m_normals[k].Y);
  6769. if (Math.abs(this.m_sinA * this.m_delta) < 1.0)
  6770. {
  6771. //dot product ...
  6772. var cosA = (this.m_normals[k].X * this.m_normals[j].X + this.m_normals[j].Y * this.m_normals[k].Y);
  6773. if (cosA > 0) // angle ==> 0 degrees
  6774. {
  6775. this.m_destPoly.push(new ClipperLib.IntPoint2(ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].X + this.m_normals[k].X * this.m_delta),
  6776. ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].Y + this.m_normals[k].Y * this.m_delta)));
  6777. return k;
  6778. }
  6779. //else angle ==> 180 degrees
  6780. }
  6781. else if (this.m_sinA > 1)
  6782. this.m_sinA = 1.0;
  6783. else if (this.m_sinA < -1)
  6784. this.m_sinA = -1.0;
  6785. if (this.m_sinA * this.m_delta < 0)
  6786. {
  6787. this.m_destPoly.push(new ClipperLib.IntPoint2(ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].X + this.m_normals[k].X * this.m_delta),
  6788. ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].Y + this.m_normals[k].Y * this.m_delta)));
  6789. this.m_destPoly.push(new ClipperLib.IntPoint1(this.m_srcPoly[j]));
  6790. this.m_destPoly.push(new ClipperLib.IntPoint2(ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].X + this.m_normals[j].X * this.m_delta),
  6791. ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].Y + this.m_normals[j].Y * this.m_delta)));
  6792. }
  6793. else
  6794. switch (jointype)
  6795. {
  6796. case ClipperLib.JoinType.jtMiter:
  6797. {
  6798. var r = 1 + (this.m_normals[j].X * this.m_normals[k].X + this.m_normals[j].Y * this.m_normals[k].Y);
  6799. if (r >= this.m_miterLim)
  6800. this.DoMiter(j, k, r);
  6801. else
  6802. this.DoSquare(j, k);
  6803. break;
  6804. }
  6805. case ClipperLib.JoinType.jtSquare:
  6806. this.DoSquare(j, k);
  6807. break;
  6808. case ClipperLib.JoinType.jtRound:
  6809. this.DoRound(j, k);
  6810. break;
  6811. }
  6812. k = j;
  6813. return k;
  6814. };
  6815. ClipperLib.ClipperOffset.prototype.DoSquare = function (j, k)
  6816. {
  6817. var dx = Math.tan(Math.atan2(this.m_sinA,
  6818. this.m_normals[k].X * this.m_normals[j].X + this.m_normals[k].Y * this.m_normals[j].Y) / 4);
  6819. this.m_destPoly.push(new ClipperLib.IntPoint2(
  6820. ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].X + this.m_delta * (this.m_normals[k].X - this.m_normals[k].Y * dx)),
  6821. ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].Y + this.m_delta * (this.m_normals[k].Y + this.m_normals[k].X * dx))));
  6822. this.m_destPoly.push(new ClipperLib.IntPoint2(
  6823. ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].X + this.m_delta * (this.m_normals[j].X + this.m_normals[j].Y * dx)),
  6824. ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].Y + this.m_delta * (this.m_normals[j].Y - this.m_normals[j].X * dx))));
  6825. };
  6826. ClipperLib.ClipperOffset.prototype.DoMiter = function (j, k, r)
  6827. {
  6828. var q = this.m_delta / r;
  6829. this.m_destPoly.push(new ClipperLib.IntPoint2(
  6830. ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].X + (this.m_normals[k].X + this.m_normals[j].X) * q),
  6831. ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].Y + (this.m_normals[k].Y + this.m_normals[j].Y) * q)));
  6832. };
  6833. ClipperLib.ClipperOffset.prototype.DoRound = function (j, k)
  6834. {
  6835. var a = Math.atan2(this.m_sinA,
  6836. this.m_normals[k].X * this.m_normals[j].X + this.m_normals[k].Y * this.m_normals[j].Y);
  6837. var steps = Math.max(ClipperLib.Cast_Int32(ClipperLib.ClipperOffset.Round(this.m_StepsPerRad * Math.abs(a))), 1);
  6838. var X = this.m_normals[k].X,
  6839. Y = this.m_normals[k].Y,
  6840. X2;
  6841. for (var i = 0; i < steps; ++i)
  6842. {
  6843. this.m_destPoly.push(new ClipperLib.IntPoint2(
  6844. ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].X + X * this.m_delta),
  6845. ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].Y + Y * this.m_delta)));
  6846. X2 = X;
  6847. X = X * this.m_cos - this.m_sin * Y;
  6848. Y = X2 * this.m_sin + Y * this.m_cos;
  6849. }
  6850. this.m_destPoly.push(new ClipperLib.IntPoint2(
  6851. ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].X + this.m_normals[j].X * this.m_delta),
  6852. ClipperLib.ClipperOffset.Round(this.m_srcPoly[j].Y + this.m_normals[j].Y * this.m_delta)));
  6853. };
  6854. ClipperLib.Error = function (message)
  6855. {
  6856. try
  6857. {
  6858. throw new Error(message);
  6859. }
  6860. catch (err)
  6861. {
  6862. alert(err.message);
  6863. }
  6864. };
  6865. // ---------------------------------------------
  6866. // JS extension by Timo 2013
  6867. ClipperLib.JS = {};
  6868. ClipperLib.JS.AreaOfPolygon = function (poly, scale)
  6869. {
  6870. if (!scale) scale = 1;
  6871. return ClipperLib.Clipper.Area(poly) / (scale * scale);
  6872. };
  6873. ClipperLib.JS.AreaOfPolygons = function (poly, scale)
  6874. {
  6875. if (!scale) scale = 1;
  6876. var area = 0;
  6877. for (var i = 0; i < poly.length; i++)
  6878. {
  6879. area += ClipperLib.Clipper.Area(poly[i]);
  6880. }
  6881. return area / (scale * scale);
  6882. };
  6883. ClipperLib.JS.BoundsOfPath = function (path, scale)
  6884. {
  6885. return ClipperLib.JS.BoundsOfPaths([path], scale);
  6886. };
  6887. ClipperLib.JS.BoundsOfPaths = function (paths, scale)
  6888. {
  6889. if (!scale) scale = 1;
  6890. var bounds = ClipperLib.Clipper.GetBounds(paths);
  6891. bounds.left /= scale;
  6892. bounds.bottom /= scale;
  6893. bounds.right /= scale;
  6894. bounds.top /= scale;
  6895. return bounds;
  6896. };
  6897. // Clean() joins vertices that are too near each other
  6898. // and causes distortion to offsetted polygons without cleaning
  6899. ClipperLib.JS.Clean = function (polygon, delta)
  6900. {
  6901. if (!(polygon instanceof Array)) return [];
  6902. var isPolygons = polygon[0] instanceof Array;
  6903. var polygon = ClipperLib.JS.Clone(polygon);
  6904. if (typeof delta !== "number" || delta === null)
  6905. {
  6906. ClipperLib.Error("Delta is not a number in Clean().");
  6907. return polygon;
  6908. }
  6909. if (polygon.length === 0 || (polygon.length === 1 && polygon[0].length === 0) || delta < 0) return polygon;
  6910. if (!isPolygons) polygon = [polygon];
  6911. var k_length = polygon.length;
  6912. var len, poly, result, d, p, j, i;
  6913. var results = [];
  6914. for (var k = 0; k < k_length; k++)
  6915. {
  6916. poly = polygon[k];
  6917. len = poly.length;
  6918. if (len === 0) continue;
  6919. else if (len < 3)
  6920. {
  6921. result = poly;
  6922. results.push(result);
  6923. continue;
  6924. }
  6925. result = poly;
  6926. d = delta * delta;
  6927. //d = Math.floor(c_delta * c_delta);
  6928. p = poly[0];
  6929. j = 1;
  6930. for (i = 1; i < len; i++)
  6931. {
  6932. if ((poly[i].X - p.X) * (poly[i].X - p.X) +
  6933. (poly[i].Y - p.Y) * (poly[i].Y - p.Y) <= d)
  6934. continue;
  6935. result[j] = poly[i];
  6936. p = poly[i];
  6937. j++;
  6938. }
  6939. p = poly[j - 1];
  6940. if ((poly[0].X - p.X) * (poly[0].X - p.X) +
  6941. (poly[0].Y - p.Y) * (poly[0].Y - p.Y) <= d)
  6942. j--;
  6943. if (j < len)
  6944. result.splice(j, len - j);
  6945. if (result.length) results.push(result);
  6946. }
  6947. if (!isPolygons && results.length) results = results[0];
  6948. else if (!isPolygons && results.length === 0) results = [];
  6949. else if (isPolygons && results.length === 0) results = [
  6950. []
  6951. ];
  6952. return results;
  6953. }
  6954. // Make deep copy of Polygons or Polygon
  6955. // so that also IntPoint objects are cloned and not only referenced
  6956. // This should be the fastest way
  6957. ClipperLib.JS.Clone = function (polygon)
  6958. {
  6959. if (!(polygon instanceof Array)) return [];
  6960. if (polygon.length === 0) return [];
  6961. else if (polygon.length === 1 && polygon[0].length === 0) return [
  6962. []
  6963. ];
  6964. var isPolygons = polygon[0] instanceof Array;
  6965. if (!isPolygons) polygon = [polygon];
  6966. var len = polygon.length,
  6967. plen, i, j, result;
  6968. var results = new Array(len);
  6969. for (i = 0; i < len; i++)
  6970. {
  6971. plen = polygon[i].length;
  6972. result = new Array(plen);
  6973. for (j = 0; j < plen; j++)
  6974. {
  6975. result[j] = {
  6976. X: polygon[i][j].X,
  6977. Y: polygon[i][j].Y
  6978. };
  6979. }
  6980. results[i] = result;
  6981. }
  6982. if (!isPolygons) results = results[0];
  6983. return results;
  6984. };
  6985. // Removes points that doesn't affect much to the visual appearance.
  6986. // If middle point is at or under certain distance (tolerance) of the line segment between
  6987. // start and end point, the middle point is removed.
  6988. ClipperLib.JS.Lighten = function (polygon, tolerance)
  6989. {
  6990. if (!(polygon instanceof Array)) return [];
  6991. if (typeof tolerance !== "number" || tolerance === null)
  6992. {
  6993. ClipperLib.Error("Tolerance is not a number in Lighten().")
  6994. return ClipperLib.JS.Clone(polygon);
  6995. }
  6996. if (polygon.length === 0 || (polygon.length === 1 && polygon[0].length === 0) || tolerance < 0)
  6997. {
  6998. return ClipperLib.JS.Clone(polygon);
  6999. }
  7000. var isPolygons = polygon[0] instanceof Array;
  7001. if (!isPolygons) polygon = [polygon];
  7002. var i, j, poly, k, poly2, plen, A, B, P, d, rem, addlast;
  7003. var bxax, byay, l, ax, ay;
  7004. var len = polygon.length;
  7005. var toleranceSq = tolerance * tolerance;
  7006. var results = [];
  7007. for (i = 0; i < len; i++)
  7008. {
  7009. poly = polygon[i];
  7010. plen = poly.length;
  7011. if (plen === 0) continue;
  7012. for (k = 0; k < 1000000; k++) // could be forever loop, but wiser to restrict max repeat count
  7013. {
  7014. poly2 = [];
  7015. plen = poly.length;
  7016. // the first have to added to the end, if first and last are not the same
  7017. // this way we ensure that also the actual last point can be removed if needed
  7018. if (poly[plen - 1].X !== poly[0].X || poly[plen - 1].Y !== poly[0].Y)
  7019. {
  7020. addlast = 1;
  7021. poly.push(
  7022. {
  7023. X: poly[0].X,
  7024. Y: poly[0].Y
  7025. });
  7026. plen = poly.length;
  7027. }
  7028. else addlast = 0;
  7029. rem = []; // Indexes of removed points
  7030. for (j = 0; j < plen - 2; j++)
  7031. {
  7032. A = poly[j]; // Start point of line segment
  7033. P = poly[j + 1]; // Middle point. This is the one to be removed.
  7034. B = poly[j + 2]; // End point of line segment
  7035. ax = A.X;
  7036. ay = A.Y;
  7037. bxax = B.X - ax;
  7038. byay = B.Y - ay;
  7039. if (bxax !== 0 || byay !== 0) // To avoid Nan, when A==P && P==B. And to avoid peaks (A==B && A!=P), which have lenght, but not area.
  7040. {
  7041. l = ((P.X - ax) * bxax + (P.Y - ay) * byay) / (bxax * bxax + byay * byay);
  7042. if (l > 1)
  7043. {
  7044. ax = B.X;
  7045. ay = B.Y;
  7046. }
  7047. else if (l > 0)
  7048. {
  7049. ax += bxax * l;
  7050. ay += byay * l;
  7051. }
  7052. }
  7053. bxax = P.X - ax;
  7054. byay = P.Y - ay;
  7055. d = bxax * bxax + byay * byay;
  7056. if (d <= toleranceSq)
  7057. {
  7058. rem[j + 1] = 1;
  7059. j++; // when removed, transfer the pointer to the next one
  7060. }
  7061. }
  7062. // add all unremoved points to poly2
  7063. poly2.push(
  7064. {
  7065. X: poly[0].X,
  7066. Y: poly[0].Y
  7067. });
  7068. for (j = 1; j < plen - 1; j++)
  7069. if (!rem[j]) poly2.push(
  7070. {
  7071. X: poly[j].X,
  7072. Y: poly[j].Y
  7073. });
  7074. poly2.push(
  7075. {
  7076. X: poly[plen - 1].X,
  7077. Y: poly[plen - 1].Y
  7078. });
  7079. // if the first point was added to the end, remove it
  7080. if (addlast) poly.pop();
  7081. // break, if there was not anymore removed points
  7082. if (!rem.length) break;
  7083. // else continue looping using poly2, to check if there are points to remove
  7084. else poly = poly2;
  7085. }
  7086. plen = poly2.length;
  7087. // remove duplicate from end, if needed
  7088. if (poly2[plen - 1].X === poly2[0].X && poly2[plen - 1].Y === poly2[0].Y)
  7089. {
  7090. poly2.pop();
  7091. }
  7092. if (poly2.length > 2) // to avoid two-point-polygons
  7093. results.push(poly2);
  7094. }
  7095. if (!isPolygons)
  7096. {
  7097. results = results[0];
  7098. }
  7099. if (typeof (results) === "undefined")
  7100. {
  7101. results = [];
  7102. }
  7103. return results;
  7104. }
  7105. ClipperLib.JS.PerimeterOfPath = function (path, closed, scale)
  7106. {
  7107. if (typeof (path) === "undefined") return 0;
  7108. var sqrt = Math.sqrt;
  7109. var perimeter = 0.0;
  7110. var p1, p2, p1x = 0.0,
  7111. p1y = 0.0,
  7112. p2x = 0.0,
  7113. p2y = 0.0;
  7114. var j = path.length;
  7115. if (j < 2) return 0;
  7116. if (closed)
  7117. {
  7118. path[j] = path[0];
  7119. j++;
  7120. }
  7121. while (--j)
  7122. {
  7123. p1 = path[j];
  7124. p1x = p1.X;
  7125. p1y = p1.Y;
  7126. p2 = path[j - 1];
  7127. p2x = p2.X;
  7128. p2y = p2.Y;
  7129. perimeter += sqrt((p1x - p2x) * (p1x - p2x) + (p1y - p2y) * (p1y - p2y));
  7130. }
  7131. if (closed) path.pop();
  7132. return perimeter / scale;
  7133. };
  7134. ClipperLib.JS.PerimeterOfPaths = function (paths, closed, scale)
  7135. {
  7136. if (!scale) scale = 1;
  7137. var perimeter = 0;
  7138. for (var i = 0; i < paths.length; i++)
  7139. {
  7140. perimeter += ClipperLib.JS.PerimeterOfPath(paths[i], closed, scale);
  7141. }
  7142. return perimeter;
  7143. };
  7144. ClipperLib.JS.ScaleDownPath = function (path, scale)
  7145. {
  7146. var i, p;
  7147. if (!scale) scale = 1;
  7148. i = path.length;
  7149. while (i--)
  7150. {
  7151. p = path[i];
  7152. p.X = p.X / scale;
  7153. p.Y = p.Y / scale;
  7154. }
  7155. };
  7156. ClipperLib.JS.ScaleDownPaths = function (paths, scale)
  7157. {
  7158. var i, j, p;
  7159. if (!scale) scale = 1;
  7160. i = paths.length;
  7161. while (i--)
  7162. {
  7163. j = paths[i].length;
  7164. while (j--)
  7165. {
  7166. p = paths[i][j];
  7167. p.X = p.X / scale;
  7168. p.Y = p.Y / scale;
  7169. }
  7170. }
  7171. };
  7172. ClipperLib.JS.ScaleUpPath = function (path, scale)
  7173. {
  7174. var i, p, round = Math.round;
  7175. if (!scale) scale = 1;
  7176. i = path.length;
  7177. while (i--)
  7178. {
  7179. p = path[i];
  7180. p.X = round(p.X * scale);
  7181. p.Y = round(p.Y * scale);
  7182. }
  7183. };
  7184. ClipperLib.JS.ScaleUpPaths = function (paths, scale)
  7185. {
  7186. var i, j, p, round = Math.round;
  7187. if (!scale) scale = 1;
  7188. i = paths.length;
  7189. while (i--)
  7190. {
  7191. j = paths[i].length;
  7192. while (j--)
  7193. {
  7194. p = paths[i][j];
  7195. p.X = round(p.X * scale);
  7196. p.Y = round(p.Y * scale);
  7197. }
  7198. }
  7199. };
  7200. /**
  7201. * @constructor
  7202. */
  7203. ClipperLib.ExPolygons = function ()
  7204. {
  7205. return [];
  7206. }
  7207. /**
  7208. * @constructor
  7209. */
  7210. ClipperLib.ExPolygon = function ()
  7211. {
  7212. this.outer = null;
  7213. this.holes = null;
  7214. };
  7215. ClipperLib.JS.AddOuterPolyNodeToExPolygons = function (polynode, expolygons)
  7216. {
  7217. var ep = new ClipperLib.ExPolygon();
  7218. ep.outer = polynode.Contour();
  7219. var childs = polynode.Childs();
  7220. var ilen = childs.length;
  7221. ep.holes = new Array(ilen);
  7222. var node, n, i, j, childs2, jlen;
  7223. for (i = 0; i < ilen; i++)
  7224. {
  7225. node = childs[i];
  7226. ep.holes[i] = node.Contour();
  7227. //Add outer polygons contained by (nested within) holes ...
  7228. for (j = 0, childs2 = node.Childs(), jlen = childs2.length; j < jlen; j++)
  7229. {
  7230. n = childs2[j];
  7231. ClipperLib.JS.AddOuterPolyNodeToExPolygons(n, expolygons);
  7232. }
  7233. }
  7234. expolygons.push(ep);
  7235. };
  7236. ClipperLib.JS.ExPolygonsToPaths = function (expolygons)
  7237. {
  7238. var a, i, alen, ilen;
  7239. var paths = new ClipperLib.Paths();
  7240. for (a = 0, alen = expolygons.length; a < alen; a++)
  7241. {
  7242. paths.push(expolygons[a].outer);
  7243. for (i = 0, ilen = expolygons[a].holes.length; i < ilen; i++)
  7244. {
  7245. paths.push(expolygons[a].holes[i]);
  7246. }
  7247. }
  7248. return paths;
  7249. }
  7250. ClipperLib.JS.PolyTreeToExPolygons = function (polytree)
  7251. {
  7252. var expolygons = new ClipperLib.ExPolygons();
  7253. var node, i, childs, ilen;
  7254. for (i = 0, childs = polytree.Childs(), ilen = childs.length; i < ilen; i++)
  7255. {
  7256. node = childs[i];
  7257. ClipperLib.JS.AddOuterPolyNodeToExPolygons(node, expolygons);
  7258. }
  7259. return expolygons;
  7260. };
  7261. })();