turf.js 1.4 MB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284232852328623287232882328923290232912329223293232942329523296232972329823299233002330123302233032330423305233062330723308233092331023311233122331323314233152331623317233182331923320233212332223323233242332523326233272332823329233302333123332233332333423335233362333723338233392334023341233422334323344233452334623347233482334923350233512335223353233542335523356233572335823359233602336123362233632336423365233662336723368233692337023371233722337323374233752337623377233782337923380233812338223383233842338523386233872338823389233902339123392233932339423395233962339723398233992340023401234022340323404234052340623407234082340923410234112341223413234142341523416234172341823419234202342123422234232342423425234262342723428234292343023431234322343323434234352343623437234382343923440234412344223443234442344523446234472344823449234502345123452234532345423455234562345723458234592346023461234622346323464234652346623467234682346923470234712347223473234742347523476234772347823479234802348123482234832348423485234862348723488234892349023491234922349323494234952349623497234982349923500235012350223503235042350523506235072350823509235102351123512235132351423515235162351723518235192352023521235222352323524235252352623527235282352923530235312353223533235342353523536235372353823539235402354123542235432354423545235462354723548235492355023551235522355323554235552355623557235582355923560235612356223563235642356523566235672356823569235702357123572235732357423575235762357723578235792358023581235822358323584235852358623587235882358923590235912359223593235942359523596235972359823599236002360123602236032360423605236062360723608236092361023611236122361323614236152361623617236182361923620236212362223623236242362523626236272362823629236302363123632236332363423635236362363723638236392364023641236422364323644236452364623647236482364923650236512365223653236542365523656236572365823659236602366123662236632366423665236662366723668236692367023671236722367323674236752367623677236782367923680236812368223683236842368523686236872368823689236902369123692236932369423695236962369723698236992370023701237022370323704237052370623707237082370923710237112371223713237142371523716237172371823719237202372123722237232372423725237262372723728237292373023731237322373323734237352373623737237382373923740237412374223743237442374523746237472374823749237502375123752237532375423755237562375723758237592376023761237622376323764237652376623767237682376923770237712377223773237742377523776237772377823779237802378123782237832378423785237862378723788237892379023791237922379323794237952379623797237982379923800238012380223803238042380523806238072380823809238102381123812238132381423815238162381723818238192382023821238222382323824238252382623827238282382923830238312383223833238342383523836238372383823839238402384123842238432384423845238462384723848238492385023851238522385323854238552385623857238582385923860238612386223863238642386523866238672386823869238702387123872238732387423875238762387723878238792388023881238822388323884238852388623887238882388923890238912389223893238942389523896238972389823899239002390123902239032390423905239062390723908239092391023911239122391323914239152391623917239182391923920239212392223923239242392523926239272392823929239302393123932239332393423935239362393723938239392394023941239422394323944239452394623947239482394923950239512395223953239542395523956239572395823959239602396123962239632396423965239662396723968239692397023971239722397323974239752397623977239782397923980239812398223983239842398523986239872398823989239902399123992239932399423995239962399723998239992400024001240022400324004240052400624007240082400924010240112401224013240142401524016240172401824019240202402124022240232402424025240262402724028240292403024031240322403324034240352403624037240382403924040240412404224043240442404524046240472404824049240502405124052240532405424055240562405724058240592406024061240622406324064240652406624067240682406924070240712407224073240742407524076240772407824079240802408124082240832408424085240862408724088240892409024091240922409324094240952409624097240982409924100241012410224103241042410524106241072410824109241102411124112241132411424115241162411724118241192412024121241222412324124241252412624127241282412924130241312413224133241342413524136241372413824139241402414124142241432414424145241462414724148241492415024151241522415324154241552415624157241582415924160241612416224163241642416524166241672416824169241702417124172241732417424175241762417724178241792418024181241822418324184241852418624187241882418924190241912419224193241942419524196241972419824199242002420124202242032420424205242062420724208242092421024211242122421324214242152421624217242182421924220242212422224223242242422524226242272422824229242302423124232242332423424235242362423724238242392424024241242422424324244242452424624247242482424924250242512425224253242542425524256242572425824259242602426124262242632426424265242662426724268242692427024271242722427324274242752427624277242782427924280242812428224283242842428524286242872428824289242902429124292242932429424295242962429724298242992430024301243022430324304243052430624307243082430924310243112431224313243142431524316243172431824319243202432124322243232432424325243262432724328243292433024331243322433324334243352433624337243382433924340243412434224343243442434524346243472434824349243502435124352243532435424355243562435724358243592436024361243622436324364243652436624367243682436924370243712437224373243742437524376243772437824379243802438124382243832438424385243862438724388243892439024391243922439324394243952439624397243982439924400244012440224403244042440524406244072440824409244102441124412244132441424415244162441724418244192442024421244222442324424244252442624427244282442924430244312443224433244342443524436244372443824439244402444124442244432444424445244462444724448244492445024451244522445324454244552445624457244582445924460244612446224463244642446524466244672446824469244702447124472244732447424475244762447724478244792448024481244822448324484244852448624487244882448924490244912449224493244942449524496244972449824499245002450124502245032450424505245062450724508245092451024511245122451324514245152451624517245182451924520245212452224523245242452524526245272452824529245302453124532245332453424535245362453724538245392454024541245422454324544245452454624547245482454924550245512455224553245542455524556245572455824559245602456124562245632456424565245662456724568245692457024571245722457324574245752457624577245782457924580245812458224583245842458524586245872458824589245902459124592245932459424595245962459724598245992460024601246022460324604246052460624607246082460924610246112461224613246142461524616246172461824619246202462124622246232462424625246262462724628246292463024631246322463324634246352463624637246382463924640246412464224643246442464524646246472464824649246502465124652246532465424655246562465724658246592466024661246622466324664246652466624667246682466924670246712467224673246742467524676246772467824679246802468124682246832468424685246862468724688246892469024691246922469324694246952469624697246982469924700247012470224703247042470524706247072470824709247102471124712247132471424715247162471724718247192472024721247222472324724247252472624727247282472924730247312473224733247342473524736247372473824739247402474124742247432474424745247462474724748247492475024751247522475324754247552475624757247582475924760247612476224763247642476524766247672476824769247702477124772247732477424775247762477724778247792478024781247822478324784247852478624787247882478924790247912479224793247942479524796247972479824799248002480124802248032480424805248062480724808248092481024811248122481324814248152481624817248182481924820248212482224823248242482524826248272482824829248302483124832248332483424835248362483724838248392484024841248422484324844248452484624847248482484924850248512485224853248542485524856248572485824859248602486124862248632486424865248662486724868248692487024871248722487324874248752487624877248782487924880248812488224883248842488524886248872488824889248902489124892248932489424895248962489724898248992490024901249022490324904249052490624907249082490924910249112491224913249142491524916249172491824919249202492124922249232492424925249262492724928249292493024931249322493324934249352493624937249382493924940249412494224943249442494524946249472494824949249502495124952249532495424955249562495724958249592496024961249622496324964249652496624967249682496924970249712497224973249742497524976249772497824979249802498124982249832498424985249862498724988249892499024991249922499324994249952499624997249982499925000250012500225003250042500525006250072500825009250102501125012250132501425015250162501725018250192502025021250222502325024250252502625027250282502925030250312503225033250342503525036250372503825039250402504125042250432504425045250462504725048250492505025051250522505325054250552505625057250582505925060250612506225063250642506525066250672506825069250702507125072250732507425075250762507725078250792508025081250822508325084250852508625087250882508925090250912509225093250942509525096250972509825099251002510125102251032510425105251062510725108251092511025111251122511325114251152511625117251182511925120251212512225123251242512525126251272512825129251302513125132251332513425135251362513725138251392514025141251422514325144251452514625147251482514925150251512515225153251542515525156251572515825159251602516125162251632516425165251662516725168251692517025171251722517325174251752517625177251782517925180251812518225183251842518525186251872518825189251902519125192251932519425195251962519725198251992520025201252022520325204252052520625207252082520925210252112521225213252142521525216252172521825219252202522125222252232522425225252262522725228252292523025231252322523325234252352523625237252382523925240252412524225243252442524525246252472524825249252502525125252252532525425255252562525725258252592526025261252622526325264252652526625267252682526925270252712527225273252742527525276252772527825279252802528125282252832528425285252862528725288252892529025291252922529325294252952529625297252982529925300253012530225303253042530525306253072530825309253102531125312253132531425315253162531725318253192532025321253222532325324253252532625327253282532925330253312533225333253342533525336253372533825339253402534125342253432534425345253462534725348253492535025351253522535325354253552535625357253582535925360253612536225363253642536525366253672536825369253702537125372253732537425375253762537725378253792538025381253822538325384253852538625387253882538925390253912539225393253942539525396253972539825399254002540125402254032540425405254062540725408254092541025411254122541325414254152541625417254182541925420254212542225423254242542525426254272542825429254302543125432254332543425435254362543725438254392544025441254422544325444254452544625447254482544925450254512545225453254542545525456254572545825459254602546125462254632546425465254662546725468254692547025471254722547325474254752547625477254782547925480254812548225483254842548525486254872548825489254902549125492254932549425495254962549725498254992550025501255022550325504255052550625507255082550925510255112551225513255142551525516255172551825519255202552125522255232552425525255262552725528255292553025531255322553325534255352553625537255382553925540255412554225543255442554525546255472554825549255502555125552255532555425555255562555725558255592556025561255622556325564255652556625567255682556925570255712557225573255742557525576255772557825579255802558125582255832558425585255862558725588255892559025591255922559325594255952559625597255982559925600256012560225603256042560525606256072560825609256102561125612256132561425615256162561725618256192562025621256222562325624256252562625627256282562925630256312563225633256342563525636256372563825639256402564125642256432564425645256462564725648256492565025651256522565325654256552565625657256582565925660256612566225663256642566525666256672566825669256702567125672256732567425675256762567725678256792568025681256822568325684256852568625687256882568925690256912569225693256942569525696256972569825699257002570125702257032570425705257062570725708257092571025711257122571325714257152571625717257182571925720257212572225723257242572525726257272572825729257302573125732257332573425735257362573725738257392574025741257422574325744257452574625747257482574925750257512575225753257542575525756257572575825759257602576125762257632576425765257662576725768257692577025771257722577325774257752577625777257782577925780257812578225783257842578525786257872578825789257902579125792257932579425795257962579725798257992580025801258022580325804258052580625807258082580925810258112581225813258142581525816258172581825819258202582125822258232582425825258262582725828258292583025831258322583325834258352583625837258382583925840258412584225843258442584525846258472584825849258502585125852258532585425855258562585725858258592586025861258622586325864258652586625867258682586925870258712587225873258742587525876258772587825879258802588125882258832588425885258862588725888258892589025891258922589325894258952589625897258982589925900259012590225903259042590525906259072590825909259102591125912259132591425915259162591725918259192592025921259222592325924259252592625927259282592925930259312593225933259342593525936259372593825939259402594125942259432594425945259462594725948259492595025951259522595325954259552595625957259582595925960259612596225963259642596525966259672596825969259702597125972259732597425975259762597725978259792598025981259822598325984259852598625987259882598925990259912599225993259942599525996259972599825999260002600126002260032600426005260062600726008260092601026011260122601326014260152601626017260182601926020260212602226023260242602526026260272602826029260302603126032260332603426035260362603726038260392604026041260422604326044260452604626047260482604926050260512605226053260542605526056260572605826059260602606126062260632606426065260662606726068260692607026071260722607326074260752607626077260782607926080260812608226083260842608526086260872608826089260902609126092260932609426095260962609726098260992610026101261022610326104261052610626107261082610926110261112611226113261142611526116261172611826119261202612126122261232612426125261262612726128261292613026131261322613326134261352613626137261382613926140261412614226143261442614526146261472614826149261502615126152261532615426155261562615726158261592616026161261622616326164261652616626167261682616926170261712617226173261742617526176261772617826179261802618126182261832618426185261862618726188261892619026191261922619326194261952619626197261982619926200262012620226203262042620526206262072620826209262102621126212262132621426215262162621726218262192622026221262222622326224262252622626227262282622926230262312623226233262342623526236262372623826239262402624126242262432624426245262462624726248262492625026251262522625326254262552625626257262582625926260262612626226263262642626526266262672626826269262702627126272262732627426275262762627726278262792628026281262822628326284262852628626287262882628926290262912629226293262942629526296262972629826299263002630126302263032630426305263062630726308263092631026311263122631326314263152631626317263182631926320263212632226323263242632526326263272632826329263302633126332263332633426335263362633726338263392634026341263422634326344263452634626347263482634926350263512635226353263542635526356263572635826359263602636126362263632636426365263662636726368263692637026371263722637326374263752637626377263782637926380263812638226383263842638526386263872638826389263902639126392263932639426395263962639726398263992640026401264022640326404264052640626407264082640926410264112641226413264142641526416264172641826419264202642126422264232642426425264262642726428264292643026431264322643326434264352643626437264382643926440264412644226443264442644526446264472644826449264502645126452264532645426455264562645726458264592646026461264622646326464264652646626467264682646926470264712647226473264742647526476264772647826479264802648126482264832648426485264862648726488264892649026491264922649326494264952649626497264982649926500265012650226503265042650526506265072650826509265102651126512265132651426515265162651726518265192652026521265222652326524265252652626527265282652926530265312653226533265342653526536265372653826539265402654126542265432654426545265462654726548265492655026551265522655326554265552655626557265582655926560265612656226563265642656526566265672656826569265702657126572265732657426575265762657726578265792658026581265822658326584265852658626587265882658926590265912659226593265942659526596265972659826599266002660126602266032660426605266062660726608266092661026611266122661326614266152661626617266182661926620266212662226623266242662526626266272662826629266302663126632266332663426635266362663726638266392664026641266422664326644266452664626647266482664926650266512665226653266542665526656266572665826659266602666126662266632666426665266662666726668266692667026671266722667326674266752667626677266782667926680266812668226683266842668526686266872668826689266902669126692266932669426695266962669726698266992670026701267022670326704267052670626707267082670926710267112671226713267142671526716267172671826719267202672126722267232672426725267262672726728267292673026731267322673326734267352673626737267382673926740267412674226743267442674526746267472674826749267502675126752267532675426755267562675726758267592676026761267622676326764267652676626767267682676926770267712677226773267742677526776267772677826779267802678126782267832678426785267862678726788267892679026791267922679326794267952679626797267982679926800268012680226803268042680526806268072680826809268102681126812268132681426815268162681726818268192682026821268222682326824268252682626827268282682926830268312683226833268342683526836268372683826839268402684126842268432684426845268462684726848268492685026851268522685326854268552685626857268582685926860268612686226863268642686526866268672686826869268702687126872268732687426875268762687726878268792688026881268822688326884268852688626887268882688926890268912689226893268942689526896268972689826899269002690126902269032690426905269062690726908269092691026911269122691326914269152691626917269182691926920269212692226923269242692526926269272692826929269302693126932269332693426935269362693726938269392694026941269422694326944269452694626947269482694926950269512695226953269542695526956269572695826959269602696126962269632696426965269662696726968269692697026971269722697326974269752697626977269782697926980269812698226983269842698526986269872698826989269902699126992269932699426995269962699726998269992700027001270022700327004270052700627007270082700927010270112701227013270142701527016270172701827019270202702127022270232702427025270262702727028270292703027031270322703327034270352703627037270382703927040270412704227043270442704527046270472704827049270502705127052270532705427055270562705727058270592706027061270622706327064270652706627067270682706927070270712707227073270742707527076270772707827079270802708127082270832708427085270862708727088270892709027091270922709327094270952709627097270982709927100271012710227103271042710527106271072710827109271102711127112271132711427115271162711727118271192712027121271222712327124271252712627127271282712927130271312713227133271342713527136271372713827139271402714127142271432714427145271462714727148271492715027151271522715327154271552715627157271582715927160271612716227163271642716527166271672716827169271702717127172271732717427175271762717727178271792718027181271822718327184271852718627187271882718927190271912719227193271942719527196271972719827199272002720127202272032720427205272062720727208272092721027211272122721327214272152721627217272182721927220272212722227223272242722527226272272722827229272302723127232272332723427235272362723727238272392724027241272422724327244272452724627247272482724927250272512725227253272542725527256272572725827259272602726127262272632726427265272662726727268272692727027271272722727327274272752727627277272782727927280272812728227283272842728527286272872728827289272902729127292272932729427295272962729727298272992730027301273022730327304273052730627307273082730927310273112731227313273142731527316273172731827319273202732127322273232732427325273262732727328273292733027331273322733327334273352733627337273382733927340273412734227343273442734527346273472734827349273502735127352273532735427355273562735727358273592736027361273622736327364273652736627367273682736927370273712737227373273742737527376273772737827379273802738127382273832738427385273862738727388273892739027391273922739327394273952739627397273982739927400274012740227403274042740527406274072740827409274102741127412274132741427415274162741727418274192742027421274222742327424274252742627427274282742927430274312743227433274342743527436274372743827439274402744127442274432744427445274462744727448274492745027451274522745327454274552745627457274582745927460274612746227463274642746527466274672746827469274702747127472274732747427475274762747727478274792748027481274822748327484274852748627487274882748927490274912749227493274942749527496274972749827499275002750127502275032750427505275062750727508275092751027511275122751327514275152751627517275182751927520275212752227523275242752527526275272752827529275302753127532275332753427535275362753727538275392754027541275422754327544275452754627547275482754927550275512755227553275542755527556275572755827559275602756127562275632756427565275662756727568275692757027571275722757327574275752757627577275782757927580275812758227583275842758527586275872758827589275902759127592275932759427595275962759727598275992760027601276022760327604276052760627607276082760927610276112761227613276142761527616276172761827619276202762127622276232762427625276262762727628276292763027631276322763327634276352763627637276382763927640276412764227643276442764527646276472764827649276502765127652276532765427655276562765727658276592766027661276622766327664276652766627667276682766927670276712767227673276742767527676276772767827679276802768127682276832768427685276862768727688276892769027691276922769327694276952769627697276982769927700277012770227703277042770527706277072770827709277102771127712277132771427715277162771727718277192772027721277222772327724277252772627727277282772927730277312773227733277342773527736277372773827739277402774127742277432774427745277462774727748277492775027751277522775327754277552775627757277582775927760277612776227763277642776527766277672776827769277702777127772277732777427775277762777727778277792778027781277822778327784277852778627787277882778927790277912779227793277942779527796277972779827799278002780127802278032780427805278062780727808278092781027811278122781327814278152781627817278182781927820278212782227823278242782527826278272782827829278302783127832278332783427835278362783727838278392784027841278422784327844278452784627847278482784927850278512785227853278542785527856278572785827859278602786127862278632786427865278662786727868278692787027871278722787327874278752787627877278782787927880278812788227883278842788527886278872788827889278902789127892278932789427895278962789727898278992790027901279022790327904279052790627907279082790927910279112791227913279142791527916279172791827919279202792127922279232792427925279262792727928279292793027931279322793327934279352793627937279382793927940279412794227943279442794527946279472794827949279502795127952279532795427955279562795727958279592796027961279622796327964279652796627967279682796927970279712797227973279742797527976279772797827979279802798127982279832798427985279862798727988279892799027991279922799327994279952799627997279982799928000280012800228003280042800528006280072800828009280102801128012280132801428015280162801728018280192802028021280222802328024280252802628027280282802928030280312803228033280342803528036280372803828039280402804128042280432804428045280462804728048280492805028051280522805328054280552805628057280582805928060280612806228063280642806528066280672806828069280702807128072280732807428075280762807728078280792808028081280822808328084280852808628087280882808928090280912809228093280942809528096280972809828099281002810128102281032810428105281062810728108281092811028111281122811328114281152811628117281182811928120281212812228123281242812528126281272812828129281302813128132281332813428135281362813728138281392814028141281422814328144281452814628147281482814928150281512815228153281542815528156281572815828159281602816128162281632816428165281662816728168281692817028171281722817328174281752817628177281782817928180281812818228183281842818528186281872818828189281902819128192281932819428195281962819728198281992820028201282022820328204282052820628207282082820928210282112821228213282142821528216282172821828219282202822128222282232822428225282262822728228282292823028231282322823328234282352823628237282382823928240282412824228243282442824528246282472824828249282502825128252282532825428255282562825728258282592826028261282622826328264282652826628267282682826928270282712827228273282742827528276282772827828279282802828128282282832828428285282862828728288282892829028291282922829328294282952829628297282982829928300283012830228303283042830528306283072830828309283102831128312283132831428315283162831728318283192832028321283222832328324283252832628327283282832928330283312833228333283342833528336283372833828339283402834128342283432834428345283462834728348283492835028351283522835328354283552835628357283582835928360283612836228363283642836528366283672836828369283702837128372283732837428375283762837728378283792838028381283822838328384283852838628387283882838928390283912839228393283942839528396283972839828399284002840128402284032840428405284062840728408284092841028411284122841328414284152841628417284182841928420284212842228423284242842528426284272842828429284302843128432284332843428435284362843728438284392844028441284422844328444284452844628447284482844928450284512845228453284542845528456284572845828459284602846128462284632846428465284662846728468284692847028471284722847328474284752847628477284782847928480284812848228483284842848528486284872848828489284902849128492284932849428495284962849728498284992850028501285022850328504285052850628507285082850928510285112851228513285142851528516285172851828519285202852128522285232852428525285262852728528285292853028531285322853328534285352853628537285382853928540285412854228543285442854528546285472854828549285502855128552285532855428555285562855728558285592856028561285622856328564285652856628567285682856928570285712857228573285742857528576285772857828579285802858128582285832858428585285862858728588285892859028591285922859328594285952859628597285982859928600286012860228603286042860528606286072860828609286102861128612286132861428615286162861728618286192862028621286222862328624286252862628627286282862928630286312863228633286342863528636286372863828639286402864128642286432864428645286462864728648286492865028651286522865328654286552865628657286582865928660286612866228663286642866528666286672866828669286702867128672286732867428675286762867728678286792868028681286822868328684286852868628687286882868928690286912869228693286942869528696286972869828699287002870128702287032870428705287062870728708287092871028711287122871328714287152871628717287182871928720287212872228723287242872528726287272872828729287302873128732287332873428735287362873728738287392874028741287422874328744287452874628747287482874928750287512875228753287542875528756287572875828759287602876128762287632876428765287662876728768287692877028771287722877328774287752877628777287782877928780287812878228783287842878528786287872878828789287902879128792287932879428795287962879728798287992880028801288022880328804288052880628807288082880928810288112881228813288142881528816288172881828819288202882128822288232882428825288262882728828288292883028831288322883328834288352883628837288382883928840288412884228843288442884528846288472884828849288502885128852288532885428855288562885728858288592886028861288622886328864288652886628867288682886928870288712887228873288742887528876288772887828879288802888128882288832888428885288862888728888288892889028891288922889328894288952889628897288982889928900289012890228903289042890528906289072890828909289102891128912289132891428915289162891728918289192892028921289222892328924289252892628927289282892928930289312893228933289342893528936289372893828939289402894128942289432894428945289462894728948289492895028951289522895328954289552895628957289582895928960289612896228963289642896528966289672896828969289702897128972289732897428975289762897728978289792898028981289822898328984289852898628987289882898928990289912899228993289942899528996289972899828999290002900129002290032900429005290062900729008290092901029011290122901329014290152901629017290182901929020290212902229023290242902529026290272902829029290302903129032290332903429035290362903729038290392904029041290422904329044290452904629047290482904929050290512905229053290542905529056290572905829059290602906129062290632906429065290662906729068290692907029071290722907329074290752907629077290782907929080290812908229083290842908529086290872908829089290902909129092290932909429095290962909729098290992910029101291022910329104291052910629107291082910929110291112911229113291142911529116291172911829119291202912129122291232912429125291262912729128291292913029131291322913329134291352913629137291382913929140291412914229143291442914529146291472914829149291502915129152291532915429155291562915729158291592916029161291622916329164291652916629167291682916929170291712917229173291742917529176291772917829179291802918129182291832918429185291862918729188291892919029191291922919329194291952919629197291982919929200292012920229203292042920529206292072920829209292102921129212292132921429215292162921729218292192922029221292222922329224292252922629227292282922929230292312923229233292342923529236292372923829239292402924129242292432924429245292462924729248292492925029251292522925329254292552925629257292582925929260292612926229263292642926529266292672926829269292702927129272292732927429275292762927729278292792928029281292822928329284292852928629287292882928929290292912929229293292942929529296292972929829299293002930129302293032930429305293062930729308293092931029311293122931329314293152931629317293182931929320293212932229323293242932529326293272932829329293302933129332293332933429335293362933729338293392934029341293422934329344293452934629347293482934929350293512935229353293542935529356293572935829359293602936129362293632936429365293662936729368293692937029371293722937329374293752937629377293782937929380293812938229383293842938529386293872938829389293902939129392293932939429395293962939729398293992940029401294022940329404294052940629407294082940929410294112941229413294142941529416294172941829419294202942129422294232942429425294262942729428294292943029431294322943329434294352943629437294382943929440294412944229443294442944529446294472944829449294502945129452294532945429455294562945729458294592946029461294622946329464294652946629467294682946929470294712947229473294742947529476294772947829479294802948129482294832948429485294862948729488294892949029491294922949329494294952949629497294982949929500295012950229503295042950529506295072950829509295102951129512295132951429515295162951729518295192952029521295222952329524295252952629527295282952929530295312953229533295342953529536295372953829539295402954129542295432954429545295462954729548295492955029551295522955329554295552955629557295582955929560295612956229563295642956529566295672956829569295702957129572295732957429575295762957729578295792958029581295822958329584295852958629587295882958929590295912959229593295942959529596295972959829599296002960129602296032960429605296062960729608296092961029611296122961329614296152961629617296182961929620296212962229623296242962529626296272962829629296302963129632296332963429635296362963729638296392964029641296422964329644296452964629647296482964929650296512965229653296542965529656296572965829659296602966129662296632966429665296662966729668296692967029671296722967329674296752967629677296782967929680296812968229683296842968529686296872968829689296902969129692296932969429695296962969729698296992970029701297022970329704297052970629707297082970929710297112971229713297142971529716297172971829719297202972129722297232972429725297262972729728297292973029731297322973329734297352973629737297382973929740297412974229743297442974529746297472974829749297502975129752297532975429755297562975729758297592976029761297622976329764297652976629767297682976929770297712977229773297742977529776297772977829779297802978129782297832978429785297862978729788297892979029791297922979329794297952979629797297982979929800298012980229803298042980529806298072980829809298102981129812298132981429815298162981729818298192982029821298222982329824298252982629827298282982929830298312983229833298342983529836298372983829839298402984129842298432984429845298462984729848298492985029851298522985329854298552985629857298582985929860298612986229863298642986529866298672986829869298702987129872298732987429875298762987729878298792988029881298822988329884298852988629887298882988929890298912989229893298942989529896298972989829899299002990129902299032990429905299062990729908299092991029911299122991329914299152991629917299182991929920299212992229923299242992529926299272992829929299302993129932299332993429935299362993729938299392994029941299422994329944299452994629947299482994929950299512995229953299542995529956299572995829959299602996129962299632996429965299662996729968299692997029971299722997329974299752997629977299782997929980299812998229983299842998529986299872998829989299902999129992299932999429995299962999729998299993000030001300023000330004300053000630007300083000930010300113001230013300143001530016300173001830019300203002130022300233002430025300263002730028300293003030031300323003330034300353003630037300383003930040300413004230043300443004530046300473004830049300503005130052300533005430055300563005730058300593006030061300623006330064300653006630067300683006930070300713007230073300743007530076300773007830079300803008130082300833008430085300863008730088300893009030091300923009330094300953009630097300983009930100301013010230103301043010530106301073010830109301103011130112301133011430115301163011730118301193012030121301223012330124301253012630127301283012930130301313013230133301343013530136301373013830139301403014130142301433014430145301463014730148301493015030151301523015330154301553015630157301583015930160301613016230163301643016530166301673016830169301703017130172301733017430175301763017730178301793018030181301823018330184301853018630187301883018930190301913019230193301943019530196301973019830199302003020130202302033020430205302063020730208302093021030211302123021330214302153021630217302183021930220302213022230223302243022530226302273022830229302303023130232302333023430235302363023730238302393024030241302423024330244302453024630247302483024930250302513025230253302543025530256302573025830259302603026130262302633026430265302663026730268302693027030271302723027330274302753027630277302783027930280302813028230283302843028530286302873028830289302903029130292302933029430295302963029730298302993030030301303023030330304303053030630307303083030930310303113031230313303143031530316303173031830319303203032130322303233032430325303263032730328303293033030331303323033330334303353033630337303383033930340303413034230343303443034530346303473034830349303503035130352303533035430355303563035730358303593036030361303623036330364303653036630367303683036930370303713037230373303743037530376303773037830379303803038130382303833038430385303863038730388303893039030391303923039330394303953039630397303983039930400304013040230403304043040530406304073040830409304103041130412304133041430415304163041730418304193042030421304223042330424304253042630427304283042930430304313043230433304343043530436304373043830439304403044130442304433044430445304463044730448304493045030451304523045330454304553045630457304583045930460304613046230463304643046530466304673046830469304703047130472304733047430475304763047730478304793048030481304823048330484304853048630487304883048930490304913049230493304943049530496304973049830499305003050130502305033050430505305063050730508305093051030511305123051330514305153051630517305183051930520305213052230523305243052530526305273052830529305303053130532305333053430535305363053730538305393054030541305423054330544305453054630547305483054930550305513055230553305543055530556305573055830559305603056130562305633056430565305663056730568305693057030571305723057330574305753057630577305783057930580305813058230583305843058530586305873058830589305903059130592305933059430595305963059730598305993060030601306023060330604306053060630607306083060930610306113061230613306143061530616306173061830619306203062130622306233062430625306263062730628306293063030631306323063330634306353063630637306383063930640306413064230643306443064530646306473064830649306503065130652306533065430655306563065730658306593066030661306623066330664306653066630667306683066930670306713067230673306743067530676306773067830679306803068130682306833068430685306863068730688306893069030691306923069330694306953069630697306983069930700307013070230703307043070530706307073070830709307103071130712307133071430715307163071730718307193072030721307223072330724307253072630727307283072930730307313073230733307343073530736307373073830739307403074130742307433074430745307463074730748307493075030751307523075330754307553075630757307583075930760307613076230763307643076530766307673076830769307703077130772307733077430775307763077730778307793078030781307823078330784307853078630787307883078930790307913079230793307943079530796307973079830799308003080130802308033080430805308063080730808308093081030811308123081330814308153081630817308183081930820308213082230823308243082530826308273082830829308303083130832308333083430835308363083730838308393084030841308423084330844308453084630847308483084930850308513085230853308543085530856308573085830859308603086130862308633086430865308663086730868308693087030871308723087330874308753087630877308783087930880308813088230883308843088530886308873088830889308903089130892308933089430895308963089730898308993090030901309023090330904309053090630907309083090930910309113091230913309143091530916309173091830919309203092130922309233092430925309263092730928309293093030931309323093330934309353093630937309383093930940309413094230943309443094530946309473094830949309503095130952309533095430955309563095730958309593096030961309623096330964309653096630967309683096930970309713097230973309743097530976309773097830979309803098130982309833098430985309863098730988309893099030991309923099330994309953099630997309983099931000310013100231003310043100531006310073100831009310103101131012310133101431015310163101731018310193102031021310223102331024310253102631027310283102931030310313103231033310343103531036310373103831039310403104131042310433104431045310463104731048310493105031051310523105331054310553105631057310583105931060310613106231063310643106531066310673106831069310703107131072310733107431075310763107731078310793108031081310823108331084310853108631087310883108931090310913109231093310943109531096310973109831099311003110131102311033110431105311063110731108311093111031111311123111331114311153111631117311183111931120311213112231123311243112531126311273112831129311303113131132311333113431135311363113731138311393114031141311423114331144311453114631147311483114931150311513115231153311543115531156311573115831159311603116131162311633116431165311663116731168311693117031171311723117331174311753117631177311783117931180311813118231183311843118531186311873118831189311903119131192311933119431195311963119731198311993120031201312023120331204312053120631207312083120931210312113121231213312143121531216312173121831219312203122131222312233122431225312263122731228312293123031231312323123331234312353123631237312383123931240312413124231243312443124531246312473124831249312503125131252312533125431255312563125731258312593126031261312623126331264312653126631267312683126931270312713127231273312743127531276312773127831279312803128131282312833128431285312863128731288312893129031291312923129331294312953129631297312983129931300313013130231303313043130531306313073130831309313103131131312313133131431315313163131731318313193132031321313223132331324313253132631327313283132931330313313133231333313343133531336313373133831339313403134131342313433134431345313463134731348313493135031351313523135331354313553135631357313583135931360313613136231363313643136531366313673136831369313703137131372313733137431375313763137731378313793138031381313823138331384313853138631387313883138931390313913139231393313943139531396313973139831399314003140131402314033140431405314063140731408314093141031411314123141331414314153141631417314183141931420314213142231423314243142531426314273142831429314303143131432314333143431435314363143731438314393144031441314423144331444314453144631447314483144931450314513145231453314543145531456314573145831459314603146131462314633146431465314663146731468314693147031471314723147331474314753147631477314783147931480314813148231483314843148531486314873148831489314903149131492314933149431495314963149731498314993150031501315023150331504315053150631507315083150931510315113151231513315143151531516315173151831519315203152131522315233152431525315263152731528315293153031531315323153331534315353153631537315383153931540315413154231543315443154531546315473154831549315503155131552315533155431555315563155731558315593156031561315623156331564315653156631567315683156931570315713157231573315743157531576315773157831579315803158131582315833158431585315863158731588315893159031591315923159331594315953159631597315983159931600316013160231603316043160531606316073160831609316103161131612316133161431615316163161731618316193162031621316223162331624316253162631627316283162931630316313163231633316343163531636316373163831639316403164131642316433164431645316463164731648316493165031651316523165331654316553165631657316583165931660316613166231663316643166531666316673166831669316703167131672316733167431675316763167731678316793168031681316823168331684316853168631687316883168931690316913169231693316943169531696316973169831699317003170131702317033170431705317063170731708317093171031711317123171331714317153171631717317183171931720317213172231723317243172531726317273172831729317303173131732317333173431735317363173731738317393174031741317423174331744317453174631747317483174931750317513175231753317543175531756317573175831759317603176131762317633176431765317663176731768317693177031771317723177331774317753177631777317783177931780317813178231783317843178531786317873178831789317903179131792317933179431795317963179731798317993180031801318023180331804318053180631807318083180931810318113181231813318143181531816318173181831819318203182131822318233182431825318263182731828318293183031831318323183331834318353183631837318383183931840318413184231843318443184531846318473184831849318503185131852318533185431855318563185731858318593186031861318623186331864318653186631867318683186931870318713187231873318743187531876318773187831879318803188131882318833188431885318863188731888318893189031891318923189331894318953189631897318983189931900319013190231903319043190531906319073190831909319103191131912319133191431915319163191731918319193192031921319223192331924319253192631927319283192931930319313193231933319343193531936319373193831939319403194131942319433194431945319463194731948319493195031951319523195331954319553195631957319583195931960319613196231963319643196531966319673196831969319703197131972319733197431975319763197731978319793198031981319823198331984319853198631987319883198931990319913199231993319943199531996319973199831999320003200132002320033200432005320063200732008320093201032011320123201332014320153201632017320183201932020320213202232023320243202532026320273202832029320303203132032320333203432035320363203732038320393204032041320423204332044320453204632047320483204932050320513205232053320543205532056320573205832059320603206132062320633206432065320663206732068320693207032071320723207332074320753207632077320783207932080320813208232083320843208532086320873208832089320903209132092320933209432095320963209732098320993210032101321023210332104321053210632107321083210932110321113211232113321143211532116321173211832119321203212132122321233212432125321263212732128321293213032131321323213332134321353213632137321383213932140321413214232143321443214532146321473214832149321503215132152321533215432155321563215732158321593216032161321623216332164321653216632167321683216932170321713217232173321743217532176321773217832179321803218132182321833218432185321863218732188321893219032191321923219332194321953219632197321983219932200322013220232203322043220532206322073220832209322103221132212322133221432215322163221732218322193222032221322223222332224322253222632227322283222932230322313223232233322343223532236322373223832239322403224132242322433224432245322463224732248322493225032251322523225332254322553225632257322583225932260322613226232263322643226532266322673226832269322703227132272322733227432275322763227732278322793228032281322823228332284322853228632287322883228932290322913229232293322943229532296322973229832299323003230132302323033230432305323063230732308323093231032311323123231332314323153231632317323183231932320323213232232323323243232532326323273232832329323303233132332323333233432335323363233732338323393234032341323423234332344323453234632347323483234932350323513235232353323543235532356323573235832359323603236132362323633236432365323663236732368323693237032371323723237332374323753237632377323783237932380323813238232383323843238532386323873238832389323903239132392323933239432395323963239732398323993240032401324023240332404324053240632407324083240932410324113241232413324143241532416324173241832419324203242132422324233242432425324263242732428324293243032431324323243332434324353243632437324383243932440324413244232443324443244532446324473244832449324503245132452324533245432455324563245732458324593246032461324623246332464324653246632467324683246932470324713247232473324743247532476324773247832479324803248132482324833248432485324863248732488324893249032491324923249332494324953249632497324983249932500325013250232503325043250532506325073250832509325103251132512325133251432515325163251732518325193252032521325223252332524325253252632527325283252932530325313253232533325343253532536325373253832539325403254132542325433254432545325463254732548325493255032551325523255332554325553255632557325583255932560325613256232563325643256532566325673256832569325703257132572325733257432575325763257732578325793258032581325823258332584325853258632587325883258932590325913259232593325943259532596325973259832599326003260132602326033260432605326063260732608326093261032611326123261332614326153261632617326183261932620326213262232623326243262532626326273262832629326303263132632326333263432635326363263732638326393264032641326423264332644326453264632647326483264932650326513265232653326543265532656326573265832659326603266132662326633266432665326663266732668326693267032671326723267332674326753267632677326783267932680326813268232683326843268532686326873268832689326903269132692326933269432695326963269732698326993270032701327023270332704327053270632707327083270932710327113271232713327143271532716327173271832719327203272132722327233272432725327263272732728327293273032731327323273332734327353273632737327383273932740327413274232743327443274532746327473274832749327503275132752327533275432755327563275732758327593276032761327623276332764327653276632767327683276932770327713277232773327743277532776327773277832779327803278132782327833278432785327863278732788327893279032791327923279332794327953279632797327983279932800328013280232803328043280532806328073280832809328103281132812328133281432815328163281732818328193282032821328223282332824328253282632827328283282932830328313283232833328343283532836328373283832839328403284132842328433284432845328463284732848328493285032851328523285332854328553285632857328583285932860328613286232863328643286532866328673286832869328703287132872328733287432875328763287732878328793288032881328823288332884328853288632887328883288932890328913289232893328943289532896328973289832899329003290132902329033290432905329063290732908329093291032911329123291332914329153291632917329183291932920329213292232923329243292532926329273292832929329303293132932329333293432935329363293732938329393294032941329423294332944329453294632947329483294932950329513295232953329543295532956329573295832959329603296132962329633296432965329663296732968329693297032971329723297332974329753297632977329783297932980329813298232983329843298532986329873298832989329903299132992329933299432995329963299732998329993300033001330023300333004330053300633007330083300933010330113301233013330143301533016330173301833019330203302133022330233302433025330263302733028330293303033031330323303333034330353303633037330383303933040330413304233043330443304533046330473304833049330503305133052330533305433055330563305733058330593306033061330623306333064330653306633067330683306933070330713307233073330743307533076330773307833079330803308133082330833308433085330863308733088330893309033091330923309333094330953309633097330983309933100331013310233103331043310533106331073310833109331103311133112331133311433115331163311733118331193312033121331223312333124331253312633127331283312933130331313313233133331343313533136331373313833139331403314133142331433314433145331463314733148331493315033151331523315333154331553315633157331583315933160331613316233163331643316533166331673316833169331703317133172331733317433175331763317733178331793318033181331823318333184331853318633187331883318933190331913319233193331943319533196331973319833199332003320133202332033320433205332063320733208332093321033211332123321333214332153321633217332183321933220332213322233223332243322533226332273322833229332303323133232332333323433235332363323733238332393324033241332423324333244332453324633247332483324933250332513325233253332543325533256332573325833259332603326133262332633326433265332663326733268332693327033271332723327333274332753327633277332783327933280332813328233283332843328533286332873328833289332903329133292332933329433295332963329733298332993330033301333023330333304333053330633307333083330933310333113331233313333143331533316333173331833319333203332133322333233332433325333263332733328333293333033331333323333333334333353333633337333383333933340333413334233343333443334533346333473334833349333503335133352333533335433355333563335733358333593336033361333623336333364333653336633367333683336933370333713337233373333743337533376333773337833379333803338133382333833338433385333863338733388333893339033391333923339333394333953339633397333983339933400334013340233403334043340533406334073340833409334103341133412334133341433415334163341733418334193342033421334223342333424334253342633427334283342933430334313343233433334343343533436334373343833439334403344133442334433344433445334463344733448334493345033451334523345333454334553345633457334583345933460334613346233463334643346533466334673346833469334703347133472334733347433475334763347733478334793348033481334823348333484334853348633487334883348933490334913349233493334943349533496334973349833499335003350133502335033350433505335063350733508335093351033511335123351333514335153351633517335183351933520335213352233523335243352533526335273352833529335303353133532335333353433535335363353733538335393354033541335423354333544335453354633547335483354933550335513355233553335543355533556335573355833559335603356133562335633356433565335663356733568335693357033571335723357333574335753357633577335783357933580335813358233583335843358533586335873358833589335903359133592335933359433595335963359733598335993360033601336023360333604336053360633607336083360933610336113361233613336143361533616336173361833619336203362133622336233362433625336263362733628336293363033631336323363333634336353363633637336383363933640336413364233643336443364533646336473364833649336503365133652336533365433655336563365733658336593366033661336623366333664336653366633667336683366933670336713367233673336743367533676336773367833679336803368133682336833368433685336863368733688336893369033691336923369333694336953369633697336983369933700337013370233703337043370533706337073370833709337103371133712337133371433715337163371733718337193372033721337223372333724337253372633727337283372933730337313373233733337343373533736337373373833739337403374133742337433374433745337463374733748337493375033751337523375333754337553375633757337583375933760337613376233763337643376533766337673376833769337703377133772337733377433775337763377733778337793378033781337823378333784337853378633787337883378933790337913379233793337943379533796337973379833799338003380133802338033380433805338063380733808338093381033811338123381333814338153381633817338183381933820338213382233823338243382533826338273382833829338303383133832338333383433835338363383733838338393384033841338423384333844338453384633847338483384933850338513385233853338543385533856338573385833859338603386133862338633386433865338663386733868338693387033871338723387333874338753387633877338783387933880338813388233883338843388533886338873388833889338903389133892338933389433895338963389733898338993390033901339023390333904339053390633907339083390933910339113391233913339143391533916339173391833919339203392133922339233392433925339263392733928339293393033931339323393333934339353393633937339383393933940339413394233943339443394533946339473394833949339503395133952339533395433955339563395733958339593396033961339623396333964339653396633967339683396933970339713397233973339743397533976339773397833979339803398133982339833398433985339863398733988339893399033991339923399333994339953399633997339983399934000340013400234003340043400534006340073400834009340103401134012340133401434015340163401734018340193402034021340223402334024340253402634027340283402934030340313403234033340343403534036340373403834039340403404134042340433404434045340463404734048340493405034051340523405334054340553405634057340583405934060340613406234063340643406534066340673406834069340703407134072340733407434075340763407734078340793408034081340823408334084340853408634087340883408934090340913409234093340943409534096340973409834099341003410134102341033410434105341063410734108341093411034111341123411334114341153411634117341183411934120341213412234123341243412534126341273412834129341303413134132341333413434135341363413734138341393414034141341423414334144341453414634147341483414934150341513415234153341543415534156341573415834159341603416134162341633416434165341663416734168341693417034171341723417334174341753417634177341783417934180341813418234183341843418534186341873418834189341903419134192341933419434195341963419734198341993420034201342023420334204342053420634207342083420934210342113421234213342143421534216342173421834219342203422134222342233422434225342263422734228342293423034231342323423334234342353423634237342383423934240342413424234243342443424534246342473424834249342503425134252342533425434255342563425734258342593426034261342623426334264342653426634267342683426934270342713427234273342743427534276342773427834279342803428134282342833428434285342863428734288342893429034291342923429334294342953429634297342983429934300343013430234303343043430534306343073430834309343103431134312343133431434315343163431734318343193432034321343223432334324343253432634327343283432934330343313433234333343343433534336343373433834339343403434134342343433434434345343463434734348343493435034351343523435334354343553435634357343583435934360343613436234363343643436534366343673436834369343703437134372343733437434375343763437734378343793438034381343823438334384343853438634387343883438934390343913439234393343943439534396343973439834399344003440134402344033440434405344063440734408344093441034411344123441334414344153441634417344183441934420344213442234423344243442534426344273442834429344303443134432344333443434435344363443734438344393444034441344423444334444344453444634447344483444934450344513445234453344543445534456344573445834459344603446134462344633446434465344663446734468344693447034471344723447334474344753447634477344783447934480344813448234483344843448534486344873448834489344903449134492344933449434495344963449734498344993450034501345023450334504345053450634507345083450934510345113451234513345143451534516345173451834519345203452134522345233452434525345263452734528345293453034531345323453334534345353453634537345383453934540345413454234543345443454534546345473454834549345503455134552345533455434555345563455734558345593456034561345623456334564345653456634567345683456934570345713457234573345743457534576345773457834579345803458134582345833458434585345863458734588345893459034591345923459334594345953459634597345983459934600346013460234603346043460534606346073460834609346103461134612346133461434615346163461734618346193462034621346223462334624346253462634627346283462934630346313463234633346343463534636346373463834639346403464134642346433464434645346463464734648346493465034651346523465334654346553465634657346583465934660346613466234663346643466534666346673466834669346703467134672346733467434675346763467734678346793468034681346823468334684346853468634687346883468934690346913469234693346943469534696346973469834699347003470134702347033470434705347063470734708347093471034711347123471334714347153471634717347183471934720347213472234723347243472534726347273472834729347303473134732347333473434735347363473734738347393474034741347423474334744347453474634747347483474934750347513475234753347543475534756347573475834759347603476134762347633476434765347663476734768347693477034771347723477334774347753477634777347783477934780347813478234783347843478534786347873478834789347903479134792347933479434795347963479734798347993480034801348023480334804348053480634807348083480934810348113481234813348143481534816348173481834819348203482134822348233482434825348263482734828348293483034831348323483334834348353483634837348383483934840348413484234843348443484534846348473484834849348503485134852348533485434855348563485734858348593486034861348623486334864348653486634867348683486934870348713487234873348743487534876348773487834879348803488134882348833488434885348863488734888348893489034891348923489334894348953489634897348983489934900349013490234903349043490534906349073490834909349103491134912349133491434915349163491734918349193492034921349223492334924349253492634927349283492934930349313493234933349343493534936349373493834939349403494134942349433494434945349463494734948349493495034951349523495334954349553495634957349583495934960349613496234963349643496534966349673496834969349703497134972349733497434975349763497734978349793498034981349823498334984349853498634987349883498934990349913499234993349943499534996349973499834999350003500135002350033500435005350063500735008350093501035011350123501335014350153501635017350183501935020350213502235023350243502535026350273502835029350303503135032350333503435035350363503735038350393504035041350423504335044350453504635047350483504935050350513505235053350543505535056350573505835059350603506135062350633506435065350663506735068350693507035071350723507335074350753507635077350783507935080350813508235083350843508535086350873508835089350903509135092350933509435095350963509735098350993510035101351023510335104351053510635107351083510935110351113511235113351143511535116351173511835119351203512135122351233512435125351263512735128351293513035131351323513335134351353513635137351383513935140351413514235143351443514535146351473514835149351503515135152351533515435155351563515735158351593516035161351623516335164351653516635167351683516935170351713517235173351743517535176351773517835179351803518135182351833518435185351863518735188351893519035191351923519335194351953519635197351983519935200352013520235203352043520535206352073520835209352103521135212352133521435215352163521735218352193522035221352223522335224352253522635227352283522935230352313523235233352343523535236352373523835239352403524135242352433524435245352463524735248352493525035251352523525335254352553525635257352583525935260352613526235263352643526535266352673526835269352703527135272352733527435275352763527735278352793528035281352823528335284352853528635287352883528935290352913529235293352943529535296352973529835299353003530135302353033530435305353063530735308353093531035311353123531335314353153531635317353183531935320353213532235323353243532535326353273532835329353303533135332353333533435335353363533735338353393534035341353423534335344353453534635347353483534935350353513535235353353543535535356353573535835359353603536135362353633536435365353663536735368353693537035371353723537335374353753537635377353783537935380353813538235383353843538535386353873538835389353903539135392353933539435395353963539735398353993540035401354023540335404354053540635407354083540935410354113541235413354143541535416354173541835419354203542135422354233542435425354263542735428354293543035431354323543335434354353543635437354383543935440354413544235443354443544535446354473544835449354503545135452354533545435455354563545735458354593546035461354623546335464354653546635467354683546935470354713547235473354743547535476354773547835479354803548135482354833548435485354863548735488354893549035491354923549335494354953549635497354983549935500355013550235503355043550535506355073550835509355103551135512355133551435515355163551735518355193552035521355223552335524355253552635527355283552935530355313553235533355343553535536355373553835539355403554135542355433554435545355463554735548355493555035551355523555335554355553555635557355583555935560355613556235563355643556535566355673556835569355703557135572355733557435575355763557735578355793558035581355823558335584355853558635587355883558935590355913559235593355943559535596355973559835599356003560135602356033560435605356063560735608356093561035611356123561335614356153561635617356183561935620356213562235623356243562535626356273562835629356303563135632356333563435635356363563735638356393564035641356423564335644356453564635647356483564935650356513565235653356543565535656356573565835659356603566135662356633566435665356663566735668356693567035671356723567335674356753567635677356783567935680356813568235683356843568535686356873568835689356903569135692356933569435695356963569735698356993570035701357023570335704357053570635707357083570935710357113571235713357143571535716357173571835719357203572135722357233572435725357263572735728357293573035731357323573335734357353573635737357383573935740357413574235743357443574535746357473574835749357503575135752357533575435755357563575735758357593576035761357623576335764357653576635767357683576935770357713577235773357743577535776357773577835779357803578135782357833578435785357863578735788357893579035791357923579335794357953579635797357983579935800358013580235803358043580535806358073580835809358103581135812358133581435815358163581735818358193582035821358223582335824358253582635827358283582935830358313583235833358343583535836358373583835839358403584135842358433584435845358463584735848358493585035851358523585335854358553585635857358583585935860358613586235863358643586535866358673586835869358703587135872358733587435875358763587735878358793588035881358823588335884358853588635887358883588935890358913589235893358943589535896358973589835899359003590135902359033590435905359063590735908359093591035911359123591335914359153591635917359183591935920359213592235923359243592535926359273592835929359303593135932359333593435935359363593735938359393594035941359423594335944359453594635947359483594935950359513595235953359543595535956359573595835959359603596135962359633596435965359663596735968359693597035971359723597335974359753597635977359783597935980359813598235983359843598535986359873598835989359903599135992359933599435995359963599735998359993600036001360023600336004360053600636007360083600936010360113601236013360143601536016360173601836019360203602136022360233602436025360263602736028360293603036031360323603336034360353603636037360383603936040360413604236043360443604536046360473604836049360503605136052360533605436055360563605736058360593606036061360623606336064360653606636067360683606936070360713607236073360743607536076360773607836079360803608136082360833608436085360863608736088360893609036091360923609336094360953609636097360983609936100361013610236103361043610536106361073610836109361103611136112361133611436115361163611736118361193612036121361223612336124361253612636127361283612936130361313613236133361343613536136361373613836139361403614136142361433614436145361463614736148361493615036151361523615336154361553615636157361583615936160361613616236163361643616536166361673616836169361703617136172361733617436175361763617736178361793618036181361823618336184361853618636187361883618936190361913619236193361943619536196361973619836199362003620136202362033620436205362063620736208362093621036211362123621336214362153621636217362183621936220362213622236223362243622536226362273622836229362303623136232362333623436235362363623736238362393624036241362423624336244362453624636247362483624936250362513625236253362543625536256362573625836259362603626136262362633626436265362663626736268362693627036271362723627336274362753627636277362783627936280362813628236283362843628536286362873628836289362903629136292362933629436295362963629736298362993630036301363023630336304363053630636307363083630936310363113631236313363143631536316363173631836319363203632136322363233632436325363263632736328363293633036331363323633336334363353633636337363383633936340363413634236343363443634536346363473634836349363503635136352363533635436355363563635736358363593636036361363623636336364363653636636367363683636936370363713637236373363743637536376363773637836379363803638136382363833638436385363863638736388363893639036391363923639336394363953639636397363983639936400364013640236403364043640536406364073640836409364103641136412364133641436415364163641736418364193642036421364223642336424364253642636427364283642936430364313643236433364343643536436364373643836439364403644136442364433644436445364463644736448364493645036451364523645336454364553645636457364583645936460364613646236463364643646536466364673646836469364703647136472364733647436475364763647736478364793648036481364823648336484364853648636487364883648936490364913649236493364943649536496364973649836499365003650136502365033650436505365063650736508365093651036511365123651336514365153651636517365183651936520365213652236523365243652536526365273652836529365303653136532365333653436535365363653736538365393654036541365423654336544365453654636547365483654936550365513655236553365543655536556365573655836559365603656136562365633656436565365663656736568365693657036571365723657336574365753657636577365783657936580365813658236583365843658536586365873658836589365903659136592365933659436595365963659736598365993660036601366023660336604366053660636607366083660936610366113661236613366143661536616366173661836619366203662136622366233662436625366263662736628366293663036631366323663336634366353663636637366383663936640366413664236643366443664536646366473664836649366503665136652366533665436655366563665736658366593666036661366623666336664366653666636667366683666936670366713667236673366743667536676366773667836679366803668136682366833668436685366863668736688366893669036691366923669336694366953669636697366983669936700367013670236703367043670536706367073670836709367103671136712367133671436715367163671736718367193672036721367223672336724367253672636727367283672936730367313673236733367343673536736367373673836739367403674136742367433674436745367463674736748367493675036751367523675336754367553675636757367583675936760367613676236763367643676536766367673676836769367703677136772367733677436775367763677736778367793678036781367823678336784367853678636787367883678936790367913679236793367943679536796367973679836799368003680136802368033680436805368063680736808368093681036811368123681336814368153681636817368183681936820368213682236823368243682536826368273682836829368303683136832368333683436835368363683736838368393684036841368423684336844368453684636847368483684936850368513685236853368543685536856368573685836859368603686136862368633686436865368663686736868368693687036871368723687336874368753687636877368783687936880368813688236883368843688536886368873688836889368903689136892368933689436895368963689736898368993690036901369023690336904369053690636907369083690936910369113691236913369143691536916369173691836919369203692136922369233692436925369263692736928369293693036931369323693336934369353693636937369383693936940369413694236943369443694536946369473694836949369503695136952369533695436955369563695736958369593696036961369623696336964369653696636967369683696936970369713697236973369743697536976369773697836979369803698136982369833698436985369863698736988369893699036991369923699336994369953699636997369983699937000370013700237003370043700537006370073700837009370103701137012370133701437015370163701737018370193702037021370223702337024370253702637027370283702937030370313703237033370343703537036370373703837039370403704137042370433704437045370463704737048370493705037051370523705337054370553705637057370583705937060370613706237063370643706537066370673706837069370703707137072370733707437075370763707737078370793708037081370823708337084370853708637087370883708937090370913709237093370943709537096370973709837099371003710137102371033710437105371063710737108371093711037111371123711337114371153711637117371183711937120371213712237123371243712537126371273712837129371303713137132371333713437135371363713737138371393714037141371423714337144371453714637147371483714937150371513715237153371543715537156371573715837159371603716137162371633716437165371663716737168371693717037171371723717337174371753717637177371783717937180371813718237183371843718537186371873718837189371903719137192371933719437195371963719737198371993720037201372023720337204372053720637207372083720937210372113721237213372143721537216372173721837219372203722137222372233722437225372263722737228372293723037231372323723337234372353723637237372383723937240372413724237243372443724537246372473724837249372503725137252372533725437255372563725737258372593726037261372623726337264372653726637267372683726937270372713727237273372743727537276372773727837279372803728137282372833728437285372863728737288372893729037291372923729337294372953729637297372983729937300373013730237303373043730537306373073730837309373103731137312373133731437315373163731737318373193732037321373223732337324373253732637327373283732937330373313733237333373343733537336373373733837339373403734137342373433734437345373463734737348373493735037351373523735337354373553735637357373583735937360373613736237363373643736537366373673736837369373703737137372373733737437375373763737737378373793738037381373823738337384373853738637387373883738937390373913739237393373943739537396373973739837399374003740137402374033740437405374063740737408374093741037411374123741337414374153741637417374183741937420374213742237423374243742537426374273742837429374303743137432374333743437435374363743737438374393744037441374423744337444374453744637447374483744937450374513745237453374543745537456374573745837459374603746137462374633746437465374663746737468374693747037471374723747337474374753747637477374783747937480374813748237483374843748537486374873748837489374903749137492374933749437495374963749737498374993750037501375023750337504375053750637507375083750937510375113751237513375143751537516375173751837519375203752137522375233752437525375263752737528375293753037531375323753337534375353753637537375383753937540375413754237543375443754537546375473754837549375503755137552375533755437555375563755737558375593756037561375623756337564375653756637567375683756937570375713757237573375743757537576375773757837579375803758137582375833758437585375863758737588375893759037591375923759337594375953759637597375983759937600376013760237603376043760537606376073760837609376103761137612376133761437615376163761737618376193762037621376223762337624376253762637627376283762937630376313763237633376343763537636376373763837639376403764137642376433764437645376463764737648376493765037651376523765337654376553765637657376583765937660376613766237663376643766537666376673766837669376703767137672376733767437675376763767737678376793768037681376823768337684376853768637687376883768937690376913769237693376943769537696376973769837699377003770137702377033770437705377063770737708377093771037711377123771337714377153771637717377183771937720377213772237723377243772537726377273772837729377303773137732377333773437735377363773737738377393774037741377423774337744377453774637747377483774937750377513775237753377543775537756377573775837759377603776137762377633776437765377663776737768377693777037771377723777337774377753777637777377783777937780377813778237783377843778537786377873778837789377903779137792377933779437795377963779737798377993780037801378023780337804378053780637807378083780937810378113781237813378143781537816378173781837819378203782137822378233782437825378263782737828378293783037831378323783337834378353783637837378383783937840378413784237843378443784537846378473784837849378503785137852378533785437855378563785737858378593786037861378623786337864378653786637867378683786937870378713787237873378743787537876378773787837879378803788137882378833788437885378863788737888378893789037891378923789337894378953789637897378983789937900379013790237903379043790537906379073790837909379103791137912379133791437915379163791737918379193792037921379223792337924379253792637927379283792937930379313793237933379343793537936379373793837939379403794137942379433794437945379463794737948379493795037951379523795337954379553795637957379583795937960379613796237963379643796537966379673796837969379703797137972379733797437975379763797737978379793798037981379823798337984379853798637987379883798937990379913799237993379943799537996379973799837999380003800138002380033800438005380063800738008380093801038011380123801338014380153801638017380183801938020380213802238023380243802538026380273802838029380303803138032380333803438035380363803738038380393804038041380423804338044380453804638047380483804938050380513805238053380543805538056380573805838059380603806138062380633806438065380663806738068380693807038071380723807338074380753807638077380783807938080380813808238083380843808538086380873808838089380903809138092380933809438095380963809738098380993810038101381023810338104381053810638107381083810938110381113811238113381143811538116381173811838119381203812138122381233812438125381263812738128381293813038131381323813338134381353813638137381383813938140381413814238143381443814538146381473814838149381503815138152381533815438155381563815738158381593816038161381623816338164381653816638167381683816938170381713817238173381743817538176381773817838179381803818138182381833818438185381863818738188381893819038191381923819338194381953819638197381983819938200382013820238203382043820538206382073820838209382103821138212382133821438215382163821738218382193822038221382223822338224382253822638227382283822938230382313823238233382343823538236382373823838239382403824138242382433824438245382463824738248382493825038251382523825338254382553825638257382583825938260382613826238263382643826538266382673826838269382703827138272382733827438275382763827738278382793828038281382823828338284382853828638287382883828938290382913829238293382943829538296382973829838299383003830138302383033830438305383063830738308383093831038311383123831338314383153831638317383183831938320383213832238323383243832538326383273832838329383303833138332383333833438335383363833738338383393834038341383423834338344383453834638347383483834938350383513835238353383543835538356383573835838359383603836138362383633836438365383663836738368383693837038371383723837338374383753837638377383783837938380383813838238383383843838538386383873838838389383903839138392383933839438395383963839738398383993840038401384023840338404384053840638407384083840938410384113841238413384143841538416384173841838419384203842138422384233842438425384263842738428384293843038431384323843338434384353843638437384383843938440384413844238443384443844538446384473844838449384503845138452384533845438455384563845738458384593846038461384623846338464384653846638467384683846938470384713847238473384743847538476384773847838479384803848138482384833848438485384863848738488384893849038491384923849338494384953849638497384983849938500385013850238503385043850538506385073850838509385103851138512385133851438515385163851738518385193852038521385223852338524385253852638527385283852938530385313853238533385343853538536385373853838539385403854138542385433854438545385463854738548385493855038551385523855338554385553855638557385583855938560385613856238563385643856538566385673856838569385703857138572385733857438575385763857738578385793858038581385823858338584385853858638587385883858938590385913859238593385943859538596385973859838599386003860138602386033860438605386063860738608386093861038611386123861338614386153861638617386183861938620386213862238623386243862538626386273862838629386303863138632386333863438635386363863738638386393864038641386423864338644386453864638647386483864938650386513865238653386543865538656386573865838659386603866138662386633866438665386663866738668386693867038671386723867338674386753867638677386783867938680386813868238683386843868538686386873868838689386903869138692386933869438695386963869738698386993870038701387023870338704387053870638707387083870938710387113871238713387143871538716387173871838719387203872138722387233872438725387263872738728387293873038731387323873338734387353873638737387383873938740387413874238743387443874538746387473874838749387503875138752387533875438755387563875738758387593876038761387623876338764387653876638767387683876938770387713877238773387743877538776387773877838779387803878138782387833878438785387863878738788387893879038791387923879338794387953879638797387983879938800388013880238803388043880538806388073880838809388103881138812388133881438815388163881738818388193882038821388223882338824388253882638827388283882938830388313883238833388343883538836388373883838839388403884138842388433884438845388463884738848388493885038851388523885338854388553885638857388583885938860388613886238863388643886538866388673886838869388703887138872388733887438875388763887738878388793888038881388823888338884388853888638887388883888938890388913889238893388943889538896388973889838899389003890138902389033890438905389063890738908389093891038911389123891338914389153891638917389183891938920389213892238923389243892538926389273892838929389303893138932389333893438935389363893738938389393894038941389423894338944389453894638947389483894938950389513895238953389543895538956389573895838959389603896138962389633896438965389663896738968389693897038971389723897338974389753897638977389783897938980389813898238983389843898538986389873898838989389903899138992389933899438995389963899738998389993900039001390023900339004390053900639007390083900939010390113901239013390143901539016390173901839019390203902139022390233902439025390263902739028390293903039031390323903339034390353903639037390383903939040390413904239043390443904539046390473904839049390503905139052390533905439055390563905739058390593906039061390623906339064390653906639067390683906939070390713907239073390743907539076390773907839079390803908139082390833908439085390863908739088390893909039091390923909339094390953909639097390983909939100391013910239103391043910539106391073910839109391103911139112391133911439115391163911739118391193912039121391223912339124391253912639127391283912939130391313913239133391343913539136391373913839139391403914139142391433914439145391463914739148391493915039151391523915339154391553915639157391583915939160391613916239163391643916539166391673916839169391703917139172391733917439175391763917739178391793918039181391823918339184391853918639187391883918939190391913919239193391943919539196391973919839199392003920139202392033920439205392063920739208392093921039211392123921339214392153921639217392183921939220392213922239223392243922539226392273922839229392303923139232392333923439235392363923739238392393924039241392423924339244392453924639247392483924939250392513925239253392543925539256392573925839259392603926139262392633926439265392663926739268392693927039271392723927339274392753927639277392783927939280392813928239283392843928539286392873928839289392903929139292392933929439295392963929739298392993930039301393023930339304393053930639307393083930939310393113931239313393143931539316393173931839319393203932139322393233932439325393263932739328393293933039331393323933339334393353933639337393383933939340393413934239343393443934539346393473934839349393503935139352393533935439355393563935739358393593936039361393623936339364393653936639367393683936939370393713937239373393743937539376393773937839379393803938139382393833938439385393863938739388393893939039391393923939339394393953939639397393983939939400394013940239403394043940539406394073940839409394103941139412394133941439415394163941739418394193942039421394223942339424394253942639427394283942939430394313943239433394343943539436394373943839439394403944139442394433944439445394463944739448394493945039451394523945339454394553945639457394583945939460394613946239463394643946539466394673946839469394703947139472394733947439475394763947739478394793948039481394823948339484394853948639487394883948939490394913949239493394943949539496394973949839499395003950139502395033950439505395063950739508395093951039511395123951339514395153951639517395183951939520395213952239523395243952539526395273952839529395303953139532395333953439535395363953739538395393954039541395423954339544395453954639547395483954939550395513955239553395543955539556395573955839559395603956139562395633956439565395663956739568395693957039571395723957339574395753957639577395783957939580395813958239583395843958539586395873958839589395903959139592395933959439595395963959739598395993960039601396023960339604396053960639607396083960939610396113961239613396143961539616396173961839619396203962139622396233962439625396263962739628396293963039631396323963339634396353963639637396383963939640396413964239643396443964539646396473964839649396503965139652396533965439655396563965739658396593966039661396623966339664396653966639667396683966939670396713967239673396743967539676396773967839679396803968139682396833968439685396863968739688396893969039691396923969339694396953969639697396983969939700397013970239703397043970539706397073970839709397103971139712397133971439715397163971739718397193972039721397223972339724397253972639727397283972939730397313973239733397343973539736397373973839739397403974139742397433974439745397463974739748397493975039751397523975339754397553975639757397583975939760397613976239763397643976539766397673976839769397703977139772397733977439775397763977739778397793978039781397823978339784397853978639787397883978939790397913979239793397943979539796397973979839799398003980139802398033980439805398063980739808398093981039811398123981339814398153981639817398183981939820398213982239823398243982539826398273982839829398303983139832398333983439835398363983739838398393984039841398423984339844398453984639847398483984939850398513985239853398543985539856398573985839859398603986139862398633986439865398663986739868398693987039871398723987339874398753987639877398783987939880398813988239883398843988539886398873988839889398903989139892398933989439895398963989739898398993990039901399023990339904399053990639907399083990939910399113991239913399143991539916399173991839919399203992139922399233992439925399263992739928399293993039931399323993339934399353993639937399383993939940399413994239943399443994539946399473994839949399503995139952399533995439955399563995739958399593996039961399623996339964399653996639967399683996939970399713997239973399743997539976399773997839979399803998139982399833998439985399863998739988399893999039991399923999339994399953999639997399983999940000400014000240003400044000540006400074000840009400104001140012400134001440015400164001740018400194002040021400224002340024400254002640027400284002940030400314003240033400344003540036400374003840039400404004140042400434004440045400464004740048400494005040051400524005340054400554005640057400584005940060400614006240063400644006540066400674006840069400704007140072400734007440075400764007740078400794008040081400824008340084400854008640087400884008940090400914009240093400944009540096400974009840099401004010140102401034010440105401064010740108401094011040111401124011340114401154011640117401184011940120401214012240123401244012540126401274012840129401304013140132401334013440135401364013740138401394014040141401424014340144401454014640147401484014940150401514015240153401544015540156401574015840159401604016140162401634016440165401664016740168401694017040171401724017340174401754017640177401784017940180401814018240183401844018540186401874018840189401904019140192401934019440195401964019740198401994020040201402024020340204402054020640207402084020940210402114021240213402144021540216402174021840219402204022140222402234022440225402264022740228402294023040231402324023340234402354023640237402384023940240402414024240243402444024540246402474024840249402504025140252402534025440255402564025740258402594026040261402624026340264402654026640267402684026940270402714027240273402744027540276402774027840279402804028140282402834028440285402864028740288402894029040291402924029340294402954029640297402984029940300403014030240303403044030540306403074030840309403104031140312403134031440315403164031740318403194032040321403224032340324403254032640327403284032940330403314033240333403344033540336403374033840339403404034140342403434034440345403464034740348403494035040351403524035340354403554035640357403584035940360403614036240363403644036540366403674036840369403704037140372403734037440375403764037740378403794038040381403824038340384403854038640387403884038940390403914039240393403944039540396403974039840399404004040140402404034040440405404064040740408404094041040411404124041340414404154041640417404184041940420404214042240423404244042540426404274042840429404304043140432404334043440435404364043740438404394044040441404424044340444404454044640447404484044940450404514045240453404544045540456404574045840459404604046140462404634046440465404664046740468404694047040471404724047340474404754047640477404784047940480404814048240483404844048540486404874048840489404904049140492404934049440495404964049740498404994050040501405024050340504405054050640507405084050940510405114051240513405144051540516405174051840519405204052140522405234052440525405264052740528405294053040531405324053340534405354053640537405384053940540405414054240543405444054540546405474054840549405504055140552405534055440555405564055740558405594056040561405624056340564405654056640567405684056940570405714057240573405744057540576405774057840579405804058140582405834058440585405864058740588405894059040591405924059340594405954059640597405984059940600406014060240603406044060540606406074060840609406104061140612406134061440615406164061740618406194062040621406224062340624406254062640627406284062940630406314063240633406344063540636406374063840639406404064140642406434064440645406464064740648406494065040651406524065340654406554065640657406584065940660406614066240663406644066540666406674066840669406704067140672406734067440675406764067740678406794068040681406824068340684406854068640687406884068940690406914069240693406944069540696406974069840699407004070140702407034070440705407064070740708407094071040711407124071340714407154071640717407184071940720407214072240723407244072540726407274072840729407304073140732407334073440735407364073740738407394074040741407424074340744407454074640747407484074940750407514075240753407544075540756407574075840759407604076140762407634076440765407664076740768407694077040771407724077340774407754077640777407784077940780407814078240783407844078540786407874078840789407904079140792407934079440795407964079740798407994080040801408024080340804408054080640807408084080940810408114081240813408144081540816408174081840819408204082140822408234082440825408264082740828408294083040831408324083340834408354083640837408384083940840408414084240843408444084540846408474084840849408504085140852408534085440855408564085740858408594086040861408624086340864408654086640867408684086940870408714087240873408744087540876408774087840879408804088140882408834088440885408864088740888408894089040891408924089340894408954089640897408984089940900409014090240903409044090540906409074090840909409104091140912409134091440915409164091740918409194092040921409224092340924409254092640927409284092940930409314093240933409344093540936409374093840939409404094140942409434094440945409464094740948409494095040951409524095340954409554095640957409584095940960409614096240963409644096540966409674096840969409704097140972409734097440975409764097740978409794098040981409824098340984409854098640987409884098940990409914099240993409944099540996409974099840999410004100141002410034100441005410064100741008410094101041011410124101341014410154101641017410184101941020410214102241023410244102541026410274102841029410304103141032410334103441035410364103741038410394104041041410424104341044410454104641047410484104941050410514105241053410544105541056410574105841059410604106141062410634106441065410664106741068410694107041071410724107341074410754107641077410784107941080410814108241083410844108541086410874108841089410904109141092410934109441095410964109741098410994110041101411024110341104411054110641107411084110941110411114111241113411144111541116411174111841119411204112141122411234112441125411264112741128411294113041131411324113341134411354113641137411384113941140411414114241143411444114541146411474114841149411504115141152411534115441155411564115741158411594116041161411624116341164411654116641167411684116941170411714117241173411744117541176411774117841179411804118141182411834118441185411864118741188411894119041191411924119341194411954119641197411984119941200412014120241203412044120541206412074120841209412104121141212412134121441215412164121741218412194122041221412224122341224412254122641227412284122941230412314123241233412344123541236412374123841239412404124141242412434124441245412464124741248412494125041251412524125341254412554125641257412584125941260412614126241263412644126541266412674126841269412704127141272412734127441275412764127741278412794128041281412824128341284412854128641287412884128941290412914129241293412944129541296412974129841299413004130141302413034130441305413064130741308413094131041311413124131341314413154131641317413184131941320413214132241323413244132541326413274132841329413304133141332413334133441335413364133741338413394134041341413424134341344413454134641347413484134941350413514135241353413544135541356413574135841359413604136141362413634136441365413664136741368413694137041371413724137341374413754137641377413784137941380413814138241383413844138541386413874138841389413904139141392413934139441395413964139741398413994140041401414024140341404414054140641407414084140941410414114141241413414144141541416414174141841419414204142141422414234142441425414264142741428414294143041431414324143341434414354143641437414384143941440414414144241443414444144541446414474144841449414504145141452414534145441455414564145741458414594146041461414624146341464414654146641467414684146941470414714147241473414744147541476414774147841479414804148141482414834148441485414864148741488414894149041491414924149341494414954149641497414984149941500415014150241503415044150541506415074150841509415104151141512415134151441515415164151741518415194152041521415224152341524415254152641527415284152941530415314153241533415344153541536415374153841539415404154141542415434154441545415464154741548415494155041551415524155341554415554155641557415584155941560415614156241563415644156541566415674156841569415704157141572415734157441575415764157741578415794158041581415824158341584415854158641587415884158941590415914159241593415944159541596415974159841599416004160141602416034160441605416064160741608416094161041611416124161341614416154161641617416184161941620416214162241623416244162541626416274162841629416304163141632416334163441635416364163741638416394164041641416424164341644416454164641647416484164941650416514165241653416544165541656416574165841659416604166141662416634166441665416664166741668416694167041671416724167341674416754167641677416784167941680416814168241683416844168541686416874168841689416904169141692416934169441695416964169741698416994170041701417024170341704417054170641707417084170941710417114171241713417144171541716417174171841719417204172141722417234172441725417264172741728417294173041731417324173341734417354173641737417384173941740417414174241743417444174541746417474174841749417504175141752417534175441755417564175741758417594176041761417624176341764417654176641767417684176941770417714177241773417744177541776417774177841779417804178141782417834178441785417864178741788417894179041791417924179341794417954179641797417984179941800418014180241803418044180541806418074180841809418104181141812418134181441815418164181741818418194182041821418224182341824418254182641827418284182941830418314183241833418344183541836418374183841839418404184141842418434184441845418464184741848418494185041851418524185341854418554185641857418584185941860418614186241863418644186541866418674186841869418704187141872418734187441875418764187741878418794188041881418824188341884418854188641887418884188941890418914189241893418944189541896418974189841899419004190141902419034190441905419064190741908419094191041911419124191341914419154191641917419184191941920419214192241923419244192541926419274192841929419304193141932419334193441935419364193741938419394194041941419424194341944419454194641947419484194941950419514195241953419544195541956419574195841959419604196141962419634196441965419664196741968419694197041971419724197341974419754197641977419784197941980419814198241983419844198541986419874198841989419904199141992419934199441995419964199741998419994200042001420024200342004420054200642007420084200942010420114201242013420144201542016420174201842019420204202142022420234202442025420264202742028420294203042031420324203342034420354203642037420384203942040420414204242043420444204542046420474204842049420504205142052420534205442055420564205742058420594206042061420624206342064420654206642067420684206942070420714207242073420744207542076420774207842079420804208142082420834208442085420864208742088420894209042091420924209342094420954209642097420984209942100421014210242103421044210542106421074210842109421104211142112421134211442115421164211742118421194212042121421224212342124421254212642127421284212942130421314213242133421344213542136421374213842139421404214142142421434214442145421464214742148421494215042151421524215342154421554215642157421584215942160421614216242163421644216542166421674216842169421704217142172421734217442175421764217742178421794218042181421824218342184421854218642187421884218942190421914219242193421944219542196421974219842199422004220142202422034220442205422064220742208422094221042211422124221342214422154221642217422184221942220422214222242223422244222542226422274222842229422304223142232422334223442235422364223742238422394224042241422424224342244422454224642247422484224942250422514225242253422544225542256422574225842259422604226142262422634226442265422664226742268422694227042271422724227342274422754227642277422784227942280422814228242283422844228542286422874228842289422904229142292422934229442295422964229742298422994230042301423024230342304423054230642307423084230942310423114231242313423144231542316423174231842319423204232142322423234232442325423264232742328423294233042331423324233342334423354233642337423384233942340423414234242343423444234542346423474234842349423504235142352423534235442355423564235742358423594236042361423624236342364423654236642367423684236942370423714237242373423744237542376423774237842379423804238142382423834238442385423864238742388423894239042391423924239342394423954239642397423984239942400424014240242403424044240542406424074240842409424104241142412424134241442415424164241742418424194242042421424224242342424424254242642427424284242942430424314243242433424344243542436424374243842439424404244142442424434244442445424464244742448424494245042451424524245342454424554245642457424584245942460424614246242463424644246542466424674246842469424704247142472424734247442475424764247742478424794248042481424824248342484424854248642487424884248942490424914249242493424944249542496424974249842499425004250142502425034250442505425064250742508425094251042511425124251342514425154251642517425184251942520425214252242523425244252542526425274252842529425304253142532425334253442535425364253742538425394254042541425424254342544425454254642547425484254942550425514255242553425544255542556425574255842559425604256142562425634256442565425664256742568425694257042571425724257342574425754257642577425784257942580425814258242583425844258542586425874258842589425904259142592425934259442595425964259742598425994260042601426024260342604426054260642607426084260942610426114261242613426144261542616426174261842619426204262142622426234262442625426264262742628426294263042631426324263342634426354263642637426384263942640426414264242643426444264542646426474264842649426504265142652426534265442655426564265742658426594266042661426624266342664426654266642667426684266942670426714267242673426744267542676426774267842679426804268142682426834268442685426864268742688426894269042691426924269342694426954269642697426984269942700427014270242703427044270542706427074270842709427104271142712427134271442715427164271742718427194272042721427224272342724427254272642727427284272942730427314273242733427344273542736427374273842739427404274142742427434274442745427464274742748427494275042751427524275342754427554275642757427584275942760427614276242763427644276542766427674276842769427704277142772427734277442775427764277742778427794278042781427824278342784427854278642787427884278942790427914279242793427944279542796427974279842799428004280142802428034280442805428064280742808428094281042811428124281342814428154281642817428184281942820428214282242823428244282542826428274282842829428304283142832428334283442835428364283742838428394284042841428424284342844428454284642847428484284942850428514285242853428544285542856428574285842859428604286142862428634286442865428664286742868428694287042871428724287342874428754287642877428784287942880428814288242883428844288542886428874288842889428904289142892428934289442895428964289742898428994290042901429024290342904429054290642907429084290942910429114291242913429144291542916429174291842919429204292142922429234292442925429264292742928429294293042931429324293342934429354293642937429384293942940429414294242943429444294542946429474294842949429504295142952429534295442955429564295742958429594296042961429624296342964429654296642967429684296942970429714297242973429744297542976429774297842979429804298142982429834298442985429864298742988429894299042991429924299342994429954299642997429984299943000430014300243003430044300543006430074300843009430104301143012430134301443015430164301743018430194302043021430224302343024430254302643027430284302943030430314303243033430344303543036430374303843039430404304143042430434304443045430464304743048430494305043051430524305343054430554305643057430584305943060430614306243063430644306543066430674306843069430704307143072430734307443075430764307743078430794308043081430824308343084430854308643087430884308943090430914309243093430944309543096430974309843099431004310143102431034310443105431064310743108431094311043111431124311343114431154311643117431184311943120431214312243123431244312543126431274312843129431304313143132431334313443135431364313743138431394314043141431424314343144431454314643147431484314943150431514315243153431544315543156431574315843159431604316143162431634316443165431664316743168431694317043171431724317343174431754317643177431784317943180431814318243183431844318543186431874318843189431904319143192431934319443195431964319743198431994320043201432024320343204432054320643207432084320943210432114321243213432144321543216432174321843219432204322143222432234322443225432264322743228432294323043231432324323343234432354323643237432384323943240432414324243243432444324543246432474324843249432504325143252432534325443255432564325743258432594326043261432624326343264432654326643267432684326943270432714327243273432744327543276432774327843279432804328143282432834328443285432864328743288432894329043291432924329343294432954329643297432984329943300433014330243303433044330543306433074330843309433104331143312433134331443315433164331743318433194332043321433224332343324433254332643327433284332943330433314333243333433344333543336433374333843339433404334143342433434334443345433464334743348433494335043351433524335343354433554335643357433584335943360433614336243363433644336543366433674336843369433704337143372433734337443375433764337743378433794338043381433824338343384433854338643387433884338943390433914339243393433944339543396433974339843399434004340143402434034340443405434064340743408434094341043411434124341343414434154341643417434184341943420434214342243423434244342543426434274342843429434304343143432434334343443435434364343743438434394344043441434424344343444434454344643447434484344943450434514345243453434544345543456434574345843459434604346143462434634346443465434664346743468434694347043471434724347343474434754347643477434784347943480434814348243483434844348543486434874348843489434904349143492434934349443495434964349743498434994350043501435024350343504435054350643507435084350943510435114351243513435144351543516435174351843519435204352143522435234352443525435264352743528435294353043531435324353343534435354353643537435384353943540435414354243543435444354543546435474354843549435504355143552435534355443555435564355743558435594356043561435624356343564435654356643567435684356943570435714357243573435744357543576435774357843579435804358143582435834358443585435864358743588435894359043591435924359343594435954359643597435984359943600436014360243603436044360543606436074360843609436104361143612436134361443615436164361743618436194362043621436224362343624436254362643627436284362943630436314363243633436344363543636436374363843639436404364143642436434364443645436464364743648436494365043651436524365343654436554365643657436584365943660436614366243663436644366543666436674366843669436704367143672436734367443675436764367743678436794368043681436824368343684436854368643687436884368943690436914369243693436944369543696436974369843699437004370143702437034370443705437064370743708437094371043711437124371343714437154371643717437184371943720437214372243723437244372543726437274372843729437304373143732437334373443735437364373743738437394374043741437424374343744437454374643747437484374943750437514375243753437544375543756437574375843759437604376143762437634376443765437664376743768437694377043771437724377343774437754377643777437784377943780437814378243783437844378543786437874378843789437904379143792437934379443795437964379743798437994380043801438024380343804438054380643807438084380943810438114381243813438144381543816438174381843819438204382143822438234382443825438264382743828438294383043831438324383343834438354383643837438384383943840438414384243843438444384543846438474384843849438504385143852438534385443855438564385743858438594386043861438624386343864438654386643867438684386943870438714387243873438744387543876438774387843879438804388143882438834388443885438864388743888438894389043891438924389343894438954389643897438984389943900439014390243903439044390543906439074390843909439104391143912439134391443915439164391743918439194392043921439224392343924439254392643927439284392943930439314393243933439344393543936439374393843939439404394143942439434394443945439464394743948439494395043951439524395343954439554395643957439584395943960439614396243963439644396543966439674396843969439704397143972439734397443975439764397743978439794398043981439824398343984439854398643987439884398943990439914399243993439944399543996439974399843999440004400144002440034400444005440064400744008440094401044011440124401344014440154401644017440184401944020440214402244023440244402544026440274402844029440304403144032440334403444035440364403744038440394404044041440424404344044440454404644047440484404944050440514405244053440544405544056440574405844059440604406144062440634406444065440664406744068440694407044071440724407344074440754407644077440784407944080440814408244083440844408544086440874408844089440904409144092440934409444095440964409744098440994410044101441024410344104441054410644107441084410944110441114411244113441144411544116441174411844119441204412144122441234412444125441264412744128441294413044131441324413344134441354413644137441384413944140441414414244143441444414544146441474414844149441504415144152441534415444155441564415744158441594416044161441624416344164441654416644167441684416944170441714417244173441744417544176441774417844179441804418144182441834418444185441864418744188441894419044191441924419344194441954419644197441984419944200442014420244203442044420544206442074420844209442104421144212442134421444215442164421744218442194422044221442224422344224442254422644227442284422944230442314423244233442344423544236442374423844239442404424144242442434424444245442464424744248442494425044251442524425344254442554425644257442584425944260442614426244263442644426544266442674426844269442704427144272442734427444275442764427744278442794428044281442824428344284442854428644287442884428944290442914429244293442944429544296442974429844299443004430144302443034430444305443064430744308443094431044311443124431344314443154431644317443184431944320443214432244323443244432544326443274432844329443304433144332443334433444335443364433744338443394434044341443424434344344443454434644347443484434944350443514435244353443544435544356443574435844359443604436144362443634436444365443664436744368443694437044371443724437344374443754437644377443784437944380443814438244383443844438544386443874438844389443904439144392443934439444395443964439744398443994440044401444024440344404444054440644407444084440944410444114441244413444144441544416444174441844419444204442144422444234442444425444264442744428444294443044431444324443344434444354443644437444384443944440444414444244443444444444544446444474444844449444504445144452444534445444455444564445744458444594446044461444624446344464444654446644467444684446944470444714447244473444744447544476444774447844479444804448144482
  1. /*!
  2. * Copyright (c) 2018 TurfJS
  3. * turf.(https://github.com/Turfjs/turf)
  4. * license: MIT
  5. * version: v5.1.6
  6. */
  7. (function (global, factory) {
  8. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  9. typeof define === 'function' && define.amd ? define(['exports'], factory) :
  10. (factory((global.turf = {})));
  11. }(this, (function (exports) { 'use strict';
  12. /**
  13. * Earth Radius used with the Harvesine formula and approximates using a spherical (non-ellipsoid) Earth.
  14. */
  15. var earthRadius = 6371008.8;
  16. /**
  17. * Unit of measurement factors using a spherical (non-ellipsoid) earth radius.
  18. */
  19. var factors = {
  20. meters: earthRadius,
  21. metres: earthRadius,
  22. millimeters: earthRadius * 1000,
  23. millimetres: earthRadius * 1000,
  24. centimeters: earthRadius * 100,
  25. centimetres: earthRadius * 100,
  26. kilometers: earthRadius / 1000,
  27. kilometres: earthRadius / 1000,
  28. miles: earthRadius / 1609.344,
  29. nauticalmiles: earthRadius / 1852,
  30. inches: earthRadius * 39.370,
  31. yards: earthRadius / 1.0936,
  32. feet: earthRadius * 3.28084,
  33. radians: 1,
  34. degrees: earthRadius / 111325,
  35. };
  36. /**
  37. * Units of measurement factors based on 1 meter.
  38. */
  39. var unitsFactors = {
  40. meters: 1,
  41. metres: 1,
  42. millimeters: 1000,
  43. millimetres: 1000,
  44. centimeters: 100,
  45. centimetres: 100,
  46. kilometers: 1 / 1000,
  47. kilometres: 1 / 1000,
  48. miles: 1 / 1609.344,
  49. nauticalmiles: 1 / 1852,
  50. inches: 39.370,
  51. yards: 1 / 1.0936,
  52. feet: 3.28084,
  53. radians: 1 / earthRadius,
  54. degrees: 1 / 111325,
  55. };
  56. /**
  57. * Area of measurement factors based on 1 square meter.
  58. */
  59. var areaFactors = {
  60. meters: 1,
  61. metres: 1,
  62. millimeters: 1000000,
  63. millimetres: 1000000,
  64. centimeters: 10000,
  65. centimetres: 10000,
  66. kilometers: 0.000001,
  67. kilometres: 0.000001,
  68. acres: 0.000247105,
  69. miles: 3.86e-7,
  70. yards: 1.195990046,
  71. feet: 10.763910417,
  72. inches: 1550.003100006
  73. };
  74. /**
  75. * Wraps a GeoJSON {@link Geometry} in a GeoJSON {@link Feature}.
  76. *
  77. * @name feature
  78. * @param {Geometry} geometry input geometry
  79. * @param {Object} [properties={}] an Object of key-value pairs to add as properties
  80. * @param {Object} [options={}] Optional Parameters
  81. * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
  82. * @param {string|number} [options.id] Identifier associated with the Feature
  83. * @returns {Feature} a GeoJSON Feature
  84. * @example
  85. * var geometry = {
  86. * "type": "Point",
  87. * "coordinates": [110, 50]
  88. * };
  89. *
  90. * var feature = turf.feature(geometry);
  91. *
  92. * //=feature
  93. */
  94. function feature(geometry, properties, options) {
  95. // Optional Parameters
  96. options = options || {};
  97. if (!isObject(options)) throw new Error('options is invalid');
  98. var bbox = options.bbox;
  99. var id = options.id;
  100. // Validation
  101. if (geometry === undefined) throw new Error('geometry is required');
  102. if (properties && properties.constructor !== Object) throw new Error('properties must be an Object');
  103. if (bbox) validateBBox(bbox);
  104. if (id) validateId(id);
  105. // Main
  106. var feat = {type: 'Feature'};
  107. if (id) feat.id = id;
  108. if (bbox) feat.bbox = bbox;
  109. feat.properties = properties || {};
  110. feat.geometry = geometry;
  111. return feat;
  112. }
  113. /**
  114. * Creates a GeoJSON {@link Geometry} from a Geometry string type & coordinates.
  115. * For GeometryCollection type use `helpers.geometryCollection`
  116. *
  117. * @name geometry
  118. * @param {string} type Geometry Type
  119. * @param {Array<number>} coordinates Coordinates
  120. * @param {Object} [options={}] Optional Parameters
  121. * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Geometry
  122. * @returns {Geometry} a GeoJSON Geometry
  123. * @example
  124. * var type = 'Point';
  125. * var coordinates = [110, 50];
  126. *
  127. * var geometry = turf.geometry(type, coordinates);
  128. *
  129. * //=geometry
  130. */
  131. function geometry(type, coordinates, options) {
  132. // Optional Parameters
  133. options = options || {};
  134. if (!isObject(options)) throw new Error('options is invalid');
  135. var bbox = options.bbox;
  136. // Validation
  137. if (!type) throw new Error('type is required');
  138. if (!coordinates) throw new Error('coordinates is required');
  139. if (!Array.isArray(coordinates)) throw new Error('coordinates must be an Array');
  140. if (bbox) validateBBox(bbox);
  141. // Main
  142. var geom;
  143. switch (type) {
  144. case 'Point': geom = point(coordinates).geometry; break;
  145. case 'LineString': geom = lineString(coordinates).geometry; break;
  146. case 'Polygon': geom = polygon(coordinates).geometry; break;
  147. case 'MultiPoint': geom = multiPoint(coordinates).geometry; break;
  148. case 'MultiLineString': geom = multiLineString(coordinates).geometry; break;
  149. case 'MultiPolygon': geom = multiPolygon(coordinates).geometry; break;
  150. default: throw new Error(type + ' is invalid');
  151. }
  152. if (bbox) geom.bbox = bbox;
  153. return geom;
  154. }
  155. /**
  156. * Creates a {@link Point} {@link Feature} from a Position.
  157. *
  158. * @name point
  159. * @param {Array<number>} coordinates longitude, latitude position (each in decimal degrees)
  160. * @param {Object} [properties={}] an Object of key-value pairs to add as properties
  161. * @param {Object} [options={}] Optional Parameters
  162. * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
  163. * @param {string|number} [options.id] Identifier associated with the Feature
  164. * @returns {Feature<Point>} a Point feature
  165. * @example
  166. * var point = turf.point([-75.343, 39.984]);
  167. *
  168. * //=point
  169. */
  170. function point(coordinates, properties, options) {
  171. if (!coordinates) throw new Error('coordinates is required');
  172. if (!Array.isArray(coordinates)) throw new Error('coordinates must be an Array');
  173. if (coordinates.length < 2) throw new Error('coordinates must be at least 2 numbers long');
  174. if (!isNumber(coordinates[0]) || !isNumber(coordinates[1])) throw new Error('coordinates must contain numbers');
  175. return feature({
  176. type: 'Point',
  177. coordinates: coordinates
  178. }, properties, options);
  179. }
  180. /**
  181. * Creates a {@link Point} {@link FeatureCollection} from an Array of Point coordinates.
  182. *
  183. * @name points
  184. * @param {Array<Array<number>>} coordinates an array of Points
  185. * @param {Object} [properties={}] Translate these properties to each Feature
  186. * @param {Object} [options={}] Optional Parameters
  187. * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the FeatureCollection
  188. * @param {string|number} [options.id] Identifier associated with the FeatureCollection
  189. * @returns {FeatureCollection<Point>} Point Feature
  190. * @example
  191. * var points = turf.points([
  192. * [-75, 39],
  193. * [-80, 45],
  194. * [-78, 50]
  195. * ]);
  196. *
  197. * //=points
  198. */
  199. function points(coordinates, properties, options) {
  200. if (!coordinates) throw new Error('coordinates is required');
  201. if (!Array.isArray(coordinates)) throw new Error('coordinates must be an Array');
  202. return featureCollection(coordinates.map(function (coords) {
  203. return point(coords, properties);
  204. }), options);
  205. }
  206. /**
  207. * Creates a {@link Polygon} {@link Feature} from an Array of LinearRings.
  208. *
  209. * @name polygon
  210. * @param {Array<Array<Array<number>>>} coordinates an array of LinearRings
  211. * @param {Object} [properties={}] an Object of key-value pairs to add as properties
  212. * @param {Object} [options={}] Optional Parameters
  213. * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
  214. * @param {string|number} [options.id] Identifier associated with the Feature
  215. * @returns {Feature<Polygon>} Polygon Feature
  216. * @example
  217. * var polygon = turf.polygon([[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]], { name: 'poly1' });
  218. *
  219. * //=polygon
  220. */
  221. function polygon(coordinates, properties, options) {
  222. if (!coordinates) throw new Error('coordinates is required');
  223. for (var i = 0; i < coordinates.length; i++) {
  224. var ring = coordinates[i];
  225. if (ring.length < 4) {
  226. throw new Error('Each LinearRing of a Polygon must have 4 or more Positions.');
  227. }
  228. for (var j = 0; j < ring[ring.length - 1].length; j++) {
  229. // Check if first point of Polygon contains two numbers
  230. if (i === 0 && j === 0 && !isNumber(ring[0][0]) || !isNumber(ring[0][1])) throw new Error('coordinates must contain numbers');
  231. if (ring[ring.length - 1][j] !== ring[0][j]) {
  232. throw new Error('First and last Position are not equivalent.');
  233. }
  234. }
  235. }
  236. return feature({
  237. type: 'Polygon',
  238. coordinates: coordinates
  239. }, properties, options);
  240. }
  241. /**
  242. * Creates a {@link Polygon} {@link FeatureCollection} from an Array of Polygon coordinates.
  243. *
  244. * @name polygons
  245. * @param {Array<Array<Array<Array<number>>>>} coordinates an array of Polygon coordinates
  246. * @param {Object} [properties={}] an Object of key-value pairs to add as properties
  247. * @param {Object} [options={}] Optional Parameters
  248. * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
  249. * @param {string|number} [options.id] Identifier associated with the FeatureCollection
  250. * @returns {FeatureCollection<Polygon>} Polygon FeatureCollection
  251. * @example
  252. * var polygons = turf.polygons([
  253. * [[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]],
  254. * [[[-15, 42], [-14, 46], [-12, 41], [-17, 44], [-15, 42]]],
  255. * ]);
  256. *
  257. * //=polygons
  258. */
  259. function polygons(coordinates, properties, options) {
  260. if (!coordinates) throw new Error('coordinates is required');
  261. if (!Array.isArray(coordinates)) throw new Error('coordinates must be an Array');
  262. return featureCollection(coordinates.map(function (coords) {
  263. return polygon(coords, properties);
  264. }), options);
  265. }
  266. /**
  267. * Creates a {@link LineString} {@link Feature} from an Array of Positions.
  268. *
  269. * @name lineString
  270. * @param {Array<Array<number>>} coordinates an array of Positions
  271. * @param {Object} [properties={}] an Object of key-value pairs to add as properties
  272. * @param {Object} [options={}] Optional Parameters
  273. * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
  274. * @param {string|number} [options.id] Identifier associated with the Feature
  275. * @returns {Feature<LineString>} LineString Feature
  276. * @example
  277. * var linestring1 = turf.lineString([[-24, 63], [-23, 60], [-25, 65], [-20, 69]], {name: 'line 1'});
  278. * var linestring2 = turf.lineString([[-14, 43], [-13, 40], [-15, 45], [-10, 49]], {name: 'line 2'});
  279. *
  280. * //=linestring1
  281. * //=linestring2
  282. */
  283. function lineString(coordinates, properties, options) {
  284. if (!coordinates) throw new Error('coordinates is required');
  285. if (coordinates.length < 2) throw new Error('coordinates must be an array of two or more positions');
  286. // Check if first point of LineString contains two numbers
  287. if (!isNumber(coordinates[0][1]) || !isNumber(coordinates[0][1])) throw new Error('coordinates must contain numbers');
  288. return feature({
  289. type: 'LineString',
  290. coordinates: coordinates
  291. }, properties, options);
  292. }
  293. /**
  294. * Creates a {@link LineString} {@link FeatureCollection} from an Array of LineString coordinates.
  295. *
  296. * @name lineStrings
  297. * @param {Array<Array<number>>} coordinates an array of LinearRings
  298. * @param {Object} [properties={}] an Object of key-value pairs to add as properties
  299. * @param {Object} [options={}] Optional Parameters
  300. * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the FeatureCollection
  301. * @param {string|number} [options.id] Identifier associated with the FeatureCollection
  302. * @returns {FeatureCollection<LineString>} LineString FeatureCollection
  303. * @example
  304. * var linestrings = turf.lineStrings([
  305. * [[-24, 63], [-23, 60], [-25, 65], [-20, 69]],
  306. * [[-14, 43], [-13, 40], [-15, 45], [-10, 49]]
  307. * ]);
  308. *
  309. * //=linestrings
  310. */
  311. function lineStrings(coordinates, properties, options) {
  312. if (!coordinates) throw new Error('coordinates is required');
  313. if (!Array.isArray(coordinates)) throw new Error('coordinates must be an Array');
  314. return featureCollection(coordinates.map(function (coords) {
  315. return lineString(coords, properties);
  316. }), options);
  317. }
  318. /**
  319. * Takes one or more {@link Feature|Features} and creates a {@link FeatureCollection}.
  320. *
  321. * @name featureCollection
  322. * @param {Feature[]} features input features
  323. * @param {Object} [options={}] Optional Parameters
  324. * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
  325. * @param {string|number} [options.id] Identifier associated with the Feature
  326. * @returns {FeatureCollection} FeatureCollection of Features
  327. * @example
  328. * var locationA = turf.point([-75.343, 39.984], {name: 'Location A'});
  329. * var locationB = turf.point([-75.833, 39.284], {name: 'Location B'});
  330. * var locationC = turf.point([-75.534, 39.123], {name: 'Location C'});
  331. *
  332. * var collection = turf.featureCollection([
  333. * locationA,
  334. * locationB,
  335. * locationC
  336. * ]);
  337. *
  338. * //=collection
  339. */
  340. function featureCollection(features, options) {
  341. // Optional Parameters
  342. options = options || {};
  343. if (!isObject(options)) throw new Error('options is invalid');
  344. var bbox = options.bbox;
  345. var id = options.id;
  346. // Validation
  347. if (!features) throw new Error('No features passed');
  348. if (!Array.isArray(features)) throw new Error('features must be an Array');
  349. if (bbox) validateBBox(bbox);
  350. if (id) validateId(id);
  351. // Main
  352. var fc = {type: 'FeatureCollection'};
  353. if (id) fc.id = id;
  354. if (bbox) fc.bbox = bbox;
  355. fc.features = features;
  356. return fc;
  357. }
  358. /**
  359. * Creates a {@link Feature<MultiLineString>} based on a
  360. * coordinate array. Properties can be added optionally.
  361. *
  362. * @name multiLineString
  363. * @param {Array<Array<Array<number>>>} coordinates an array of LineStrings
  364. * @param {Object} [properties={}] an Object of key-value pairs to add as properties
  365. * @param {Object} [options={}] Optional Parameters
  366. * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
  367. * @param {string|number} [options.id] Identifier associated with the Feature
  368. * @returns {Feature<MultiLineString>} a MultiLineString feature
  369. * @throws {Error} if no coordinates are passed
  370. * @example
  371. * var multiLine = turf.multiLineString([[[0,0],[10,10]]]);
  372. *
  373. * //=multiLine
  374. */
  375. function multiLineString(coordinates, properties, options) {
  376. if (!coordinates) throw new Error('coordinates is required');
  377. return feature({
  378. type: 'MultiLineString',
  379. coordinates: coordinates
  380. }, properties, options);
  381. }
  382. /**
  383. * Creates a {@link Feature<MultiPoint>} based on a
  384. * coordinate array. Properties can be added optionally.
  385. *
  386. * @name multiPoint
  387. * @param {Array<Array<number>>} coordinates an array of Positions
  388. * @param {Object} [properties={}] an Object of key-value pairs to add as properties
  389. * @param {Object} [options={}] Optional Parameters
  390. * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
  391. * @param {string|number} [options.id] Identifier associated with the Feature
  392. * @returns {Feature<MultiPoint>} a MultiPoint feature
  393. * @throws {Error} if no coordinates are passed
  394. * @example
  395. * var multiPt = turf.multiPoint([[0,0],[10,10]]);
  396. *
  397. * //=multiPt
  398. */
  399. function multiPoint(coordinates, properties, options) {
  400. if (!coordinates) throw new Error('coordinates is required');
  401. return feature({
  402. type: 'MultiPoint',
  403. coordinates: coordinates
  404. }, properties, options);
  405. }
  406. /**
  407. * Creates a {@link Feature<MultiPolygon>} based on a
  408. * coordinate array. Properties can be added optionally.
  409. *
  410. * @name multiPolygon
  411. * @param {Array<Array<Array<Array<number>>>>} coordinates an array of Polygons
  412. * @param {Object} [properties={}] an Object of key-value pairs to add as properties
  413. * @param {Object} [options={}] Optional Parameters
  414. * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
  415. * @param {string|number} [options.id] Identifier associated with the Feature
  416. * @returns {Feature<MultiPolygon>} a multipolygon feature
  417. * @throws {Error} if no coordinates are passed
  418. * @example
  419. * var multiPoly = turf.multiPolygon([[[[0,0],[0,10],[10,10],[10,0],[0,0]]]]);
  420. *
  421. * //=multiPoly
  422. *
  423. */
  424. function multiPolygon(coordinates, properties, options) {
  425. if (!coordinates) throw new Error('coordinates is required');
  426. return feature({
  427. type: 'MultiPolygon',
  428. coordinates: coordinates
  429. }, properties, options);
  430. }
  431. /**
  432. * Creates a {@link Feature<GeometryCollection>} based on a
  433. * coordinate array. Properties can be added optionally.
  434. *
  435. * @name geometryCollection
  436. * @param {Array<Geometry>} geometries an array of GeoJSON Geometries
  437. * @param {Object} [properties={}] an Object of key-value pairs to add as properties
  438. * @param {Object} [options={}] Optional Parameters
  439. * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
  440. * @param {string|number} [options.id] Identifier associated with the Feature
  441. * @returns {Feature<GeometryCollection>} a GeoJSON GeometryCollection Feature
  442. * @example
  443. * var pt = {
  444. * "type": "Point",
  445. * "coordinates": [100, 0]
  446. * };
  447. * var line = {
  448. * "type": "LineString",
  449. * "coordinates": [ [101, 0], [102, 1] ]
  450. * };
  451. * var collection = turf.geometryCollection([pt, line]);
  452. *
  453. * //=collection
  454. */
  455. function geometryCollection(geometries, properties, options) {
  456. if (!geometries) throw new Error('geometries is required');
  457. if (!Array.isArray(geometries)) throw new Error('geometries must be an Array');
  458. return feature({
  459. type: 'GeometryCollection',
  460. geometries: geometries
  461. }, properties, options);
  462. }
  463. /**
  464. * Round number to precision
  465. *
  466. * @param {number} num Number
  467. * @param {number} [precision=0] Precision
  468. * @returns {number} rounded number
  469. * @example
  470. * turf.round(120.4321)
  471. * //=120
  472. *
  473. * turf.round(120.4321, 2)
  474. * //=120.43
  475. */
  476. function round(num, precision) {
  477. if (num === undefined || num === null || isNaN(num)) throw new Error('num is required');
  478. if (precision && !(precision >= 0)) throw new Error('precision must be a positive number');
  479. var multiplier = Math.pow(10, precision || 0);
  480. return Math.round(num * multiplier) / multiplier;
  481. }
  482. /**
  483. * Convert a distance measurement (assuming a spherical Earth) from radians to a more friendly unit.
  484. * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet
  485. *
  486. * @name radiansToLength
  487. * @param {number} radians in radians across the sphere
  488. * @param {string} [units='kilometers'] can be degrees, radians, miles, or kilometers inches, yards, metres, meters, kilometres, kilometers.
  489. * @returns {number} distance
  490. */
  491. function radiansToLength(radians, units) {
  492. if (radians === undefined || radians === null) throw new Error('radians is required');
  493. if (units && typeof units !== 'string') throw new Error('units must be a string');
  494. var factor = factors[units || 'kilometers'];
  495. if (!factor) throw new Error(units + ' units is invalid');
  496. return radians * factor;
  497. }
  498. /**
  499. * Convert a distance measurement (assuming a spherical Earth) from a real-world unit into radians
  500. * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet
  501. *
  502. * @name lengthToRadians
  503. * @param {number} distance in real units
  504. * @param {string} [units='kilometers'] can be degrees, radians, miles, or kilometers inches, yards, metres, meters, kilometres, kilometers.
  505. * @returns {number} radians
  506. */
  507. function lengthToRadians(distance, units) {
  508. if (distance === undefined || distance === null) throw new Error('distance is required');
  509. if (units && typeof units !== 'string') throw new Error('units must be a string');
  510. var factor = factors[units || 'kilometers'];
  511. if (!factor) throw new Error(units + ' units is invalid');
  512. return distance / factor;
  513. }
  514. /**
  515. * Convert a distance measurement (assuming a spherical Earth) from a real-world unit into degrees
  516. * Valid units: miles, nauticalmiles, inches, yards, meters, metres, centimeters, kilometres, feet
  517. *
  518. * @name lengthToDegrees
  519. * @param {number} distance in real units
  520. * @param {string} [units='kilometers'] can be degrees, radians, miles, or kilometers inches, yards, metres, meters, kilometres, kilometers.
  521. * @returns {number} degrees
  522. */
  523. function lengthToDegrees(distance, units) {
  524. return radiansToDegrees(lengthToRadians(distance, units));
  525. }
  526. /**
  527. * Converts any bearing angle from the north line direction (positive clockwise)
  528. * and returns an angle between 0-360 degrees (positive clockwise), 0 being the north line
  529. *
  530. * @name bearingToAzimuth
  531. * @param {number} bearing angle, between -180 and +180 degrees
  532. * @returns {number} angle between 0 and 360 degrees
  533. */
  534. function bearingToAzimuth(bearing) {
  535. if (bearing === null || bearing === undefined) throw new Error('bearing is required');
  536. var angle = bearing % 360;
  537. if (angle < 0) angle += 360;
  538. return angle;
  539. }
  540. /**
  541. * Converts an angle in radians to degrees
  542. *
  543. * @name radiansToDegrees
  544. * @param {number} radians angle in radians
  545. * @returns {number} degrees between 0 and 360 degrees
  546. */
  547. function radiansToDegrees(radians) {
  548. if (radians === null || radians === undefined) throw new Error('radians is required');
  549. var degrees = radians % (2 * Math.PI);
  550. return degrees * 180 / Math.PI;
  551. }
  552. /**
  553. * Converts an angle in degrees to radians
  554. *
  555. * @name degreesToRadians
  556. * @param {number} degrees angle between 0 and 360 degrees
  557. * @returns {number} angle in radians
  558. */
  559. function degreesToRadians(degrees) {
  560. if (degrees === null || degrees === undefined) throw new Error('degrees is required');
  561. var radians = degrees % 360;
  562. return radians * Math.PI / 180;
  563. }
  564. /**
  565. * Converts a length to the requested unit.
  566. * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet
  567. *
  568. * @param {number} length to be converted
  569. * @param {string} originalUnit of the length
  570. * @param {string} [finalUnit='kilometers'] returned unit
  571. * @returns {number} the converted length
  572. */
  573. function convertLength(length, originalUnit, finalUnit) {
  574. if (length === null || length === undefined) throw new Error('length is required');
  575. if (!(length >= 0)) throw new Error('length must be a positive number');
  576. return radiansToLength(lengthToRadians(length, originalUnit), finalUnit || 'kilometers');
  577. }
  578. /**
  579. * Converts a area to the requested unit.
  580. * Valid units: kilometers, kilometres, meters, metres, centimetres, millimeters, acres, miles, yards, feet, inches
  581. * @param {number} area to be converted
  582. * @param {string} [originalUnit='meters'] of the distance
  583. * @param {string} [finalUnit='kilometers'] returned unit
  584. * @returns {number} the converted distance
  585. */
  586. function convertArea(area, originalUnit, finalUnit) {
  587. if (area === null || area === undefined) throw new Error('area is required');
  588. if (!(area >= 0)) throw new Error('area must be a positive number');
  589. var startFactor = areaFactors[originalUnit || 'meters'];
  590. if (!startFactor) throw new Error('invalid original units');
  591. var finalFactor = areaFactors[finalUnit || 'kilometers'];
  592. if (!finalFactor) throw new Error('invalid final units');
  593. return (area / startFactor) * finalFactor;
  594. }
  595. /**
  596. * isNumber
  597. *
  598. * @param {*} num Number to validate
  599. * @returns {boolean} true/false
  600. * @example
  601. * turf.isNumber(123)
  602. * //=true
  603. * turf.isNumber('foo')
  604. * //=false
  605. */
  606. function isNumber(num) {
  607. return !isNaN(num) && num !== null && !Array.isArray(num);
  608. }
  609. /**
  610. * isObject
  611. *
  612. * @param {*} input variable to validate
  613. * @returns {boolean} true/false
  614. * @example
  615. * turf.isObject({elevation: 10})
  616. * //=true
  617. * turf.isObject('foo')
  618. * //=false
  619. */
  620. function isObject(input) {
  621. return (!!input) && (input.constructor === Object);
  622. }
  623. /**
  624. * Validate BBox
  625. *
  626. * @private
  627. * @param {Array<number>} bbox BBox to validate
  628. * @returns {void}
  629. * @throws Error if BBox is not valid
  630. * @example
  631. * validateBBox([-180, -40, 110, 50])
  632. * //=OK
  633. * validateBBox([-180, -40])
  634. * //=Error
  635. * validateBBox('Foo')
  636. * //=Error
  637. * validateBBox(5)
  638. * //=Error
  639. * validateBBox(null)
  640. * //=Error
  641. * validateBBox(undefined)
  642. * //=Error
  643. */
  644. function validateBBox(bbox) {
  645. if (!bbox) throw new Error('bbox is required');
  646. if (!Array.isArray(bbox)) throw new Error('bbox must be an Array');
  647. if (bbox.length !== 4 && bbox.length !== 6) throw new Error('bbox must be an Array of 4 or 6 numbers');
  648. bbox.forEach(function (num) {
  649. if (!isNumber(num)) throw new Error('bbox must only contain numbers');
  650. });
  651. }
  652. /**
  653. * Validate Id
  654. *
  655. * @private
  656. * @param {string|number} id Id to validate
  657. * @returns {void}
  658. * @throws Error if Id is not valid
  659. * @example
  660. * validateId([-180, -40, 110, 50])
  661. * //=Error
  662. * validateId([-180, -40])
  663. * //=Error
  664. * validateId('Foo')
  665. * //=OK
  666. * validateId(5)
  667. * //=OK
  668. * validateId(null)
  669. * //=Error
  670. * validateId(undefined)
  671. * //=Error
  672. */
  673. function validateId(id) {
  674. if (!id) throw new Error('id is required');
  675. if (['string', 'number'].indexOf(typeof id) === -1) throw new Error('id must be a number or a string');
  676. }
  677. // Deprecated methods
  678. function radians2degrees() {
  679. throw new Error('method has been renamed to `radiansToDegrees`');
  680. }
  681. function degrees2radians() {
  682. throw new Error('method has been renamed to `degreesToRadians`');
  683. }
  684. function distanceToDegrees() {
  685. throw new Error('method has been renamed to `lengthToDegrees`');
  686. }
  687. function distanceToRadians() {
  688. throw new Error('method has been renamed to `lengthToRadians`');
  689. }
  690. function radiansToDistance() {
  691. throw new Error('method has been renamed to `radiansToLength`');
  692. }
  693. function bearingToAngle() {
  694. throw new Error('method has been renamed to `bearingToAzimuth`');
  695. }
  696. function convertDistance() {
  697. throw new Error('method has been renamed to `convertLength`');
  698. }
  699. var main_es$1 = Object.freeze({
  700. earthRadius: earthRadius,
  701. factors: factors,
  702. unitsFactors: unitsFactors,
  703. areaFactors: areaFactors,
  704. feature: feature,
  705. geometry: geometry,
  706. point: point,
  707. points: points,
  708. polygon: polygon,
  709. polygons: polygons,
  710. lineString: lineString,
  711. lineStrings: lineStrings,
  712. featureCollection: featureCollection,
  713. multiLineString: multiLineString,
  714. multiPoint: multiPoint,
  715. multiPolygon: multiPolygon,
  716. geometryCollection: geometryCollection,
  717. round: round,
  718. radiansToLength: radiansToLength,
  719. lengthToRadians: lengthToRadians,
  720. lengthToDegrees: lengthToDegrees,
  721. bearingToAzimuth: bearingToAzimuth,
  722. radiansToDegrees: radiansToDegrees,
  723. degreesToRadians: degreesToRadians,
  724. convertLength: convertLength,
  725. convertArea: convertArea,
  726. isNumber: isNumber,
  727. isObject: isObject,
  728. validateBBox: validateBBox,
  729. validateId: validateId,
  730. radians2degrees: radians2degrees,
  731. degrees2radians: degrees2radians,
  732. distanceToDegrees: distanceToDegrees,
  733. distanceToRadians: distanceToRadians,
  734. radiansToDistance: radiansToDistance,
  735. bearingToAngle: bearingToAngle,
  736. convertDistance: convertDistance
  737. });
  738. /**
  739. * Callback for coordEach
  740. *
  741. * @callback coordEachCallback
  742. * @param {Array<number>} currentCoord The current coordinate being processed.
  743. * @param {number} coordIndex The current index of the coordinate being processed.
  744. * @param {number} featureIndex The current index of the Feature being processed.
  745. * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.
  746. * @param {number} geometryIndex The current index of the Geometry being processed.
  747. */
  748. /**
  749. * Iterate over coordinates in any GeoJSON object, similar to Array.forEach()
  750. *
  751. * @name coordEach
  752. * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
  753. * @param {Function} callback a method that takes (currentCoord, coordIndex, featureIndex, multiFeatureIndex)
  754. * @param {boolean} [excludeWrapCoord=false] whether or not to include the final coordinate of LinearRings that wraps the ring in its iteration.
  755. * @example
  756. * var features = turf.featureCollection([
  757. * turf.point([26, 37], {"foo": "bar"}),
  758. * turf.point([36, 53], {"hello": "world"})
  759. * ]);
  760. *
  761. * turf.coordEach(features, function (currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) {
  762. * //=currentCoord
  763. * //=coordIndex
  764. * //=featureIndex
  765. * //=multiFeatureIndex
  766. * //=geometryIndex
  767. * });
  768. */
  769. function coordEach(geojson, callback, excludeWrapCoord) {
  770. // Handles null Geometry -- Skips this GeoJSON
  771. if (geojson === null) return;
  772. var j, k, l, geometry$$1, stopG, coords,
  773. geometryMaybeCollection,
  774. wrapShrink = 0,
  775. coordIndex = 0,
  776. isGeometryCollection,
  777. type = geojson.type,
  778. isFeatureCollection = type === 'FeatureCollection',
  779. isFeature = type === 'Feature',
  780. stop = isFeatureCollection ? geojson.features.length : 1;
  781. // This logic may look a little weird. The reason why it is that way
  782. // is because it's trying to be fast. GeoJSON supports multiple kinds
  783. // of objects at its root: FeatureCollection, Features, Geometries.
  784. // This function has the responsibility of handling all of them, and that
  785. // means that some of the `for` loops you see below actually just don't apply
  786. // to certain inputs. For instance, if you give this just a
  787. // Point geometry, then both loops are short-circuited and all we do
  788. // is gradually rename the input until it's called 'geometry'.
  789. //
  790. // This also aims to allocate as few resources as possible: just a
  791. // few numbers and booleans, rather than any temporary arrays as would
  792. // be required with the normalization approach.
  793. for (var featureIndex = 0; featureIndex < stop; featureIndex++) {
  794. geometryMaybeCollection = (isFeatureCollection ? geojson.features[featureIndex].geometry :
  795. (isFeature ? geojson.geometry : geojson));
  796. isGeometryCollection = (geometryMaybeCollection) ? geometryMaybeCollection.type === 'GeometryCollection' : false;
  797. stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;
  798. for (var geomIndex = 0; geomIndex < stopG; geomIndex++) {
  799. var multiFeatureIndex = 0;
  800. var geometryIndex = 0;
  801. geometry$$1 = isGeometryCollection ?
  802. geometryMaybeCollection.geometries[geomIndex] : geometryMaybeCollection;
  803. // Handles null Geometry -- Skips this geometry
  804. if (geometry$$1 === null) continue;
  805. coords = geometry$$1.coordinates;
  806. var geomType = geometry$$1.type;
  807. wrapShrink = (excludeWrapCoord && (geomType === 'Polygon' || geomType === 'MultiPolygon')) ? 1 : 0;
  808. switch (geomType) {
  809. case null:
  810. break;
  811. case 'Point':
  812. callback(coords, coordIndex, featureIndex, multiFeatureIndex, geometryIndex);
  813. coordIndex++;
  814. multiFeatureIndex++;
  815. break;
  816. case 'LineString':
  817. case 'MultiPoint':
  818. for (j = 0; j < coords.length; j++) {
  819. callback(coords[j], coordIndex, featureIndex, multiFeatureIndex, geometryIndex);
  820. coordIndex++;
  821. if (geomType === 'MultiPoint') multiFeatureIndex++;
  822. }
  823. if (geomType === 'LineString') multiFeatureIndex++;
  824. break;
  825. case 'Polygon':
  826. case 'MultiLineString':
  827. for (j = 0; j < coords.length; j++) {
  828. for (k = 0; k < coords[j].length - wrapShrink; k++) {
  829. callback(coords[j][k], coordIndex, featureIndex, multiFeatureIndex, geometryIndex);
  830. coordIndex++;
  831. }
  832. if (geomType === 'MultiLineString') multiFeatureIndex++;
  833. if (geomType === 'Polygon') geometryIndex++;
  834. }
  835. if (geomType === 'Polygon') multiFeatureIndex++;
  836. break;
  837. case 'MultiPolygon':
  838. for (j = 0; j < coords.length; j++) {
  839. if (geomType === 'MultiPolygon') geometryIndex = 0;
  840. for (k = 0; k < coords[j].length; k++) {
  841. for (l = 0; l < coords[j][k].length - wrapShrink; l++) {
  842. callback(coords[j][k][l], coordIndex, featureIndex, multiFeatureIndex, geometryIndex);
  843. coordIndex++;
  844. }
  845. geometryIndex++;
  846. }
  847. multiFeatureIndex++;
  848. }
  849. break;
  850. case 'GeometryCollection':
  851. for (j = 0; j < geometry$$1.geometries.length; j++)
  852. coordEach(geometry$$1.geometries[j], callback, excludeWrapCoord);
  853. break;
  854. default:
  855. throw new Error('Unknown Geometry Type');
  856. }
  857. }
  858. }
  859. }
  860. /**
  861. * Callback for coordReduce
  862. *
  863. * The first time the callback function is called, the values provided as arguments depend
  864. * on whether the reduce method has an initialValue argument.
  865. *
  866. * If an initialValue is provided to the reduce method:
  867. * - The previousValue argument is initialValue.
  868. * - The currentValue argument is the value of the first element present in the array.
  869. *
  870. * If an initialValue is not provided:
  871. * - The previousValue argument is the value of the first element present in the array.
  872. * - The currentValue argument is the value of the second element present in the array.
  873. *
  874. * @callback coordReduceCallback
  875. * @param {*} previousValue The accumulated value previously returned in the last invocation
  876. * of the callback, or initialValue, if supplied.
  877. * @param {Array<number>} currentCoord The current coordinate being processed.
  878. * @param {number} coordIndex The current index of the coordinate being processed.
  879. * Starts at index 0, if an initialValue is provided, and at index 1 otherwise.
  880. * @param {number} featureIndex The current index of the Feature being processed.
  881. * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.
  882. * @param {number} geometryIndex The current index of the Geometry being processed.
  883. */
  884. /**
  885. * Reduce coordinates in any GeoJSON object, similar to Array.reduce()
  886. *
  887. * @name coordReduce
  888. * @param {FeatureCollection|Geometry|Feature} geojson any GeoJSON object
  889. * @param {Function} callback a method that takes (previousValue, currentCoord, coordIndex)
  890. * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
  891. * @param {boolean} [excludeWrapCoord=false] whether or not to include the final coordinate of LinearRings that wraps the ring in its iteration.
  892. * @returns {*} The value that results from the reduction.
  893. * @example
  894. * var features = turf.featureCollection([
  895. * turf.point([26, 37], {"foo": "bar"}),
  896. * turf.point([36, 53], {"hello": "world"})
  897. * ]);
  898. *
  899. * turf.coordReduce(features, function (previousValue, currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) {
  900. * //=previousValue
  901. * //=currentCoord
  902. * //=coordIndex
  903. * //=featureIndex
  904. * //=multiFeatureIndex
  905. * //=geometryIndex
  906. * return currentCoord;
  907. * });
  908. */
  909. function coordReduce(geojson, callback, initialValue, excludeWrapCoord) {
  910. var previousValue = initialValue;
  911. coordEach(geojson, function (currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) {
  912. if (coordIndex === 0 && initialValue === undefined) previousValue = currentCoord;
  913. else previousValue = callback(previousValue, currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex);
  914. }, excludeWrapCoord);
  915. return previousValue;
  916. }
  917. /**
  918. * Callback for propEach
  919. *
  920. * @callback propEachCallback
  921. * @param {Object} currentProperties The current Properties being processed.
  922. * @param {number} featureIndex The current index of the Feature being processed.
  923. */
  924. /**
  925. * Iterate over properties in any GeoJSON object, similar to Array.forEach()
  926. *
  927. * @name propEach
  928. * @param {FeatureCollection|Feature} geojson any GeoJSON object
  929. * @param {Function} callback a method that takes (currentProperties, featureIndex)
  930. * @example
  931. * var features = turf.featureCollection([
  932. * turf.point([26, 37], {foo: 'bar'}),
  933. * turf.point([36, 53], {hello: 'world'})
  934. * ]);
  935. *
  936. * turf.propEach(features, function (currentProperties, featureIndex) {
  937. * //=currentProperties
  938. * //=featureIndex
  939. * });
  940. */
  941. function propEach(geojson, callback) {
  942. var i;
  943. switch (geojson.type) {
  944. case 'FeatureCollection':
  945. for (i = 0; i < geojson.features.length; i++) {
  946. callback(geojson.features[i].properties, i);
  947. }
  948. break;
  949. case 'Feature':
  950. callback(geojson.properties, 0);
  951. break;
  952. }
  953. }
  954. /**
  955. * Callback for propReduce
  956. *
  957. * The first time the callback function is called, the values provided as arguments depend
  958. * on whether the reduce method has an initialValue argument.
  959. *
  960. * If an initialValue is provided to the reduce method:
  961. * - The previousValue argument is initialValue.
  962. * - The currentValue argument is the value of the first element present in the array.
  963. *
  964. * If an initialValue is not provided:
  965. * - The previousValue argument is the value of the first element present in the array.
  966. * - The currentValue argument is the value of the second element present in the array.
  967. *
  968. * @callback propReduceCallback
  969. * @param {*} previousValue The accumulated value previously returned in the last invocation
  970. * of the callback, or initialValue, if supplied.
  971. * @param {*} currentProperties The current Properties being processed.
  972. * @param {number} featureIndex The current index of the Feature being processed.
  973. */
  974. /**
  975. * Reduce properties in any GeoJSON object into a single value,
  976. * similar to how Array.reduce works. However, in this case we lazily run
  977. * the reduction, so an array of all properties is unnecessary.
  978. *
  979. * @name propReduce
  980. * @param {FeatureCollection|Feature} geojson any GeoJSON object
  981. * @param {Function} callback a method that takes (previousValue, currentProperties, featureIndex)
  982. * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
  983. * @returns {*} The value that results from the reduction.
  984. * @example
  985. * var features = turf.featureCollection([
  986. * turf.point([26, 37], {foo: 'bar'}),
  987. * turf.point([36, 53], {hello: 'world'})
  988. * ]);
  989. *
  990. * turf.propReduce(features, function (previousValue, currentProperties, featureIndex) {
  991. * //=previousValue
  992. * //=currentProperties
  993. * //=featureIndex
  994. * return currentProperties
  995. * });
  996. */
  997. function propReduce(geojson, callback, initialValue) {
  998. var previousValue = initialValue;
  999. propEach(geojson, function (currentProperties, featureIndex) {
  1000. if (featureIndex === 0 && initialValue === undefined) previousValue = currentProperties;
  1001. else previousValue = callback(previousValue, currentProperties, featureIndex);
  1002. });
  1003. return previousValue;
  1004. }
  1005. /**
  1006. * Callback for featureEach
  1007. *
  1008. * @callback featureEachCallback
  1009. * @param {Feature<any>} currentFeature The current Feature being processed.
  1010. * @param {number} featureIndex The current index of the Feature being processed.
  1011. */
  1012. /**
  1013. * Iterate over features in any GeoJSON object, similar to
  1014. * Array.forEach.
  1015. *
  1016. * @name featureEach
  1017. * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
  1018. * @param {Function} callback a method that takes (currentFeature, featureIndex)
  1019. * @example
  1020. * var features = turf.featureCollection([
  1021. * turf.point([26, 37], {foo: 'bar'}),
  1022. * turf.point([36, 53], {hello: 'world'})
  1023. * ]);
  1024. *
  1025. * turf.featureEach(features, function (currentFeature, featureIndex) {
  1026. * //=currentFeature
  1027. * //=featureIndex
  1028. * });
  1029. */
  1030. function featureEach(geojson, callback) {
  1031. if (geojson.type === 'Feature') {
  1032. callback(geojson, 0);
  1033. } else if (geojson.type === 'FeatureCollection') {
  1034. for (var i = 0; i < geojson.features.length; i++) {
  1035. callback(geojson.features[i], i);
  1036. }
  1037. }
  1038. }
  1039. /**
  1040. * Callback for featureReduce
  1041. *
  1042. * The first time the callback function is called, the values provided as arguments depend
  1043. * on whether the reduce method has an initialValue argument.
  1044. *
  1045. * If an initialValue is provided to the reduce method:
  1046. * - The previousValue argument is initialValue.
  1047. * - The currentValue argument is the value of the first element present in the array.
  1048. *
  1049. * If an initialValue is not provided:
  1050. * - The previousValue argument is the value of the first element present in the array.
  1051. * - The currentValue argument is the value of the second element present in the array.
  1052. *
  1053. * @callback featureReduceCallback
  1054. * @param {*} previousValue The accumulated value previously returned in the last invocation
  1055. * of the callback, or initialValue, if supplied.
  1056. * @param {Feature} currentFeature The current Feature being processed.
  1057. * @param {number} featureIndex The current index of the Feature being processed.
  1058. */
  1059. /**
  1060. * Reduce features in any GeoJSON object, similar to Array.reduce().
  1061. *
  1062. * @name featureReduce
  1063. * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
  1064. * @param {Function} callback a method that takes (previousValue, currentFeature, featureIndex)
  1065. * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
  1066. * @returns {*} The value that results from the reduction.
  1067. * @example
  1068. * var features = turf.featureCollection([
  1069. * turf.point([26, 37], {"foo": "bar"}),
  1070. * turf.point([36, 53], {"hello": "world"})
  1071. * ]);
  1072. *
  1073. * turf.featureReduce(features, function (previousValue, currentFeature, featureIndex) {
  1074. * //=previousValue
  1075. * //=currentFeature
  1076. * //=featureIndex
  1077. * return currentFeature
  1078. * });
  1079. */
  1080. function featureReduce(geojson, callback, initialValue) {
  1081. var previousValue = initialValue;
  1082. featureEach(geojson, function (currentFeature, featureIndex) {
  1083. if (featureIndex === 0 && initialValue === undefined) previousValue = currentFeature;
  1084. else previousValue = callback(previousValue, currentFeature, featureIndex);
  1085. });
  1086. return previousValue;
  1087. }
  1088. /**
  1089. * Get all coordinates from any GeoJSON object.
  1090. *
  1091. * @name coordAll
  1092. * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
  1093. * @returns {Array<Array<number>>} coordinate position array
  1094. * @example
  1095. * var features = turf.featureCollection([
  1096. * turf.point([26, 37], {foo: 'bar'}),
  1097. * turf.point([36, 53], {hello: 'world'})
  1098. * ]);
  1099. *
  1100. * var coords = turf.coordAll(features);
  1101. * //= [[26, 37], [36, 53]]
  1102. */
  1103. function coordAll(geojson) {
  1104. var coords = [];
  1105. coordEach(geojson, function (coord) {
  1106. coords.push(coord);
  1107. });
  1108. return coords;
  1109. }
  1110. /**
  1111. * Callback for geomEach
  1112. *
  1113. * @callback geomEachCallback
  1114. * @param {Geometry} currentGeometry The current Geometry being processed.
  1115. * @param {number} featureIndex The current index of the Feature being processed.
  1116. * @param {Object} featureProperties The current Feature Properties being processed.
  1117. * @param {Array<number>} featureBBox The current Feature BBox being processed.
  1118. * @param {number|string} featureId The current Feature Id being processed.
  1119. */
  1120. /**
  1121. * Iterate over each geometry in any GeoJSON object, similar to Array.forEach()
  1122. *
  1123. * @name geomEach
  1124. * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
  1125. * @param {Function} callback a method that takes (currentGeometry, featureIndex, featureProperties, featureBBox, featureId)
  1126. * @example
  1127. * var features = turf.featureCollection([
  1128. * turf.point([26, 37], {foo: 'bar'}),
  1129. * turf.point([36, 53], {hello: 'world'})
  1130. * ]);
  1131. *
  1132. * turf.geomEach(features, function (currentGeometry, featureIndex, featureProperties, featureBBox, featureId) {
  1133. * //=currentGeometry
  1134. * //=featureIndex
  1135. * //=featureProperties
  1136. * //=featureBBox
  1137. * //=featureId
  1138. * });
  1139. */
  1140. function geomEach(geojson, callback) {
  1141. var i, j, g, geometry$$1, stopG,
  1142. geometryMaybeCollection,
  1143. isGeometryCollection,
  1144. featureProperties,
  1145. featureBBox,
  1146. featureId,
  1147. featureIndex = 0,
  1148. isFeatureCollection = geojson.type === 'FeatureCollection',
  1149. isFeature = geojson.type === 'Feature',
  1150. stop = isFeatureCollection ? geojson.features.length : 1;
  1151. // This logic may look a little weird. The reason why it is that way
  1152. // is because it's trying to be fast. GeoJSON supports multiple kinds
  1153. // of objects at its root: FeatureCollection, Features, Geometries.
  1154. // This function has the responsibility of handling all of them, and that
  1155. // means that some of the `for` loops you see below actually just don't apply
  1156. // to certain inputs. For instance, if you give this just a
  1157. // Point geometry, then both loops are short-circuited and all we do
  1158. // is gradually rename the input until it's called 'geometry'.
  1159. //
  1160. // This also aims to allocate as few resources as possible: just a
  1161. // few numbers and booleans, rather than any temporary arrays as would
  1162. // be required with the normalization approach.
  1163. for (i = 0; i < stop; i++) {
  1164. geometryMaybeCollection = (isFeatureCollection ? geojson.features[i].geometry :
  1165. (isFeature ? geojson.geometry : geojson));
  1166. featureProperties = (isFeatureCollection ? geojson.features[i].properties :
  1167. (isFeature ? geojson.properties : {}));
  1168. featureBBox = (isFeatureCollection ? geojson.features[i].bbox :
  1169. (isFeature ? geojson.bbox : undefined));
  1170. featureId = (isFeatureCollection ? geojson.features[i].id :
  1171. (isFeature ? geojson.id : undefined));
  1172. isGeometryCollection = (geometryMaybeCollection) ? geometryMaybeCollection.type === 'GeometryCollection' : false;
  1173. stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;
  1174. for (g = 0; g < stopG; g++) {
  1175. geometry$$1 = isGeometryCollection ?
  1176. geometryMaybeCollection.geometries[g] : geometryMaybeCollection;
  1177. // Handle null Geometry
  1178. if (geometry$$1 === null) {
  1179. callback(null, featureIndex, featureProperties, featureBBox, featureId);
  1180. continue;
  1181. }
  1182. switch (geometry$$1.type) {
  1183. case 'Point':
  1184. case 'LineString':
  1185. case 'MultiPoint':
  1186. case 'Polygon':
  1187. case 'MultiLineString':
  1188. case 'MultiPolygon': {
  1189. callback(geometry$$1, featureIndex, featureProperties, featureBBox, featureId);
  1190. break;
  1191. }
  1192. case 'GeometryCollection': {
  1193. for (j = 0; j < geometry$$1.geometries.length; j++) {
  1194. callback(geometry$$1.geometries[j], featureIndex, featureProperties, featureBBox, featureId);
  1195. }
  1196. break;
  1197. }
  1198. default:
  1199. throw new Error('Unknown Geometry Type');
  1200. }
  1201. }
  1202. // Only increase `featureIndex` per each feature
  1203. featureIndex++;
  1204. }
  1205. }
  1206. /**
  1207. * Callback for geomReduce
  1208. *
  1209. * The first time the callback function is called, the values provided as arguments depend
  1210. * on whether the reduce method has an initialValue argument.
  1211. *
  1212. * If an initialValue is provided to the reduce method:
  1213. * - The previousValue argument is initialValue.
  1214. * - The currentValue argument is the value of the first element present in the array.
  1215. *
  1216. * If an initialValue is not provided:
  1217. * - The previousValue argument is the value of the first element present in the array.
  1218. * - The currentValue argument is the value of the second element present in the array.
  1219. *
  1220. * @callback geomReduceCallback
  1221. * @param {*} previousValue The accumulated value previously returned in the last invocation
  1222. * of the callback, or initialValue, if supplied.
  1223. * @param {Geometry} currentGeometry The current Geometry being processed.
  1224. * @param {number} featureIndex The current index of the Feature being processed.
  1225. * @param {Object} featureProperties The current Feature Properties being processed.
  1226. * @param {Array<number>} featureBBox The current Feature BBox being processed.
  1227. * @param {number|string} featureId The current Feature Id being processed.
  1228. */
  1229. /**
  1230. * Reduce geometry in any GeoJSON object, similar to Array.reduce().
  1231. *
  1232. * @name geomReduce
  1233. * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
  1234. * @param {Function} callback a method that takes (previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId)
  1235. * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
  1236. * @returns {*} The value that results from the reduction.
  1237. * @example
  1238. * var features = turf.featureCollection([
  1239. * turf.point([26, 37], {foo: 'bar'}),
  1240. * turf.point([36, 53], {hello: 'world'})
  1241. * ]);
  1242. *
  1243. * turf.geomReduce(features, function (previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId) {
  1244. * //=previousValue
  1245. * //=currentGeometry
  1246. * //=featureIndex
  1247. * //=featureProperties
  1248. * //=featureBBox
  1249. * //=featureId
  1250. * return currentGeometry
  1251. * });
  1252. */
  1253. function geomReduce(geojson, callback, initialValue) {
  1254. var previousValue = initialValue;
  1255. geomEach(geojson, function (currentGeometry, featureIndex, featureProperties, featureBBox, featureId) {
  1256. if (featureIndex === 0 && initialValue === undefined) previousValue = currentGeometry;
  1257. else previousValue = callback(previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId);
  1258. });
  1259. return previousValue;
  1260. }
  1261. /**
  1262. * Callback for flattenEach
  1263. *
  1264. * @callback flattenEachCallback
  1265. * @param {Feature} currentFeature The current flattened feature being processed.
  1266. * @param {number} featureIndex The current index of the Feature being processed.
  1267. * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.
  1268. */
  1269. /**
  1270. * Iterate over flattened features in any GeoJSON object, similar to
  1271. * Array.forEach.
  1272. *
  1273. * @name flattenEach
  1274. * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
  1275. * @param {Function} callback a method that takes (currentFeature, featureIndex, multiFeatureIndex)
  1276. * @example
  1277. * var features = turf.featureCollection([
  1278. * turf.point([26, 37], {foo: 'bar'}),
  1279. * turf.multiPoint([[40, 30], [36, 53]], {hello: 'world'})
  1280. * ]);
  1281. *
  1282. * turf.flattenEach(features, function (currentFeature, featureIndex, multiFeatureIndex) {
  1283. * //=currentFeature
  1284. * //=featureIndex
  1285. * //=multiFeatureIndex
  1286. * });
  1287. */
  1288. function flattenEach(geojson, callback) {
  1289. geomEach(geojson, function (geometry$$1, featureIndex, properties, bbox, id) {
  1290. // Callback for single geometry
  1291. var type = (geometry$$1 === null) ? null : geometry$$1.type;
  1292. switch (type) {
  1293. case null:
  1294. case 'Point':
  1295. case 'LineString':
  1296. case 'Polygon':
  1297. callback(feature(geometry$$1, properties, {bbox: bbox, id: id}), featureIndex, 0);
  1298. return;
  1299. }
  1300. var geomType;
  1301. // Callback for multi-geometry
  1302. switch (type) {
  1303. case 'MultiPoint':
  1304. geomType = 'Point';
  1305. break;
  1306. case 'MultiLineString':
  1307. geomType = 'LineString';
  1308. break;
  1309. case 'MultiPolygon':
  1310. geomType = 'Polygon';
  1311. break;
  1312. }
  1313. geometry$$1.coordinates.forEach(function (coordinate, multiFeatureIndex) {
  1314. var geom = {
  1315. type: geomType,
  1316. coordinates: coordinate
  1317. };
  1318. callback(feature(geom, properties), featureIndex, multiFeatureIndex);
  1319. });
  1320. });
  1321. }
  1322. /**
  1323. * Callback for flattenReduce
  1324. *
  1325. * The first time the callback function is called, the values provided as arguments depend
  1326. * on whether the reduce method has an initialValue argument.
  1327. *
  1328. * If an initialValue is provided to the reduce method:
  1329. * - The previousValue argument is initialValue.
  1330. * - The currentValue argument is the value of the first element present in the array.
  1331. *
  1332. * If an initialValue is not provided:
  1333. * - The previousValue argument is the value of the first element present in the array.
  1334. * - The currentValue argument is the value of the second element present in the array.
  1335. *
  1336. * @callback flattenReduceCallback
  1337. * @param {*} previousValue The accumulated value previously returned in the last invocation
  1338. * of the callback, or initialValue, if supplied.
  1339. * @param {Feature} currentFeature The current Feature being processed.
  1340. * @param {number} featureIndex The current index of the Feature being processed.
  1341. * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.
  1342. */
  1343. /**
  1344. * Reduce flattened features in any GeoJSON object, similar to Array.reduce().
  1345. *
  1346. * @name flattenReduce
  1347. * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
  1348. * @param {Function} callback a method that takes (previousValue, currentFeature, featureIndex, multiFeatureIndex)
  1349. * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
  1350. * @returns {*} The value that results from the reduction.
  1351. * @example
  1352. * var features = turf.featureCollection([
  1353. * turf.point([26, 37], {foo: 'bar'}),
  1354. * turf.multiPoint([[40, 30], [36, 53]], {hello: 'world'})
  1355. * ]);
  1356. *
  1357. * turf.flattenReduce(features, function (previousValue, currentFeature, featureIndex, multiFeatureIndex) {
  1358. * //=previousValue
  1359. * //=currentFeature
  1360. * //=featureIndex
  1361. * //=multiFeatureIndex
  1362. * return currentFeature
  1363. * });
  1364. */
  1365. function flattenReduce(geojson, callback, initialValue) {
  1366. var previousValue = initialValue;
  1367. flattenEach(geojson, function (currentFeature, featureIndex, multiFeatureIndex) {
  1368. if (featureIndex === 0 && multiFeatureIndex === 0 && initialValue === undefined) previousValue = currentFeature;
  1369. else previousValue = callback(previousValue, currentFeature, featureIndex, multiFeatureIndex);
  1370. });
  1371. return previousValue;
  1372. }
  1373. /**
  1374. * Callback for segmentEach
  1375. *
  1376. * @callback segmentEachCallback
  1377. * @param {Feature<LineString>} currentSegment The current Segment being processed.
  1378. * @param {number} featureIndex The current index of the Feature being processed.
  1379. * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.
  1380. * @param {number} geometryIndex The current index of the Geometry being processed.
  1381. * @param {number} segmentIndex The current index of the Segment being processed.
  1382. * @returns {void}
  1383. */
  1384. /**
  1385. * Iterate over 2-vertex line segment in any GeoJSON object, similar to Array.forEach()
  1386. * (Multi)Point geometries do not contain segments therefore they are ignored during this operation.
  1387. *
  1388. * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON
  1389. * @param {Function} callback a method that takes (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex)
  1390. * @returns {void}
  1391. * @example
  1392. * var polygon = turf.polygon([[[-50, 5], [-40, -10], [-50, -10], [-40, 5], [-50, 5]]]);
  1393. *
  1394. * // Iterate over GeoJSON by 2-vertex segments
  1395. * turf.segmentEach(polygon, function (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) {
  1396. * //=currentSegment
  1397. * //=featureIndex
  1398. * //=multiFeatureIndex
  1399. * //=geometryIndex
  1400. * //=segmentIndex
  1401. * });
  1402. *
  1403. * // Calculate the total number of segments
  1404. * var total = 0;
  1405. * turf.segmentEach(polygon, function () {
  1406. * total++;
  1407. * });
  1408. */
  1409. function segmentEach(geojson, callback) {
  1410. flattenEach(geojson, function (feature$$1, featureIndex, multiFeatureIndex) {
  1411. var segmentIndex = 0;
  1412. // Exclude null Geometries
  1413. if (!feature$$1.geometry) return;
  1414. // (Multi)Point geometries do not contain segments therefore they are ignored during this operation.
  1415. var type = feature$$1.geometry.type;
  1416. if (type === 'Point' || type === 'MultiPoint') return;
  1417. // Generate 2-vertex line segments
  1418. coordReduce(feature$$1, function (previousCoords, currentCoord, coordIndex, featureIndexCoord, mutliPartIndexCoord, geometryIndex) {
  1419. var currentSegment = lineString([previousCoords, currentCoord], feature$$1.properties);
  1420. callback(currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex);
  1421. segmentIndex++;
  1422. return currentCoord;
  1423. });
  1424. });
  1425. }
  1426. /**
  1427. * Callback for segmentReduce
  1428. *
  1429. * The first time the callback function is called, the values provided as arguments depend
  1430. * on whether the reduce method has an initialValue argument.
  1431. *
  1432. * If an initialValue is provided to the reduce method:
  1433. * - The previousValue argument is initialValue.
  1434. * - The currentValue argument is the value of the first element present in the array.
  1435. *
  1436. * If an initialValue is not provided:
  1437. * - The previousValue argument is the value of the first element present in the array.
  1438. * - The currentValue argument is the value of the second element present in the array.
  1439. *
  1440. * @callback segmentReduceCallback
  1441. * @param {*} previousValue The accumulated value previously returned in the last invocation
  1442. * of the callback, or initialValue, if supplied.
  1443. * @param {Feature<LineString>} currentSegment The current Segment being processed.
  1444. * @param {number} featureIndex The current index of the Feature being processed.
  1445. * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.
  1446. * @param {number} geometryIndex The current index of the Geometry being processed.
  1447. * @param {number} segmentIndex The current index of the Segment being processed.
  1448. */
  1449. /**
  1450. * Reduce 2-vertex line segment in any GeoJSON object, similar to Array.reduce()
  1451. * (Multi)Point geometries do not contain segments therefore they are ignored during this operation.
  1452. *
  1453. * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON
  1454. * @param {Function} callback a method that takes (previousValue, currentSegment, currentIndex)
  1455. * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
  1456. * @returns {void}
  1457. * @example
  1458. * var polygon = turf.polygon([[[-50, 5], [-40, -10], [-50, -10], [-40, 5], [-50, 5]]]);
  1459. *
  1460. * // Iterate over GeoJSON by 2-vertex segments
  1461. * turf.segmentReduce(polygon, function (previousSegment, currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) {
  1462. * //= previousSegment
  1463. * //= currentSegment
  1464. * //= featureIndex
  1465. * //= multiFeatureIndex
  1466. * //= geometryIndex
  1467. * //= segmentInex
  1468. * return currentSegment
  1469. * });
  1470. *
  1471. * // Calculate the total number of segments
  1472. * var initialValue = 0
  1473. * var total = turf.segmentReduce(polygon, function (previousValue) {
  1474. * previousValue++;
  1475. * return previousValue;
  1476. * }, initialValue);
  1477. */
  1478. function segmentReduce(geojson, callback, initialValue) {
  1479. var previousValue = initialValue;
  1480. var started = false;
  1481. segmentEach(geojson, function (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) {
  1482. if (started === false && initialValue === undefined) previousValue = currentSegment;
  1483. else previousValue = callback(previousValue, currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex);
  1484. started = true;
  1485. });
  1486. return previousValue;
  1487. }
  1488. /**
  1489. * Callback for lineEach
  1490. *
  1491. * @callback lineEachCallback
  1492. * @param {Feature<LineString>} currentLine The current LineString|LinearRing being processed
  1493. * @param {number} featureIndex The current index of the Feature being processed
  1494. * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed
  1495. * @param {number} geometryIndex The current index of the Geometry being processed
  1496. */
  1497. /**
  1498. * Iterate over line or ring coordinates in LineString, Polygon, MultiLineString, MultiPolygon Features or Geometries,
  1499. * similar to Array.forEach.
  1500. *
  1501. * @name lineEach
  1502. * @param {Geometry|Feature<LineString|Polygon|MultiLineString|MultiPolygon>} geojson object
  1503. * @param {Function} callback a method that takes (currentLine, featureIndex, multiFeatureIndex, geometryIndex)
  1504. * @example
  1505. * var multiLine = turf.multiLineString([
  1506. * [[26, 37], [35, 45]],
  1507. * [[36, 53], [38, 50], [41, 55]]
  1508. * ]);
  1509. *
  1510. * turf.lineEach(multiLine, function (currentLine, featureIndex, multiFeatureIndex, geometryIndex) {
  1511. * //=currentLine
  1512. * //=featureIndex
  1513. * //=multiFeatureIndex
  1514. * //=geometryIndex
  1515. * });
  1516. */
  1517. function lineEach(geojson, callback) {
  1518. // validation
  1519. if (!geojson) throw new Error('geojson is required');
  1520. flattenEach(geojson, function (feature$$1, featureIndex, multiFeatureIndex) {
  1521. if (feature$$1.geometry === null) return;
  1522. var type = feature$$1.geometry.type;
  1523. var coords = feature$$1.geometry.coordinates;
  1524. switch (type) {
  1525. case 'LineString':
  1526. callback(feature$$1, featureIndex, multiFeatureIndex, 0, 0);
  1527. break;
  1528. case 'Polygon':
  1529. for (var geometryIndex = 0; geometryIndex < coords.length; geometryIndex++) {
  1530. callback(lineString(coords[geometryIndex], feature$$1.properties), featureIndex, multiFeatureIndex, geometryIndex);
  1531. }
  1532. break;
  1533. }
  1534. });
  1535. }
  1536. /**
  1537. * Callback for lineReduce
  1538. *
  1539. * The first time the callback function is called, the values provided as arguments depend
  1540. * on whether the reduce method has an initialValue argument.
  1541. *
  1542. * If an initialValue is provided to the reduce method:
  1543. * - The previousValue argument is initialValue.
  1544. * - The currentValue argument is the value of the first element present in the array.
  1545. *
  1546. * If an initialValue is not provided:
  1547. * - The previousValue argument is the value of the first element present in the array.
  1548. * - The currentValue argument is the value of the second element present in the array.
  1549. *
  1550. * @callback lineReduceCallback
  1551. * @param {*} previousValue The accumulated value previously returned in the last invocation
  1552. * of the callback, or initialValue, if supplied.
  1553. * @param {Feature<LineString>} currentLine The current LineString|LinearRing being processed.
  1554. * @param {number} featureIndex The current index of the Feature being processed
  1555. * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed
  1556. * @param {number} geometryIndex The current index of the Geometry being processed
  1557. */
  1558. /**
  1559. * Reduce features in any GeoJSON object, similar to Array.reduce().
  1560. *
  1561. * @name lineReduce
  1562. * @param {Geometry|Feature<LineString|Polygon|MultiLineString|MultiPolygon>} geojson object
  1563. * @param {Function} callback a method that takes (previousValue, currentLine, featureIndex, multiFeatureIndex, geometryIndex)
  1564. * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
  1565. * @returns {*} The value that results from the reduction.
  1566. * @example
  1567. * var multiPoly = turf.multiPolygon([
  1568. * turf.polygon([[[12,48],[2,41],[24,38],[12,48]], [[9,44],[13,41],[13,45],[9,44]]]),
  1569. * turf.polygon([[[5, 5], [0, 0], [2, 2], [4, 4], [5, 5]]])
  1570. * ]);
  1571. *
  1572. * turf.lineReduce(multiPoly, function (previousValue, currentLine, featureIndex, multiFeatureIndex, geometryIndex) {
  1573. * //=previousValue
  1574. * //=currentLine
  1575. * //=featureIndex
  1576. * //=multiFeatureIndex
  1577. * //=geometryIndex
  1578. * return currentLine
  1579. * });
  1580. */
  1581. function lineReduce(geojson, callback, initialValue) {
  1582. var previousValue = initialValue;
  1583. lineEach(geojson, function (currentLine, featureIndex, multiFeatureIndex, geometryIndex) {
  1584. if (featureIndex === 0 && initialValue === undefined) previousValue = currentLine;
  1585. else previousValue = callback(previousValue, currentLine, featureIndex, multiFeatureIndex, geometryIndex);
  1586. });
  1587. return previousValue;
  1588. }
  1589. var main_es = Object.freeze({
  1590. coordEach: coordEach,
  1591. coordReduce: coordReduce,
  1592. propEach: propEach,
  1593. propReduce: propReduce,
  1594. featureEach: featureEach,
  1595. featureReduce: featureReduce,
  1596. coordAll: coordAll,
  1597. geomEach: geomEach,
  1598. geomReduce: geomReduce,
  1599. flattenEach: flattenEach,
  1600. flattenReduce: flattenReduce,
  1601. segmentEach: segmentEach,
  1602. segmentReduce: segmentReduce,
  1603. lineEach: lineEach,
  1604. lineReduce: lineReduce
  1605. });
  1606. /**
  1607. * Takes a set of features, calculates the bbox of all input features, and returns a bounding box.
  1608. *
  1609. * @name bbox
  1610. * @param {GeoJSON} geojson any GeoJSON object
  1611. * @returns {BBox} bbox extent in [minX, minY, maxX, maxY] order
  1612. * @example
  1613. * var line = turf.lineString([[-74, 40], [-78, 42], [-82, 35]]);
  1614. * var bbox = turf.bbox(line);
  1615. * var bboxPolygon = turf.bboxPolygon(bbox);
  1616. *
  1617. * //addToMap
  1618. * var addToMap = [line, bboxPolygon]
  1619. */
  1620. function bbox(geojson) {
  1621. var BBox = [Infinity, Infinity, -Infinity, -Infinity];
  1622. coordEach(geojson, function (coord) {
  1623. if (BBox[0] > coord[0]) BBox[0] = coord[0];
  1624. if (BBox[1] > coord[1]) BBox[1] = coord[1];
  1625. if (BBox[2] < coord[0]) BBox[2] = coord[0];
  1626. if (BBox[3] < coord[1]) BBox[3] = coord[1];
  1627. });
  1628. return BBox;
  1629. }
  1630. /**
  1631. * Unwrap a coordinate from a Point Feature, Geometry or a single coordinate.
  1632. *
  1633. * @name getCoord
  1634. * @param {Array<number>|Geometry<Point>|Feature<Point>} obj Object
  1635. * @returns {Array<number>} coordinates
  1636. * @example
  1637. * var pt = turf.point([10, 10]);
  1638. *
  1639. * var coord = turf.getCoord(pt);
  1640. * //= [10, 10]
  1641. */
  1642. function getCoord(obj) {
  1643. if (!obj) throw new Error('obj is required');
  1644. var coordinates = getCoords(obj);
  1645. // getCoord() must contain at least two numbers (Point)
  1646. if (coordinates.length > 1 && isNumber(coordinates[0]) && isNumber(coordinates[1])) {
  1647. return coordinates;
  1648. } else {
  1649. throw new Error('Coordinate is not a valid Point');
  1650. }
  1651. }
  1652. /**
  1653. * Unwrap coordinates from a Feature, Geometry Object or an Array of numbers
  1654. *
  1655. * @name getCoords
  1656. * @param {Array<number>|Geometry|Feature} obj Object
  1657. * @returns {Array<number>} coordinates
  1658. * @example
  1659. * var poly = turf.polygon([[[119.32, -8.7], [119.55, -8.69], [119.51, -8.54], [119.32, -8.7]]]);
  1660. *
  1661. * var coord = turf.getCoords(poly);
  1662. * //= [[[119.32, -8.7], [119.55, -8.69], [119.51, -8.54], [119.32, -8.7]]]
  1663. */
  1664. function getCoords(obj) {
  1665. if (!obj) throw new Error('obj is required');
  1666. var coordinates;
  1667. // Array of numbers
  1668. if (obj.length) {
  1669. coordinates = obj;
  1670. // Geometry Object
  1671. } else if (obj.coordinates) {
  1672. coordinates = obj.coordinates;
  1673. // Feature
  1674. } else if (obj.geometry && obj.geometry.coordinates) {
  1675. coordinates = obj.geometry.coordinates;
  1676. }
  1677. // Checks if coordinates contains a number
  1678. if (coordinates) {
  1679. containsNumber(coordinates);
  1680. return coordinates;
  1681. }
  1682. throw new Error('No valid coordinates');
  1683. }
  1684. /**
  1685. * Checks if coordinates contains a number
  1686. *
  1687. * @name containsNumber
  1688. * @param {Array<any>} coordinates GeoJSON Coordinates
  1689. * @returns {boolean} true if Array contains a number
  1690. */
  1691. function containsNumber(coordinates) {
  1692. if (coordinates.length > 1 && isNumber(coordinates[0]) && isNumber(coordinates[1])) {
  1693. return true;
  1694. }
  1695. if (Array.isArray(coordinates[0]) && coordinates[0].length) {
  1696. return containsNumber(coordinates[0]);
  1697. }
  1698. throw new Error('coordinates must only contain numbers');
  1699. }
  1700. /**
  1701. * Enforce expectations about types of GeoJSON objects for Turf.
  1702. *
  1703. * @name geojsonType
  1704. * @param {GeoJSON} value any GeoJSON object
  1705. * @param {string} type expected GeoJSON type
  1706. * @param {string} name name of calling function
  1707. * @throws {Error} if value is not the expected type.
  1708. */
  1709. function geojsonType(value, type, name) {
  1710. if (!type || !name) throw new Error('type and name required');
  1711. if (!value || value.type !== type) {
  1712. throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + value.type);
  1713. }
  1714. }
  1715. /**
  1716. * Enforce expectations about types of {@link Feature} inputs for Turf.
  1717. * Internally this uses {@link geojsonType} to judge geometry types.
  1718. *
  1719. * @name featureOf
  1720. * @param {Feature} feature a feature with an expected geometry type
  1721. * @param {string} type expected GeoJSON type
  1722. * @param {string} name name of calling function
  1723. * @throws {Error} error if value is not the expected type.
  1724. */
  1725. function featureOf(feature$$1, type, name) {
  1726. if (!feature$$1) throw new Error('No feature passed');
  1727. if (!name) throw new Error('.featureOf() requires a name');
  1728. if (!feature$$1 || feature$$1.type !== 'Feature' || !feature$$1.geometry) {
  1729. throw new Error('Invalid input to ' + name + ', Feature with geometry required');
  1730. }
  1731. if (!feature$$1.geometry || feature$$1.geometry.type !== type) {
  1732. throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + feature$$1.geometry.type);
  1733. }
  1734. }
  1735. /**
  1736. * Enforce expectations about types of {@link FeatureCollection} inputs for Turf.
  1737. * Internally this uses {@link geojsonType} to judge geometry types.
  1738. *
  1739. * @name collectionOf
  1740. * @param {FeatureCollection} featureCollection a FeatureCollection for which features will be judged
  1741. * @param {string} type expected GeoJSON type
  1742. * @param {string} name name of calling function
  1743. * @throws {Error} if value is not the expected type.
  1744. */
  1745. function collectionOf(featureCollection$$1, type, name) {
  1746. if (!featureCollection$$1) throw new Error('No featureCollection passed');
  1747. if (!name) throw new Error('.collectionOf() requires a name');
  1748. if (!featureCollection$$1 || featureCollection$$1.type !== 'FeatureCollection') {
  1749. throw new Error('Invalid input to ' + name + ', FeatureCollection required');
  1750. }
  1751. for (var i = 0; i < featureCollection$$1.features.length; i++) {
  1752. var feature$$1 = featureCollection$$1.features[i];
  1753. if (!feature$$1 || feature$$1.type !== 'Feature' || !feature$$1.geometry) {
  1754. throw new Error('Invalid input to ' + name + ', Feature with geometry required');
  1755. }
  1756. if (!feature$$1.geometry || feature$$1.geometry.type !== type) {
  1757. throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + feature$$1.geometry.type);
  1758. }
  1759. }
  1760. }
  1761. /**
  1762. * Get Geometry from Feature or Geometry Object
  1763. *
  1764. * @param {Feature|Geometry} geojson GeoJSON Feature or Geometry Object
  1765. * @returns {Geometry|null} GeoJSON Geometry Object
  1766. * @throws {Error} if geojson is not a Feature or Geometry Object
  1767. * @example
  1768. * var point = {
  1769. * "type": "Feature",
  1770. * "properties": {},
  1771. * "geometry": {
  1772. * "type": "Point",
  1773. * "coordinates": [110, 40]
  1774. * }
  1775. * }
  1776. * var geom = turf.getGeom(point)
  1777. * //={"type": "Point", "coordinates": [110, 40]}
  1778. */
  1779. function getGeom(geojson) {
  1780. if (!geojson) throw new Error('geojson is required');
  1781. if (geojson.geometry !== undefined) return geojson.geometry;
  1782. if (geojson.coordinates || geojson.geometries) return geojson;
  1783. throw new Error('geojson must be a valid Feature or Geometry Object');
  1784. }
  1785. /**
  1786. * Get Geometry Type from Feature or Geometry Object
  1787. *
  1788. * @throws {Error} **DEPRECATED** in v5.0.0 in favor of getType
  1789. */
  1790. function getGeomType() {
  1791. throw new Error('invariant.getGeomType has been deprecated in v5.0 in favor of invariant.getType');
  1792. }
  1793. /**
  1794. * Get GeoJSON object's type, Geometry type is prioritize.
  1795. *
  1796. * @param {GeoJSON} geojson GeoJSON object
  1797. * @param {string} [name] name of the variable to display in error message
  1798. * @returns {string} GeoJSON type
  1799. * @example
  1800. * var point = {
  1801. * "type": "Feature",
  1802. * "properties": {},
  1803. * "geometry": {
  1804. * "type": "Point",
  1805. * "coordinates": [110, 40]
  1806. * }
  1807. * }
  1808. * var geom = turf.getType(point)
  1809. * //="Point"
  1810. */
  1811. function getType(geojson, name) {
  1812. if (!geojson) throw new Error((name || 'geojson') + ' is required');
  1813. // GeoJSON Feature & GeometryCollection
  1814. if (geojson.geometry && geojson.geometry.type) return geojson.geometry.type;
  1815. // GeoJSON Geometry & FeatureCollection
  1816. if (geojson.type) return geojson.type;
  1817. throw new Error((name || 'geojson') + ' is invalid');
  1818. }
  1819. var main_es$2 = Object.freeze({
  1820. getCoord: getCoord,
  1821. getCoords: getCoords,
  1822. containsNumber: containsNumber,
  1823. geojsonType: geojsonType,
  1824. featureOf: featureOf,
  1825. collectionOf: collectionOf,
  1826. getGeom: getGeom,
  1827. getGeomType: getGeomType,
  1828. getType: getType
  1829. });
  1830. /**
  1831. * @license GNU Affero General Public License.
  1832. * Copyright (c) 2015, 2015 Ronny Lorenz <ronny@tbi.univie.ac.at>
  1833. * v. 1.2.0
  1834. * https://github.com/RaumZeit/MarchingSquares.js
  1835. */
  1836. /**
  1837. * Compute the isocontour(s) of a scalar 2D field given
  1838. * a certain threshold by applying the Marching Squares
  1839. * Algorithm. The function returns a list of path coordinates
  1840. */
  1841. var defaultSettings = {
  1842. successCallback: null,
  1843. verbose: false
  1844. };
  1845. var settings = {};
  1846. function isoContours(data, threshold, options) {
  1847. /* process options */
  1848. options = options ? options : {};
  1849. var optionKeys = Object.keys(defaultSettings);
  1850. for (var i = 0; i < optionKeys.length; i++) {
  1851. var key = optionKeys[i];
  1852. var val = options[key];
  1853. val = ((typeof val !== 'undefined') && (val !== null)) ? val : defaultSettings[key];
  1854. settings[key] = val;
  1855. }
  1856. if (settings.verbose)
  1857. console.log('MarchingSquaresJS-isoContours: computing isocontour for ' + threshold);
  1858. var ret = contourGrid2Paths(computeContourGrid(data, threshold));
  1859. if (typeof settings.successCallback === 'function')
  1860. settings.successCallback(ret);
  1861. return ret;
  1862. }
  1863. /*
  1864. Thats all for the public interface, below follows the actual
  1865. implementation
  1866. */
  1867. /*
  1868. ################################
  1869. Isocontour implementation below
  1870. ################################
  1871. */
  1872. /* assume that x1 == 1 && x0 == 0 */
  1873. function interpolateX(y, y0, y1) {
  1874. return (y - y0) / (y1 - y0);
  1875. }
  1876. /* compute the isocontour 4-bit grid */
  1877. function computeContourGrid(data, threshold) {
  1878. var rows = data.length - 1;
  1879. var cols = data[0].length - 1;
  1880. var ContourGrid = { rows: rows, cols: cols, cells: [] };
  1881. for (var j = 0; j < rows; ++j) {
  1882. ContourGrid.cells[j] = [];
  1883. for (var i = 0; i < cols; ++i) {
  1884. /* compose the 4-bit corner representation */
  1885. var cval = 0;
  1886. var tl = data[j + 1][i];
  1887. var tr = data[j + 1][i + 1];
  1888. var br = data[j][i + 1];
  1889. var bl = data[j][i];
  1890. if (isNaN(tl) || isNaN(tr) || isNaN(br) || isNaN(bl)) {
  1891. continue;
  1892. }
  1893. cval |= ((tl >= threshold) ? 8 : 0);
  1894. cval |= ((tr >= threshold) ? 4 : 0);
  1895. cval |= ((br >= threshold) ? 2 : 0);
  1896. cval |= ((bl >= threshold) ? 1 : 0);
  1897. /* resolve ambiguity for cval == 5 || 10 via averaging */
  1898. var flipped = false;
  1899. if (cval === 5 || cval === 10) {
  1900. var average = (tl + tr + br + bl) / 4;
  1901. if (cval === 5 && (average < threshold)) {
  1902. cval = 10;
  1903. flipped = true;
  1904. } else if (cval === 10 && (average < threshold)) {
  1905. cval = 5;
  1906. flipped = true;
  1907. }
  1908. }
  1909. /* add cell to ContourGrid if it contains edges */
  1910. if (cval !== 0 && cval !== 15) {
  1911. var top, bottom, left, right;
  1912. top = bottom = left = right = 0.5;
  1913. /* interpolate edges of cell */
  1914. if (cval === 1) {
  1915. left = 1 - interpolateX(threshold, tl, bl);
  1916. bottom = 1 - interpolateX(threshold, br, bl);
  1917. } else if (cval === 2) {
  1918. bottom = interpolateX(threshold, bl, br);
  1919. right = 1 - interpolateX(threshold, tr, br);
  1920. } else if (cval === 3) {
  1921. left = 1 - interpolateX(threshold, tl, bl);
  1922. right = 1 - interpolateX(threshold, tr, br);
  1923. } else if (cval === 4) {
  1924. top = interpolateX(threshold, tl, tr);
  1925. right = interpolateX(threshold, br, tr);
  1926. } else if (cval === 5) {
  1927. top = interpolateX(threshold, tl, tr);
  1928. right = interpolateX(threshold, br, tr);
  1929. bottom = 1 - interpolateX(threshold, br, bl);
  1930. left = 1 - interpolateX(threshold, tl, bl);
  1931. } else if (cval === 6) {
  1932. bottom = interpolateX(threshold, bl, br);
  1933. top = interpolateX(threshold, tl, tr);
  1934. } else if (cval === 7) {
  1935. left = 1 - interpolateX(threshold, tl, bl);
  1936. top = interpolateX(threshold, tl, tr);
  1937. } else if (cval === 8) {
  1938. left = interpolateX(threshold, bl, tl);
  1939. top = 1 - interpolateX(threshold, tr, tl);
  1940. } else if (cval === 9) {
  1941. bottom = 1 - interpolateX(threshold, br, bl);
  1942. top = 1 - interpolateX(threshold, tr, tl);
  1943. } else if (cval === 10) {
  1944. top = 1 - interpolateX(threshold, tr, tl);
  1945. right = 1 - interpolateX(threshold, tr, br);
  1946. bottom = interpolateX(threshold, bl, br);
  1947. left = interpolateX(threshold, bl, tl);
  1948. } else if (cval === 11) {
  1949. top = 1 - interpolateX(threshold, tr, tl);
  1950. right = 1 - interpolateX(threshold, tr, br);
  1951. } else if (cval === 12) {
  1952. left = interpolateX(threshold, bl, tl);
  1953. right = interpolateX(threshold, br, tr);
  1954. } else if (cval === 13) {
  1955. bottom = 1 - interpolateX(threshold, br, bl);
  1956. right = interpolateX(threshold, br, tr);
  1957. } else if (cval === 14) {
  1958. left = interpolateX(threshold, bl, tl);
  1959. bottom = interpolateX(threshold, bl, br);
  1960. } else {
  1961. console.log('MarchingSquaresJS-isoContours: Illegal cval detected: ' + cval);
  1962. }
  1963. ContourGrid.cells[j][i] = {
  1964. cval: cval,
  1965. flipped: flipped,
  1966. top: top,
  1967. right: right,
  1968. bottom: bottom,
  1969. left: left
  1970. };
  1971. }
  1972. }
  1973. }
  1974. return ContourGrid;
  1975. }
  1976. function isSaddle(cell) {
  1977. return cell.cval === 5 || cell.cval === 10;
  1978. }
  1979. function isTrivial(cell) {
  1980. return cell.cval === 0 || cell.cval === 15;
  1981. }
  1982. function clearCell(cell) {
  1983. if ((!isTrivial(cell)) && (cell.cval !== 5) && (cell.cval !== 10)) {
  1984. cell.cval = 15;
  1985. }
  1986. }
  1987. function getXY(cell, edge) {
  1988. if (edge === 'top') {
  1989. return [cell.top, 1.0];
  1990. } else if (edge === 'bottom') {
  1991. return [cell.bottom, 0.0];
  1992. } else if (edge === 'right') {
  1993. return [1.0, cell.right];
  1994. } else if (edge === 'left') {
  1995. return [0.0, cell.left];
  1996. }
  1997. }
  1998. function contourGrid2Paths(grid) {
  1999. var paths = [];
  2000. var path_idx = 0;
  2001. var rows = grid.rows;
  2002. var cols = grid.cols;
  2003. var epsilon = 1e-7;
  2004. grid.cells.forEach(function (g, j) {
  2005. g.forEach(function (gg, i) {
  2006. if ((typeof gg !== 'undefined') && (!isSaddle(gg)) && (!isTrivial(gg))) {
  2007. var p = tracePath(grid.cells, j, i);
  2008. var merged = false;
  2009. /* we may try to merge paths at this point */
  2010. if (p.info === 'mergeable') {
  2011. /*
  2012. search backwards through the path array to find an entry
  2013. that starts with where the current path ends...
  2014. */
  2015. var x = p.path[p.path.length - 1][0],
  2016. y = p.path[p.path.length - 1][1];
  2017. for (var k = path_idx - 1; k >= 0; k--) {
  2018. if ((Math.abs(paths[k][0][0] - x) <= epsilon) && (Math.abs(paths[k][0][1] - y) <= epsilon)) {
  2019. for (var l = p.path.length - 2; l >= 0; --l) {
  2020. paths[k].unshift(p.path[l]);
  2021. }
  2022. merged = true;
  2023. break;
  2024. }
  2025. }
  2026. }
  2027. if (!merged)
  2028. paths[path_idx++] = p.path;
  2029. }
  2030. });
  2031. });
  2032. return paths;
  2033. }
  2034. /*
  2035. construct consecutive line segments from starting cell by
  2036. walking arround the enclosed area clock-wise
  2037. */
  2038. function tracePath(grid, j, i) {
  2039. var maxj = grid.length;
  2040. var p = [];
  2041. var dxContour = [0, 0, 1, 1, 0, 0, 0, 0, -1, 0, 1, 1, -1, 0, -1, 0];
  2042. var dyContour = [0, -1, 0, 0, 1, 1, 1, 1, 0, -1, 0, 0, 0, -1, 0, 0];
  2043. var dx, dy;
  2044. var startEdge = ['none', 'left', 'bottom', 'left', 'right', 'none', 'bottom', 'left', 'top', 'top', 'none', 'top', 'right', 'right', 'bottom', 'none'];
  2045. var nextEdge = ['none', 'bottom', 'right', 'right', 'top', 'top', 'top', 'top', 'left', 'bottom', 'right', 'right', 'left', 'bottom', 'left', 'none'];
  2046. var edge;
  2047. var startCell = grid[j][i];
  2048. var currentCell = grid[j][i];
  2049. var cval = currentCell.cval;
  2050. var edge = startEdge[cval];
  2051. var pt = getXY(currentCell, edge);
  2052. /* push initial segment */
  2053. p.push([i + pt[0], j + pt[1]]);
  2054. edge = nextEdge[cval];
  2055. pt = getXY(currentCell, edge);
  2056. p.push([i + pt[0], j + pt[1]]);
  2057. clearCell(currentCell);
  2058. /* now walk arround the enclosed area in clockwise-direction */
  2059. var k = i + dxContour[cval];
  2060. var l = j + dyContour[cval];
  2061. var prev_cval = cval;
  2062. while ((k >= 0) && (l >= 0) && (l < maxj) && ((k != i) || (l != j))) {
  2063. currentCell = grid[l][k];
  2064. if (typeof currentCell === 'undefined') { /* path ends here */
  2065. //console.log(k + " " + l + " is undefined, stopping path!");
  2066. break;
  2067. }
  2068. cval = currentCell.cval;
  2069. if ((cval === 0) || (cval === 15)) {
  2070. return { path: p, info: 'mergeable' };
  2071. }
  2072. edge = nextEdge[cval];
  2073. dx = dxContour[cval];
  2074. dy = dyContour[cval];
  2075. if ((cval === 5) || (cval === 10)) {
  2076. /* select upper or lower band, depending on previous cells cval */
  2077. if (cval === 5) {
  2078. if (currentCell.flipped) { /* this is actually a flipped case 10 */
  2079. if (dyContour[prev_cval] === -1) {
  2080. edge = 'left';
  2081. dx = -1;
  2082. dy = 0;
  2083. } else {
  2084. edge = 'right';
  2085. dx = 1;
  2086. dy = 0;
  2087. }
  2088. } else { /* real case 5 */
  2089. if (dxContour[prev_cval] === -1) {
  2090. edge = 'bottom';
  2091. dx = 0;
  2092. dy = -1;
  2093. }
  2094. }
  2095. } else if (cval === 10) {
  2096. if (currentCell.flipped) { /* this is actually a flipped case 5 */
  2097. if (dxContour[prev_cval] === -1) {
  2098. edge = 'top';
  2099. dx = 0;
  2100. dy = 1;
  2101. } else {
  2102. edge = 'bottom';
  2103. dx = 0;
  2104. dy = -1;
  2105. }
  2106. } else { /* real case 10 */
  2107. if (dyContour[prev_cval] === 1) {
  2108. edge = 'left';
  2109. dx = -1;
  2110. dy = 0;
  2111. }
  2112. }
  2113. }
  2114. }
  2115. pt = getXY(currentCell, edge);
  2116. p.push([k + pt[0], l + pt[1]]);
  2117. clearCell(currentCell);
  2118. k += dx;
  2119. l += dy;
  2120. prev_cval = cval;
  2121. }
  2122. return { path: p, info: 'closed' };
  2123. }
  2124. /**
  2125. * Takes a {@link Point} grid and returns a correspondent matrix {Array<Array<number>>}
  2126. * of the 'property' values
  2127. *
  2128. * @name gridToMatrix
  2129. * @param {FeatureCollection<Point>} grid of points
  2130. * @param {Object} [options={}] Optional parameters
  2131. * @param {string} [options.zProperty='elevation'] the property name in `points` from which z-values will be pulled
  2132. * @param {boolean} [options.flip=false] returns the matrix upside-down
  2133. * @param {boolean} [options.flags=false] flags, adding a `matrixPosition` array field ([row, column]) to its properties,
  2134. * the grid points with coordinates on the matrix
  2135. * @returns {Array<Array<number>>} matrix of property values
  2136. * @example
  2137. * var extent = [-70.823364, -33.553984, -70.473175, -33.302986];
  2138. * var cellSize = 3;
  2139. * var grid = turf.pointGrid(extent, cellSize);
  2140. * // add a random property to each point between 0 and 60
  2141. * for (var i = 0; i < grid.features.length; i++) {
  2142. * grid.features[i].properties.elevation = (Math.random() * 60);
  2143. * }
  2144. * gridToMatrix(grid);
  2145. * //= [
  2146. * [ 1, 13, 10, 9, 10, 13, 18],
  2147. * [34, 8, 5, 4, 5, 8, 13],
  2148. * [10, 5, 2, 1, 2, 5, 4],
  2149. * [ 0, 4, 56, 19, 1, 4, 9],
  2150. * [10, 5, 2, 1, 2, 5, 10],
  2151. * [57, 8, 5, 4, 5, 0, 57],
  2152. * [ 3, 13, 10, 9, 5, 13, 18],
  2153. * [18, 13, 10, 9, 78, 13, 18]
  2154. * ]
  2155. */
  2156. function gridToMatrix(grid, options) {
  2157. // Optional parameters
  2158. options = options || {};
  2159. if (!isObject(options)) throw new Error('options is invalid');
  2160. var zProperty = options.zProperty || 'elevation';
  2161. var flip = options.flip;
  2162. var flags = options.flags;
  2163. // validation
  2164. collectionOf(grid, 'Point', 'input must contain Points');
  2165. var pointsMatrix = sortPointsByLatLng(grid, flip);
  2166. var matrix = [];
  2167. // create property matrix from sorted points
  2168. // looping order matters here
  2169. for (var r = 0; r < pointsMatrix.length; r++) {
  2170. var pointRow = pointsMatrix[r];
  2171. var row = [];
  2172. for (var c = 0; c < pointRow.length; c++) {
  2173. var point$$1 = pointRow[c];
  2174. // Check if zProperty exist
  2175. if (point$$1.properties[zProperty]) row.push(point$$1.properties[zProperty]);
  2176. else row.push(0);
  2177. // add flags
  2178. if (flags === true) point$$1.properties.matrixPosition = [r, c];
  2179. }
  2180. matrix.push(row);
  2181. }
  2182. return matrix;
  2183. }
  2184. /**
  2185. * Sorts points by latitude and longitude, creating a 2-dimensional array of points
  2186. *
  2187. * @private
  2188. * @param {FeatureCollection<Point>} points GeoJSON Point features
  2189. * @param {boolean} [flip=false] returns the matrix upside-down
  2190. * @returns {Array<Array<Point>>} points ordered by latitude and longitude
  2191. */
  2192. function sortPointsByLatLng(points$$1, flip) {
  2193. var pointsByLatitude = {};
  2194. // divide points by rows with the same latitude
  2195. featureEach(points$$1, function (point$$1) {
  2196. var lat = getCoords(point$$1)[1];
  2197. if (!pointsByLatitude[lat]) pointsByLatitude[lat] = [];
  2198. pointsByLatitude[lat].push(point$$1);
  2199. });
  2200. // sort points (with the same latitude) by longitude
  2201. var orderedRowsByLatitude = Object.keys(pointsByLatitude).map(function (lat) {
  2202. var row = pointsByLatitude[lat];
  2203. var rowOrderedByLongitude = row.sort(function (a, b) {
  2204. return getCoords(a)[0] - getCoords(b)[0];
  2205. });
  2206. return rowOrderedByLongitude;
  2207. });
  2208. // sort rows (of points with the same latitude) by latitude
  2209. var pointMatrix = orderedRowsByLatitude.sort(function (a, b) {
  2210. if (flip) return getCoords(a[0])[1] - getCoords(b[0])[1];
  2211. else return getCoords(b[0])[1] - getCoords(a[0])[1];
  2212. });
  2213. return pointMatrix;
  2214. }
  2215. /**
  2216. * Takes a grid {@link FeatureCollection} of {@link Point} features with z-values and an array of
  2217. * value breaks and generates [isolines](http://en.wikipedia.org/wiki/Isoline).
  2218. *
  2219. * @name isolines
  2220. * @param {FeatureCollection<Point>} pointGrid input points
  2221. * @param {Array<number>} breaks values of `zProperty` where to draw isolines
  2222. * @param {Object} [options={}] Optional parameters
  2223. * @param {string} [options.zProperty='elevation'] the property name in `points` from which z-values will be pulled
  2224. * @param {Object} [options.commonProperties={}] GeoJSON properties passed to ALL isolines
  2225. * @param {Array<Object>} [options.breaksProperties=[]] GeoJSON properties passed, in order, to the correspondent isoline;
  2226. * the breaks array will define the order in which the isolines are created
  2227. * @returns {FeatureCollection<MultiLineString>} a FeatureCollection of {@link MultiLineString} features representing isolines
  2228. * @example
  2229. * // create a grid of points with random z-values in their properties
  2230. * var extent = [0, 30, 20, 50];
  2231. * var cellWidth = 100;
  2232. * var pointGrid = turf.pointGrid(extent, cellWidth, {units: 'miles'});
  2233. *
  2234. * for (var i = 0; i < pointGrid.features.length; i++) {
  2235. * pointGrid.features[i].properties.temperature = Math.random() * 10;
  2236. * }
  2237. * var breaks = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  2238. *
  2239. * var lines = turf.isolines(pointGrid, breaks, {zProperty: 'temperature'});
  2240. *
  2241. * //addToMap
  2242. * var addToMap = [lines];
  2243. */
  2244. function isolines(pointGrid, breaks, options) {
  2245. // Optional parameters
  2246. options = options || {};
  2247. if (!isObject(options)) throw new Error('options is invalid');
  2248. var zProperty = options.zProperty || 'elevation';
  2249. var commonProperties = options.commonProperties || {};
  2250. var breaksProperties = options.breaksProperties || [];
  2251. // Input validation
  2252. collectionOf(pointGrid, 'Point', 'Input must contain Points');
  2253. if (!breaks) throw new Error('breaks is required');
  2254. if (!Array.isArray(breaks)) throw new Error('breaks must be an Array');
  2255. if (!isObject(commonProperties)) throw new Error('commonProperties must be an Object');
  2256. if (!Array.isArray(breaksProperties)) throw new Error('breaksProperties must be an Array');
  2257. // Isoline methods
  2258. var matrix = gridToMatrix(pointGrid, {zProperty: zProperty, flip: true});
  2259. var createdIsoLines = createIsoLines(matrix, breaks, zProperty, commonProperties, breaksProperties);
  2260. var scaledIsolines = rescaleIsolines(createdIsoLines, matrix, pointGrid);
  2261. return featureCollection(scaledIsolines);
  2262. }
  2263. /**
  2264. * Creates the isolines lines (featuresCollection of MultiLineString features) from the 2D data grid
  2265. *
  2266. * Marchingsquares process the grid data as a 3D representation of a function on a 2D plane, therefore it
  2267. * assumes the points (x-y coordinates) are one 'unit' distance. The result of the isolines function needs to be
  2268. * rescaled, with turfjs, to the original area and proportions on the map
  2269. *
  2270. * @private
  2271. * @param {Array<Array<number>>} matrix Grid Data
  2272. * @param {Array<number>} breaks Breaks
  2273. * @param {string} zProperty name of the z-values property
  2274. * @param {Object} [commonProperties={}] GeoJSON properties passed to ALL isolines
  2275. * @param {Object} [breaksProperties=[]] GeoJSON properties passed to the correspondent isoline
  2276. * @returns {Array<MultiLineString>} isolines
  2277. */
  2278. function createIsoLines(matrix, breaks, zProperty, commonProperties, breaksProperties) {
  2279. var results = [];
  2280. for (var i = 1; i < breaks.length; i++) {
  2281. var threshold = +breaks[i]; // make sure it's a number
  2282. var properties = Object.assign(
  2283. {},
  2284. commonProperties,
  2285. breaksProperties[i]
  2286. );
  2287. properties[zProperty] = threshold;
  2288. var isoline = multiLineString(isoContours(matrix, threshold), properties);
  2289. results.push(isoline);
  2290. }
  2291. return results;
  2292. }
  2293. /**
  2294. * Translates and scales isolines
  2295. *
  2296. * @private
  2297. * @param {Array<MultiLineString>} createdIsoLines to be rescaled
  2298. * @param {Array<Array<number>>} matrix Grid Data
  2299. * @param {Object} points Points by Latitude
  2300. * @returns {Array<MultiLineString>} isolines
  2301. */
  2302. function rescaleIsolines(createdIsoLines, matrix, points$$1) {
  2303. // get dimensions (on the map) of the original grid
  2304. var gridBbox = bbox(points$$1); // [ minX, minY, maxX, maxY ]
  2305. var originalWidth = gridBbox[2] - gridBbox[0];
  2306. var originalHeigth = gridBbox[3] - gridBbox[1];
  2307. // get origin, which is the first point of the last row on the rectangular data on the map
  2308. var x0 = gridBbox[0];
  2309. var y0 = gridBbox[1];
  2310. // get number of cells per side
  2311. var matrixWidth = matrix[0].length - 1;
  2312. var matrixHeight = matrix.length - 1;
  2313. // calculate the scaling factor between matrix and rectangular grid on the map
  2314. var scaleX = originalWidth / matrixWidth;
  2315. var scaleY = originalHeigth / matrixHeight;
  2316. var resize = function (point$$1) {
  2317. point$$1[0] = point$$1[0] * scaleX + x0;
  2318. point$$1[1] = point$$1[1] * scaleY + y0;
  2319. };
  2320. // resize and shift each point/line of the createdIsoLines
  2321. createdIsoLines.forEach(function (isoline) {
  2322. coordEach(isoline, resize);
  2323. });
  2324. return createdIsoLines;
  2325. }
  2326. var quickselect = partialSort;
  2327. // Floyd-Rivest selection algorithm:
  2328. // Rearrange items so that all items in the [left, k] range are smaller than all items in (k, right];
  2329. // The k-th element will have the (k - left + 1)th smallest value in [left, right]
  2330. function partialSort(arr, k, left, right, compare) {
  2331. left = left || 0;
  2332. right = right || (arr.length - 1);
  2333. compare = compare || defaultCompare;
  2334. while (right > left) {
  2335. if (right - left > 600) {
  2336. var n = right - left + 1;
  2337. var m = k - left + 1;
  2338. var z = Math.log(n);
  2339. var s = 0.5 * Math.exp(2 * z / 3);
  2340. var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
  2341. var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
  2342. var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
  2343. partialSort(arr, k, newLeft, newRight, compare);
  2344. }
  2345. var t = arr[k];
  2346. var i = left;
  2347. var j = right;
  2348. swap(arr, left, k);
  2349. if (compare(arr[right], t) > 0) swap(arr, left, right);
  2350. while (i < j) {
  2351. swap(arr, i, j);
  2352. i++;
  2353. j--;
  2354. while (compare(arr[i], t) < 0) i++;
  2355. while (compare(arr[j], t) > 0) j--;
  2356. }
  2357. if (compare(arr[left], t) === 0) swap(arr, left, j);
  2358. else {
  2359. j++;
  2360. swap(arr, j, right);
  2361. }
  2362. if (j <= k) left = j + 1;
  2363. if (k <= j) right = j - 1;
  2364. }
  2365. }
  2366. function swap(arr, i, j) {
  2367. var tmp = arr[i];
  2368. arr[i] = arr[j];
  2369. arr[j] = tmp;
  2370. }
  2371. function defaultCompare(a, b) {
  2372. return a < b ? -1 : a > b ? 1 : 0;
  2373. }
  2374. var rbush_1 = rbush;
  2375. function rbush(maxEntries, format) {
  2376. if (!(this instanceof rbush)) return new rbush(maxEntries, format);
  2377. // max entries in a node is 9 by default; min node fill is 40% for best performance
  2378. this._maxEntries = Math.max(4, maxEntries || 9);
  2379. this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
  2380. if (format) {
  2381. this._initFormat(format);
  2382. }
  2383. this.clear();
  2384. }
  2385. rbush.prototype = {
  2386. all: function () {
  2387. return this._all(this.data, []);
  2388. },
  2389. search: function (bbox) {
  2390. var node = this.data,
  2391. result = [],
  2392. toBBox = this.toBBox;
  2393. if (!intersects$1(bbox, node)) return result;
  2394. var nodesToSearch = [],
  2395. i, len, child, childBBox;
  2396. while (node) {
  2397. for (i = 0, len = node.children.length; i < len; i++) {
  2398. child = node.children[i];
  2399. childBBox = node.leaf ? toBBox(child) : child;
  2400. if (intersects$1(bbox, childBBox)) {
  2401. if (node.leaf) result.push(child);
  2402. else if (contains(bbox, childBBox)) this._all(child, result);
  2403. else nodesToSearch.push(child);
  2404. }
  2405. }
  2406. node = nodesToSearch.pop();
  2407. }
  2408. return result;
  2409. },
  2410. collides: function (bbox) {
  2411. var node = this.data,
  2412. toBBox = this.toBBox;
  2413. if (!intersects$1(bbox, node)) return false;
  2414. var nodesToSearch = [],
  2415. i, len, child, childBBox;
  2416. while (node) {
  2417. for (i = 0, len = node.children.length; i < len; i++) {
  2418. child = node.children[i];
  2419. childBBox = node.leaf ? toBBox(child) : child;
  2420. if (intersects$1(bbox, childBBox)) {
  2421. if (node.leaf || contains(bbox, childBBox)) return true;
  2422. nodesToSearch.push(child);
  2423. }
  2424. }
  2425. node = nodesToSearch.pop();
  2426. }
  2427. return false;
  2428. },
  2429. load: function (data) {
  2430. if (!(data && data.length)) return this;
  2431. if (data.length < this._minEntries) {
  2432. for (var i = 0, len = data.length; i < len; i++) {
  2433. this.insert(data[i]);
  2434. }
  2435. return this;
  2436. }
  2437. // recursively build the tree with the given data from stratch using OMT algorithm
  2438. var node = this._build(data.slice(), 0, data.length - 1, 0);
  2439. if (!this.data.children.length) {
  2440. // save as is if tree is empty
  2441. this.data = node;
  2442. } else if (this.data.height === node.height) {
  2443. // split root if trees have the same height
  2444. this._splitRoot(this.data, node);
  2445. } else {
  2446. if (this.data.height < node.height) {
  2447. // swap trees if inserted one is bigger
  2448. var tmpNode = this.data;
  2449. this.data = node;
  2450. node = tmpNode;
  2451. }
  2452. // insert the small tree into the large tree at appropriate level
  2453. this._insert(node, this.data.height - node.height - 1, true);
  2454. }
  2455. return this;
  2456. },
  2457. insert: function (item) {
  2458. if (item) this._insert(item, this.data.height - 1);
  2459. return this;
  2460. },
  2461. clear: function () {
  2462. this.data = createNode([]);
  2463. return this;
  2464. },
  2465. remove: function (item, equalsFn) {
  2466. if (!item) return this;
  2467. var node = this.data,
  2468. bbox = this.toBBox(item),
  2469. path = [],
  2470. indexes = [],
  2471. i, parent, index, goingUp;
  2472. // depth-first iterative tree traversal
  2473. while (node || path.length) {
  2474. if (!node) { // go up
  2475. node = path.pop();
  2476. parent = path[path.length - 1];
  2477. i = indexes.pop();
  2478. goingUp = true;
  2479. }
  2480. if (node.leaf) { // check current node
  2481. index = findItem(item, node.children, equalsFn);
  2482. if (index !== -1) {
  2483. // item found, remove the item and condense tree upwards
  2484. node.children.splice(index, 1);
  2485. path.push(node);
  2486. this._condense(path);
  2487. return this;
  2488. }
  2489. }
  2490. if (!goingUp && !node.leaf && contains(node, bbox)) { // go down
  2491. path.push(node);
  2492. indexes.push(i);
  2493. i = 0;
  2494. parent = node;
  2495. node = node.children[0];
  2496. } else if (parent) { // go right
  2497. i++;
  2498. node = parent.children[i];
  2499. goingUp = false;
  2500. } else node = null; // nothing found
  2501. }
  2502. return this;
  2503. },
  2504. toBBox: function (item) { return item; },
  2505. compareMinX: compareNodeMinX,
  2506. compareMinY: compareNodeMinY,
  2507. toJSON: function () { return this.data; },
  2508. fromJSON: function (data) {
  2509. this.data = data;
  2510. return this;
  2511. },
  2512. _all: function (node, result) {
  2513. var nodesToSearch = [];
  2514. while (node) {
  2515. if (node.leaf) result.push.apply(result, node.children);
  2516. else nodesToSearch.push.apply(nodesToSearch, node.children);
  2517. node = nodesToSearch.pop();
  2518. }
  2519. return result;
  2520. },
  2521. _build: function (items, left, right, height) {
  2522. var N = right - left + 1,
  2523. M = this._maxEntries,
  2524. node;
  2525. if (N <= M) {
  2526. // reached leaf level; return leaf
  2527. node = createNode(items.slice(left, right + 1));
  2528. calcBBox(node, this.toBBox);
  2529. return node;
  2530. }
  2531. if (!height) {
  2532. // target height of the bulk-loaded tree
  2533. height = Math.ceil(Math.log(N) / Math.log(M));
  2534. // target number of root entries to maximize storage utilization
  2535. M = Math.ceil(N / Math.pow(M, height - 1));
  2536. }
  2537. node = createNode([]);
  2538. node.leaf = false;
  2539. node.height = height;
  2540. // split the items into M mostly square tiles
  2541. var N2 = Math.ceil(N / M),
  2542. N1 = N2 * Math.ceil(Math.sqrt(M)),
  2543. i, j, right2, right3;
  2544. multiSelect(items, left, right, N1, this.compareMinX);
  2545. for (i = left; i <= right; i += N1) {
  2546. right2 = Math.min(i + N1 - 1, right);
  2547. multiSelect(items, i, right2, N2, this.compareMinY);
  2548. for (j = i; j <= right2; j += N2) {
  2549. right3 = Math.min(j + N2 - 1, right2);
  2550. // pack each entry recursively
  2551. node.children.push(this._build(items, j, right3, height - 1));
  2552. }
  2553. }
  2554. calcBBox(node, this.toBBox);
  2555. return node;
  2556. },
  2557. _chooseSubtree: function (bbox, node, level, path) {
  2558. var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
  2559. while (true) {
  2560. path.push(node);
  2561. if (node.leaf || path.length - 1 === level) break;
  2562. minArea = minEnlargement = Infinity;
  2563. for (i = 0, len = node.children.length; i < len; i++) {
  2564. child = node.children[i];
  2565. area = bboxArea(child);
  2566. enlargement = enlargedArea(bbox, child) - area;
  2567. // choose entry with the least area enlargement
  2568. if (enlargement < minEnlargement) {
  2569. minEnlargement = enlargement;
  2570. minArea = area < minArea ? area : minArea;
  2571. targetNode = child;
  2572. } else if (enlargement === minEnlargement) {
  2573. // otherwise choose one with the smallest area
  2574. if (area < minArea) {
  2575. minArea = area;
  2576. targetNode = child;
  2577. }
  2578. }
  2579. }
  2580. node = targetNode || node.children[0];
  2581. }
  2582. return node;
  2583. },
  2584. _insert: function (item, level, isNode) {
  2585. var toBBox = this.toBBox,
  2586. bbox = isNode ? item : toBBox(item),
  2587. insertPath = [];
  2588. // find the best node for accommodating the item, saving all nodes along the path too
  2589. var node = this._chooseSubtree(bbox, this.data, level, insertPath);
  2590. // put the item into the node
  2591. node.children.push(item);
  2592. extend(node, bbox);
  2593. // split on node overflow; propagate upwards if necessary
  2594. while (level >= 0) {
  2595. if (insertPath[level].children.length > this._maxEntries) {
  2596. this._split(insertPath, level);
  2597. level--;
  2598. } else break;
  2599. }
  2600. // adjust bboxes along the insertion path
  2601. this._adjustParentBBoxes(bbox, insertPath, level);
  2602. },
  2603. // split overflowed node into two
  2604. _split: function (insertPath, level) {
  2605. var node = insertPath[level],
  2606. M = node.children.length,
  2607. m = this._minEntries;
  2608. this._chooseSplitAxis(node, m, M);
  2609. var splitIndex = this._chooseSplitIndex(node, m, M);
  2610. var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
  2611. newNode.height = node.height;
  2612. newNode.leaf = node.leaf;
  2613. calcBBox(node, this.toBBox);
  2614. calcBBox(newNode, this.toBBox);
  2615. if (level) insertPath[level - 1].children.push(newNode);
  2616. else this._splitRoot(node, newNode);
  2617. },
  2618. _splitRoot: function (node, newNode) {
  2619. // split root node
  2620. this.data = createNode([node, newNode]);
  2621. this.data.height = node.height + 1;
  2622. this.data.leaf = false;
  2623. calcBBox(this.data, this.toBBox);
  2624. },
  2625. _chooseSplitIndex: function (node, m, M) {
  2626. var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
  2627. minOverlap = minArea = Infinity;
  2628. for (i = m; i <= M - m; i++) {
  2629. bbox1 = distBBox(node, 0, i, this.toBBox);
  2630. bbox2 = distBBox(node, i, M, this.toBBox);
  2631. overlap = intersectionArea(bbox1, bbox2);
  2632. area = bboxArea(bbox1) + bboxArea(bbox2);
  2633. // choose distribution with minimum overlap
  2634. if (overlap < minOverlap) {
  2635. minOverlap = overlap;
  2636. index = i;
  2637. minArea = area < minArea ? area : minArea;
  2638. } else if (overlap === minOverlap) {
  2639. // otherwise choose distribution with minimum area
  2640. if (area < minArea) {
  2641. minArea = area;
  2642. index = i;
  2643. }
  2644. }
  2645. }
  2646. return index;
  2647. },
  2648. // sorts node children by the best axis for split
  2649. _chooseSplitAxis: function (node, m, M) {
  2650. var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
  2651. compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
  2652. xMargin = this._allDistMargin(node, m, M, compareMinX),
  2653. yMargin = this._allDistMargin(node, m, M, compareMinY);
  2654. // if total distributions margin value is minimal for x, sort by minX,
  2655. // otherwise it's already sorted by minY
  2656. if (xMargin < yMargin) node.children.sort(compareMinX);
  2657. },
  2658. // total margin of all possible split distributions where each node is at least m full
  2659. _allDistMargin: function (node, m, M, compare) {
  2660. node.children.sort(compare);
  2661. var toBBox = this.toBBox,
  2662. leftBBox = distBBox(node, 0, m, toBBox),
  2663. rightBBox = distBBox(node, M - m, M, toBBox),
  2664. margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
  2665. i, child;
  2666. for (i = m; i < M - m; i++) {
  2667. child = node.children[i];
  2668. extend(leftBBox, node.leaf ? toBBox(child) : child);
  2669. margin += bboxMargin(leftBBox);
  2670. }
  2671. for (i = M - m - 1; i >= m; i--) {
  2672. child = node.children[i];
  2673. extend(rightBBox, node.leaf ? toBBox(child) : child);
  2674. margin += bboxMargin(rightBBox);
  2675. }
  2676. return margin;
  2677. },
  2678. _adjustParentBBoxes: function (bbox, path, level) {
  2679. // adjust bboxes along the given tree path
  2680. for (var i = level; i >= 0; i--) {
  2681. extend(path[i], bbox);
  2682. }
  2683. },
  2684. _condense: function (path) {
  2685. // go through the path, removing empty nodes and updating bboxes
  2686. for (var i = path.length - 1, siblings; i >= 0; i--) {
  2687. if (path[i].children.length === 0) {
  2688. if (i > 0) {
  2689. siblings = path[i - 1].children;
  2690. siblings.splice(siblings.indexOf(path[i]), 1);
  2691. } else this.clear();
  2692. } else calcBBox(path[i], this.toBBox);
  2693. }
  2694. },
  2695. _initFormat: function (format) {
  2696. // data format (minX, minY, maxX, maxY accessors)
  2697. // uses eval-type function compilation instead of just accepting a toBBox function
  2698. // because the algorithms are very sensitive to sorting functions performance,
  2699. // so they should be dead simple and without inner calls
  2700. var compareArr = ['return a', ' - b', ';'];
  2701. this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
  2702. this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
  2703. this.toBBox = new Function('a',
  2704. 'return {minX: a' + format[0] +
  2705. ', minY: a' + format[1] +
  2706. ', maxX: a' + format[2] +
  2707. ', maxY: a' + format[3] + '};');
  2708. }
  2709. };
  2710. function findItem(item, items, equalsFn) {
  2711. if (!equalsFn) return items.indexOf(item);
  2712. for (var i = 0; i < items.length; i++) {
  2713. if (equalsFn(item, items[i])) return i;
  2714. }
  2715. return -1;
  2716. }
  2717. // calculate node's bbox from bboxes of its children
  2718. function calcBBox(node, toBBox) {
  2719. distBBox(node, 0, node.children.length, toBBox, node);
  2720. }
  2721. // min bounding rectangle of node children from k to p-1
  2722. function distBBox(node, k, p, toBBox, destNode) {
  2723. if (!destNode) destNode = createNode(null);
  2724. destNode.minX = Infinity;
  2725. destNode.minY = Infinity;
  2726. destNode.maxX = -Infinity;
  2727. destNode.maxY = -Infinity;
  2728. for (var i = k, child; i < p; i++) {
  2729. child = node.children[i];
  2730. extend(destNode, node.leaf ? toBBox(child) : child);
  2731. }
  2732. return destNode;
  2733. }
  2734. function extend(a, b) {
  2735. a.minX = Math.min(a.minX, b.minX);
  2736. a.minY = Math.min(a.minY, b.minY);
  2737. a.maxX = Math.max(a.maxX, b.maxX);
  2738. a.maxY = Math.max(a.maxY, b.maxY);
  2739. return a;
  2740. }
  2741. function compareNodeMinX(a, b) { return a.minX - b.minX; }
  2742. function compareNodeMinY(a, b) { return a.minY - b.minY; }
  2743. function bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }
  2744. function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
  2745. function enlargedArea(a, b) {
  2746. return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
  2747. (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
  2748. }
  2749. function intersectionArea(a, b) {
  2750. var minX = Math.max(a.minX, b.minX),
  2751. minY = Math.max(a.minY, b.minY),
  2752. maxX = Math.min(a.maxX, b.maxX),
  2753. maxY = Math.min(a.maxY, b.maxY);
  2754. return Math.max(0, maxX - minX) *
  2755. Math.max(0, maxY - minY);
  2756. }
  2757. function contains(a, b) {
  2758. return a.minX <= b.minX &&
  2759. a.minY <= b.minY &&
  2760. b.maxX <= a.maxX &&
  2761. b.maxY <= a.maxY;
  2762. }
  2763. function intersects$1(a, b) {
  2764. return b.minX <= a.maxX &&
  2765. b.minY <= a.maxY &&
  2766. b.maxX >= a.minX &&
  2767. b.maxY >= a.minY;
  2768. }
  2769. function createNode(children) {
  2770. return {
  2771. children: children,
  2772. height: 1,
  2773. leaf: true,
  2774. minX: Infinity,
  2775. minY: Infinity,
  2776. maxX: -Infinity,
  2777. maxY: -Infinity
  2778. };
  2779. }
  2780. // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
  2781. // combines selection algorithm with binary divide & conquer approach
  2782. function multiSelect(arr, left, right, n, compare) {
  2783. var stack = [left, right],
  2784. mid;
  2785. while (stack.length) {
  2786. right = stack.pop();
  2787. left = stack.pop();
  2788. if (right - left <= n) continue;
  2789. mid = left + Math.ceil((right - left) / n / 2) * n;
  2790. quickselect(arr, mid, left, right, compare);
  2791. stack.push(left, mid, mid, right);
  2792. }
  2793. }
  2794. function createCommonjsModule(fn, module) {
  2795. return module = { exports: {} }, fn(module, module.exports), module.exports;
  2796. }
  2797. var twoProduct_1 = twoProduct;
  2798. var SPLITTER = +(Math.pow(2, 27) + 1.0);
  2799. function twoProduct(a, b, result) {
  2800. var x = a * b;
  2801. var c = SPLITTER * a;
  2802. var abig = c - a;
  2803. var ahi = c - abig;
  2804. var alo = a - ahi;
  2805. var d = SPLITTER * b;
  2806. var bbig = d - b;
  2807. var bhi = d - bbig;
  2808. var blo = b - bhi;
  2809. var err1 = x - (ahi * bhi);
  2810. var err2 = err1 - (alo * bhi);
  2811. var err3 = err2 - (ahi * blo);
  2812. var y = alo * blo - err3;
  2813. if(result) {
  2814. result[0] = y;
  2815. result[1] = x;
  2816. return result
  2817. }
  2818. return [ y, x ]
  2819. }
  2820. var robustSum = linearExpansionSum;
  2821. //Easy case: Add two scalars
  2822. function scalarScalar(a, b) {
  2823. var x = a + b;
  2824. var bv = x - a;
  2825. var av = x - bv;
  2826. var br = b - bv;
  2827. var ar = a - av;
  2828. var y = ar + br;
  2829. if(y) {
  2830. return [y, x]
  2831. }
  2832. return [x]
  2833. }
  2834. function linearExpansionSum(e, f) {
  2835. var ne = e.length|0;
  2836. var nf = f.length|0;
  2837. if(ne === 1 && nf === 1) {
  2838. return scalarScalar(e[0], f[0])
  2839. }
  2840. var n = ne + nf;
  2841. var g = new Array(n);
  2842. var count = 0;
  2843. var eptr = 0;
  2844. var fptr = 0;
  2845. var abs = Math.abs;
  2846. var ei = e[eptr];
  2847. var ea = abs(ei);
  2848. var fi = f[fptr];
  2849. var fa = abs(fi);
  2850. var a, b;
  2851. if(ea < fa) {
  2852. b = ei;
  2853. eptr += 1;
  2854. if(eptr < ne) {
  2855. ei = e[eptr];
  2856. ea = abs(ei);
  2857. }
  2858. } else {
  2859. b = fi;
  2860. fptr += 1;
  2861. if(fptr < nf) {
  2862. fi = f[fptr];
  2863. fa = abs(fi);
  2864. }
  2865. }
  2866. if((eptr < ne && ea < fa) || (fptr >= nf)) {
  2867. a = ei;
  2868. eptr += 1;
  2869. if(eptr < ne) {
  2870. ei = e[eptr];
  2871. ea = abs(ei);
  2872. }
  2873. } else {
  2874. a = fi;
  2875. fptr += 1;
  2876. if(fptr < nf) {
  2877. fi = f[fptr];
  2878. fa = abs(fi);
  2879. }
  2880. }
  2881. var x = a + b;
  2882. var bv = x - a;
  2883. var y = b - bv;
  2884. var q0 = y;
  2885. var q1 = x;
  2886. var _x, _bv, _av, _br, _ar;
  2887. while(eptr < ne && fptr < nf) {
  2888. if(ea < fa) {
  2889. a = ei;
  2890. eptr += 1;
  2891. if(eptr < ne) {
  2892. ei = e[eptr];
  2893. ea = abs(ei);
  2894. }
  2895. } else {
  2896. a = fi;
  2897. fptr += 1;
  2898. if(fptr < nf) {
  2899. fi = f[fptr];
  2900. fa = abs(fi);
  2901. }
  2902. }
  2903. b = q0;
  2904. x = a + b;
  2905. bv = x - a;
  2906. y = b - bv;
  2907. if(y) {
  2908. g[count++] = y;
  2909. }
  2910. _x = q1 + x;
  2911. _bv = _x - q1;
  2912. _av = _x - _bv;
  2913. _br = x - _bv;
  2914. _ar = q1 - _av;
  2915. q0 = _ar + _br;
  2916. q1 = _x;
  2917. }
  2918. while(eptr < ne) {
  2919. a = ei;
  2920. b = q0;
  2921. x = a + b;
  2922. bv = x - a;
  2923. y = b - bv;
  2924. if(y) {
  2925. g[count++] = y;
  2926. }
  2927. _x = q1 + x;
  2928. _bv = _x - q1;
  2929. _av = _x - _bv;
  2930. _br = x - _bv;
  2931. _ar = q1 - _av;
  2932. q0 = _ar + _br;
  2933. q1 = _x;
  2934. eptr += 1;
  2935. if(eptr < ne) {
  2936. ei = e[eptr];
  2937. }
  2938. }
  2939. while(fptr < nf) {
  2940. a = fi;
  2941. b = q0;
  2942. x = a + b;
  2943. bv = x - a;
  2944. y = b - bv;
  2945. if(y) {
  2946. g[count++] = y;
  2947. }
  2948. _x = q1 + x;
  2949. _bv = _x - q1;
  2950. _av = _x - _bv;
  2951. _br = x - _bv;
  2952. _ar = q1 - _av;
  2953. q0 = _ar + _br;
  2954. q1 = _x;
  2955. fptr += 1;
  2956. if(fptr < nf) {
  2957. fi = f[fptr];
  2958. }
  2959. }
  2960. if(q0) {
  2961. g[count++] = q0;
  2962. }
  2963. if(q1) {
  2964. g[count++] = q1;
  2965. }
  2966. if(!count) {
  2967. g[count++] = 0.0;
  2968. }
  2969. g.length = count;
  2970. return g
  2971. }
  2972. var twoSum = fastTwoSum;
  2973. function fastTwoSum(a, b, result) {
  2974. var x = a + b;
  2975. var bv = x - a;
  2976. var av = x - bv;
  2977. var br = b - bv;
  2978. var ar = a - av;
  2979. if(result) {
  2980. result[0] = ar + br;
  2981. result[1] = x;
  2982. return result
  2983. }
  2984. return [ar+br, x]
  2985. }
  2986. var robustScale = scaleLinearExpansion;
  2987. function scaleLinearExpansion(e, scale) {
  2988. var n = e.length;
  2989. if(n === 1) {
  2990. var ts = twoProduct_1(e[0], scale);
  2991. if(ts[0]) {
  2992. return ts
  2993. }
  2994. return [ ts[1] ]
  2995. }
  2996. var g = new Array(2 * n);
  2997. var q = [0.1, 0.1];
  2998. var t = [0.1, 0.1];
  2999. var count = 0;
  3000. twoProduct_1(e[0], scale, q);
  3001. if(q[0]) {
  3002. g[count++] = q[0];
  3003. }
  3004. for(var i=1; i<n; ++i) {
  3005. twoProduct_1(e[i], scale, t);
  3006. var pq = q[1];
  3007. twoSum(pq, t[0], q);
  3008. if(q[0]) {
  3009. g[count++] = q[0];
  3010. }
  3011. var a = t[1];
  3012. var b = q[1];
  3013. var x = a + b;
  3014. var bv = x - a;
  3015. var y = b - bv;
  3016. q[1] = x;
  3017. if(y) {
  3018. g[count++] = y;
  3019. }
  3020. }
  3021. if(q[1]) {
  3022. g[count++] = q[1];
  3023. }
  3024. if(count === 0) {
  3025. g[count++] = 0.0;
  3026. }
  3027. g.length = count;
  3028. return g
  3029. }
  3030. var robustDiff = robustSubtract;
  3031. //Easy case: Add two scalars
  3032. function scalarScalar$1(a, b) {
  3033. var x = a + b;
  3034. var bv = x - a;
  3035. var av = x - bv;
  3036. var br = b - bv;
  3037. var ar = a - av;
  3038. var y = ar + br;
  3039. if(y) {
  3040. return [y, x]
  3041. }
  3042. return [x]
  3043. }
  3044. function robustSubtract(e, f) {
  3045. var ne = e.length|0;
  3046. var nf = f.length|0;
  3047. if(ne === 1 && nf === 1) {
  3048. return scalarScalar$1(e[0], -f[0])
  3049. }
  3050. var n = ne + nf;
  3051. var g = new Array(n);
  3052. var count = 0;
  3053. var eptr = 0;
  3054. var fptr = 0;
  3055. var abs = Math.abs;
  3056. var ei = e[eptr];
  3057. var ea = abs(ei);
  3058. var fi = -f[fptr];
  3059. var fa = abs(fi);
  3060. var a, b;
  3061. if(ea < fa) {
  3062. b = ei;
  3063. eptr += 1;
  3064. if(eptr < ne) {
  3065. ei = e[eptr];
  3066. ea = abs(ei);
  3067. }
  3068. } else {
  3069. b = fi;
  3070. fptr += 1;
  3071. if(fptr < nf) {
  3072. fi = -f[fptr];
  3073. fa = abs(fi);
  3074. }
  3075. }
  3076. if((eptr < ne && ea < fa) || (fptr >= nf)) {
  3077. a = ei;
  3078. eptr += 1;
  3079. if(eptr < ne) {
  3080. ei = e[eptr];
  3081. ea = abs(ei);
  3082. }
  3083. } else {
  3084. a = fi;
  3085. fptr += 1;
  3086. if(fptr < nf) {
  3087. fi = -f[fptr];
  3088. fa = abs(fi);
  3089. }
  3090. }
  3091. var x = a + b;
  3092. var bv = x - a;
  3093. var y = b - bv;
  3094. var q0 = y;
  3095. var q1 = x;
  3096. var _x, _bv, _av, _br, _ar;
  3097. while(eptr < ne && fptr < nf) {
  3098. if(ea < fa) {
  3099. a = ei;
  3100. eptr += 1;
  3101. if(eptr < ne) {
  3102. ei = e[eptr];
  3103. ea = abs(ei);
  3104. }
  3105. } else {
  3106. a = fi;
  3107. fptr += 1;
  3108. if(fptr < nf) {
  3109. fi = -f[fptr];
  3110. fa = abs(fi);
  3111. }
  3112. }
  3113. b = q0;
  3114. x = a + b;
  3115. bv = x - a;
  3116. y = b - bv;
  3117. if(y) {
  3118. g[count++] = y;
  3119. }
  3120. _x = q1 + x;
  3121. _bv = _x - q1;
  3122. _av = _x - _bv;
  3123. _br = x - _bv;
  3124. _ar = q1 - _av;
  3125. q0 = _ar + _br;
  3126. q1 = _x;
  3127. }
  3128. while(eptr < ne) {
  3129. a = ei;
  3130. b = q0;
  3131. x = a + b;
  3132. bv = x - a;
  3133. y = b - bv;
  3134. if(y) {
  3135. g[count++] = y;
  3136. }
  3137. _x = q1 + x;
  3138. _bv = _x - q1;
  3139. _av = _x - _bv;
  3140. _br = x - _bv;
  3141. _ar = q1 - _av;
  3142. q0 = _ar + _br;
  3143. q1 = _x;
  3144. eptr += 1;
  3145. if(eptr < ne) {
  3146. ei = e[eptr];
  3147. }
  3148. }
  3149. while(fptr < nf) {
  3150. a = fi;
  3151. b = q0;
  3152. x = a + b;
  3153. bv = x - a;
  3154. y = b - bv;
  3155. if(y) {
  3156. g[count++] = y;
  3157. }
  3158. _x = q1 + x;
  3159. _bv = _x - q1;
  3160. _av = _x - _bv;
  3161. _br = x - _bv;
  3162. _ar = q1 - _av;
  3163. q0 = _ar + _br;
  3164. q1 = _x;
  3165. fptr += 1;
  3166. if(fptr < nf) {
  3167. fi = -f[fptr];
  3168. }
  3169. }
  3170. if(q0) {
  3171. g[count++] = q0;
  3172. }
  3173. if(q1) {
  3174. g[count++] = q1;
  3175. }
  3176. if(!count) {
  3177. g[count++] = 0.0;
  3178. }
  3179. g.length = count;
  3180. return g
  3181. }
  3182. var orientation_1 = createCommonjsModule(function (module) {
  3183. var NUM_EXPAND = 5;
  3184. var EPSILON = 1.1102230246251565e-16;
  3185. var ERRBOUND3 = (3.0 + 16.0 * EPSILON) * EPSILON;
  3186. var ERRBOUND4 = (7.0 + 56.0 * EPSILON) * EPSILON;
  3187. function cofactor(m, c) {
  3188. var result = new Array(m.length-1);
  3189. for(var i=1; i<m.length; ++i) {
  3190. var r = result[i-1] = new Array(m.length-1);
  3191. for(var j=0,k=0; j<m.length; ++j) {
  3192. if(j === c) {
  3193. continue
  3194. }
  3195. r[k++] = m[i][j];
  3196. }
  3197. }
  3198. return result
  3199. }
  3200. function matrix(n) {
  3201. var result = new Array(n);
  3202. for(var i=0; i<n; ++i) {
  3203. result[i] = new Array(n);
  3204. for(var j=0; j<n; ++j) {
  3205. result[i][j] = ["m", j, "[", (n-i-1), "]"].join("");
  3206. }
  3207. }
  3208. return result
  3209. }
  3210. function sign(n) {
  3211. if(n & 1) {
  3212. return "-"
  3213. }
  3214. return ""
  3215. }
  3216. function generateSum(expr) {
  3217. if(expr.length === 1) {
  3218. return expr[0]
  3219. } else if(expr.length === 2) {
  3220. return ["sum(", expr[0], ",", expr[1], ")"].join("")
  3221. } else {
  3222. var m = expr.length>>1;
  3223. return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("")
  3224. }
  3225. }
  3226. function determinant(m) {
  3227. if(m.length === 2) {
  3228. return [["sum(prod(", m[0][0], ",", m[1][1], "),prod(-", m[0][1], ",", m[1][0], "))"].join("")]
  3229. } else {
  3230. var expr = [];
  3231. for(var i=0; i<m.length; ++i) {
  3232. expr.push(["scale(", generateSum(determinant(cofactor(m, i))), ",", sign(i), m[0][i], ")"].join(""));
  3233. }
  3234. return expr
  3235. }
  3236. }
  3237. function orientation(n) {
  3238. var pos = [];
  3239. var neg = [];
  3240. var m = matrix(n);
  3241. var args = [];
  3242. for(var i=0; i<n; ++i) {
  3243. if((i&1)===0) {
  3244. pos.push.apply(pos, determinant(cofactor(m, i)));
  3245. } else {
  3246. neg.push.apply(neg, determinant(cofactor(m, i)));
  3247. }
  3248. args.push("m" + i);
  3249. }
  3250. var posExpr = generateSum(pos);
  3251. var negExpr = generateSum(neg);
  3252. var funcName = "orientation" + n + "Exact";
  3253. var code = ["function ", funcName, "(", args.join(), "){var p=", posExpr, ",n=", negExpr, ",d=sub(p,n);\
  3254. return d[d.length-1];};return ", funcName].join("");
  3255. var proc = new Function("sum", "prod", "scale", "sub", code);
  3256. return proc(robustSum, twoProduct_1, robustScale, robustDiff)
  3257. }
  3258. var orientation3Exact = orientation(3);
  3259. var orientation4Exact = orientation(4);
  3260. var CACHED = [
  3261. function orientation0() { return 0 },
  3262. function orientation1() { return 0 },
  3263. function orientation2(a, b) {
  3264. return b[0] - a[0]
  3265. },
  3266. function orientation3(a, b, c) {
  3267. var l = (a[1] - c[1]) * (b[0] - c[0]);
  3268. var r = (a[0] - c[0]) * (b[1] - c[1]);
  3269. var det = l - r;
  3270. var s;
  3271. if(l > 0) {
  3272. if(r <= 0) {
  3273. return det
  3274. } else {
  3275. s = l + r;
  3276. }
  3277. } else if(l < 0) {
  3278. if(r >= 0) {
  3279. return det
  3280. } else {
  3281. s = -(l + r);
  3282. }
  3283. } else {
  3284. return det
  3285. }
  3286. var tol = ERRBOUND3 * s;
  3287. if(det >= tol || det <= -tol) {
  3288. return det
  3289. }
  3290. return orientation3Exact(a, b, c)
  3291. },
  3292. function orientation4(a,b,c,d) {
  3293. var adx = a[0] - d[0];
  3294. var bdx = b[0] - d[0];
  3295. var cdx = c[0] - d[0];
  3296. var ady = a[1] - d[1];
  3297. var bdy = b[1] - d[1];
  3298. var cdy = c[1] - d[1];
  3299. var adz = a[2] - d[2];
  3300. var bdz = b[2] - d[2];
  3301. var cdz = c[2] - d[2];
  3302. var bdxcdy = bdx * cdy;
  3303. var cdxbdy = cdx * bdy;
  3304. var cdxady = cdx * ady;
  3305. var adxcdy = adx * cdy;
  3306. var adxbdy = adx * bdy;
  3307. var bdxady = bdx * ady;
  3308. var det = adz * (bdxcdy - cdxbdy)
  3309. + bdz * (cdxady - adxcdy)
  3310. + cdz * (adxbdy - bdxady);
  3311. var permanent = (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * Math.abs(adz)
  3312. + (Math.abs(cdxady) + Math.abs(adxcdy)) * Math.abs(bdz)
  3313. + (Math.abs(adxbdy) + Math.abs(bdxady)) * Math.abs(cdz);
  3314. var tol = ERRBOUND4 * permanent;
  3315. if ((det > tol) || (-det > tol)) {
  3316. return det
  3317. }
  3318. return orientation4Exact(a,b,c,d)
  3319. }
  3320. ];
  3321. function slowOrient(args) {
  3322. var proc = CACHED[args.length];
  3323. if(!proc) {
  3324. proc = CACHED[args.length] = orientation(args.length);
  3325. }
  3326. return proc.apply(undefined, args)
  3327. }
  3328. function generateOrientationProc() {
  3329. while(CACHED.length <= NUM_EXPAND) {
  3330. CACHED.push(orientation(CACHED.length));
  3331. }
  3332. var args = [];
  3333. var procArgs = ["slow"];
  3334. for(var i=0; i<=NUM_EXPAND; ++i) {
  3335. args.push("a" + i);
  3336. procArgs.push("o" + i);
  3337. }
  3338. var code = [
  3339. "function getOrientation(", args.join(), "){switch(arguments.length){case 0:case 1:return 0;"
  3340. ];
  3341. for(var i=2; i<=NUM_EXPAND; ++i) {
  3342. code.push("case ", i, ":return o", i, "(", args.slice(0, i).join(), ");");
  3343. }
  3344. code.push("}var s=new Array(arguments.length);for(var i=0;i<arguments.length;++i){s[i]=arguments[i]};return slow(s);}return getOrientation");
  3345. procArgs.push(code.join(""));
  3346. var proc = Function.apply(undefined, procArgs);
  3347. module.exports = proc.apply(undefined, [slowOrient].concat(CACHED));
  3348. for(var i=0; i<=NUM_EXPAND; ++i) {
  3349. module.exports[i] = CACHED[i];
  3350. }
  3351. }
  3352. generateOrientationProc();
  3353. });
  3354. var monotoneConvexHull2d = monotoneConvexHull2D;
  3355. var orient$1 = orientation_1[3];
  3356. function monotoneConvexHull2D(points) {
  3357. var n = points.length;
  3358. if(n < 3) {
  3359. var result = new Array(n);
  3360. for(var i=0; i<n; ++i) {
  3361. result[i] = i;
  3362. }
  3363. if(n === 2 &&
  3364. points[0][0] === points[1][0] &&
  3365. points[0][1] === points[1][1]) {
  3366. return [0]
  3367. }
  3368. return result
  3369. }
  3370. //Sort point indices along x-axis
  3371. var sorted = new Array(n);
  3372. for(var i=0; i<n; ++i) {
  3373. sorted[i] = i;
  3374. }
  3375. sorted.sort(function(a,b) {
  3376. var d = points[a][0]-points[b][0];
  3377. if(d) {
  3378. return d
  3379. }
  3380. return points[a][1] - points[b][1]
  3381. });
  3382. //Construct upper and lower hulls
  3383. var lower = [sorted[0], sorted[1]];
  3384. var upper = [sorted[0], sorted[1]];
  3385. for(var i=2; i<n; ++i) {
  3386. var idx = sorted[i];
  3387. var p = points[idx];
  3388. //Insert into lower list
  3389. var m = lower.length;
  3390. while(m > 1 && orient$1(
  3391. points[lower[m-2]],
  3392. points[lower[m-1]],
  3393. p) <= 0) {
  3394. m -= 1;
  3395. lower.pop();
  3396. }
  3397. lower.push(idx);
  3398. //Insert into upper list
  3399. m = upper.length;
  3400. while(m > 1 && orient$1(
  3401. points[upper[m-2]],
  3402. points[upper[m-1]],
  3403. p) >= 0) {
  3404. m -= 1;
  3405. upper.pop();
  3406. }
  3407. upper.push(idx);
  3408. }
  3409. //Merge lists together
  3410. var result = new Array(upper.length + lower.length - 2);
  3411. var ptr = 0;
  3412. for(var i=0, nl=lower.length; i<nl; ++i) {
  3413. result[ptr++] = lower[i];
  3414. }
  3415. for(var j=upper.length-2; j>0; --j) {
  3416. result[ptr++] = upper[j];
  3417. }
  3418. //Return result
  3419. return result
  3420. }
  3421. var tinyqueue = TinyQueue;
  3422. var default_1$1 = TinyQueue;
  3423. function TinyQueue(data, compare) {
  3424. if (!(this instanceof TinyQueue)) return new TinyQueue(data, compare);
  3425. this.data = data || [];
  3426. this.length = this.data.length;
  3427. this.compare = compare || defaultCompare$1;
  3428. if (this.length > 0) {
  3429. for (var i = (this.length >> 1) - 1; i >= 0; i--) this._down(i);
  3430. }
  3431. }
  3432. function defaultCompare$1(a, b) {
  3433. return a < b ? -1 : a > b ? 1 : 0;
  3434. }
  3435. TinyQueue.prototype = {
  3436. push: function (item) {
  3437. this.data.push(item);
  3438. this.length++;
  3439. this._up(this.length - 1);
  3440. },
  3441. pop: function () {
  3442. if (this.length === 0) return undefined;
  3443. var top = this.data[0];
  3444. this.length--;
  3445. if (this.length > 0) {
  3446. this.data[0] = this.data[this.length];
  3447. this._down(0);
  3448. }
  3449. this.data.pop();
  3450. return top;
  3451. },
  3452. peek: function () {
  3453. return this.data[0];
  3454. },
  3455. _up: function (pos) {
  3456. var data = this.data;
  3457. var compare = this.compare;
  3458. var item = data[pos];
  3459. while (pos > 0) {
  3460. var parent = (pos - 1) >> 1;
  3461. var current = data[parent];
  3462. if (compare(item, current) >= 0) break;
  3463. data[pos] = current;
  3464. pos = parent;
  3465. }
  3466. data[pos] = item;
  3467. },
  3468. _down: function (pos) {
  3469. var data = this.data;
  3470. var compare = this.compare;
  3471. var halfLength = this.length >> 1;
  3472. var item = data[pos];
  3473. while (pos < halfLength) {
  3474. var left = (pos << 1) + 1;
  3475. var right = left + 1;
  3476. var best = data[left];
  3477. if (right < this.length && compare(data[right], best) < 0) {
  3478. left = right;
  3479. best = data[right];
  3480. }
  3481. if (compare(best, item) >= 0) break;
  3482. data[pos] = best;
  3483. pos = left;
  3484. }
  3485. data[pos] = item;
  3486. }
  3487. };
  3488. tinyqueue.default = default_1$1;
  3489. var pointInPolygon = function (point, vs) {
  3490. // ray-casting algorithm based on
  3491. // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
  3492. var x = point[0], y = point[1];
  3493. var inside = false;
  3494. for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
  3495. var xi = vs[i][0], yi = vs[i][1];
  3496. var xj = vs[j][0], yj = vs[j][1];
  3497. var intersect = ((yi > y) != (yj > y))
  3498. && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
  3499. if (intersect) inside = !inside;
  3500. }
  3501. return inside;
  3502. };
  3503. var orient = orientation_1[3];
  3504. var concaveman_1 = concaveman;
  3505. var default_1 = concaveman;
  3506. function concaveman(points, concavity, lengthThreshold) {
  3507. // a relative measure of concavity; higher value means simpler hull
  3508. concavity = Math.max(0, concavity === undefined ? 2 : concavity);
  3509. // when a segment goes below this length threshold, it won't be drilled down further
  3510. lengthThreshold = lengthThreshold || 0;
  3511. // start with a convex hull of the points
  3512. var hull = fastConvexHull(points);
  3513. // index the points with an R-tree
  3514. var tree = rbush_1(16, ['[0]', '[1]', '[0]', '[1]']).load(points);
  3515. // turn the convex hull into a linked list and populate the initial edge queue with the nodes
  3516. var queue = [];
  3517. for (var i = 0, last; i < hull.length; i++) {
  3518. var p = hull[i];
  3519. tree.remove(p);
  3520. last = insertNode(p, last);
  3521. queue.push(last);
  3522. }
  3523. // index the segments with an R-tree (for intersection checks)
  3524. var segTree = rbush_1(16);
  3525. for (i = 0; i < queue.length; i++) segTree.insert(updateBBox(queue[i]));
  3526. var sqConcavity = concavity * concavity;
  3527. var sqLenThreshold = lengthThreshold * lengthThreshold;
  3528. // process edges one by one
  3529. while (queue.length) {
  3530. var node = queue.shift();
  3531. var a = node.p;
  3532. var b = node.next.p;
  3533. // skip the edge if it's already short enough
  3534. var sqLen = getSqDist(a, b);
  3535. if (sqLen < sqLenThreshold) continue;
  3536. var maxSqLen = sqLen / sqConcavity;
  3537. // find the best connection point for the current edge to flex inward to
  3538. p = findCandidate(tree, node.prev.p, a, b, node.next.next.p, maxSqLen, segTree);
  3539. // if we found a connection and it satisfies our concavity measure
  3540. if (p && Math.min(getSqDist(p, a), getSqDist(p, b)) <= maxSqLen) {
  3541. // connect the edge endpoints through this point and add 2 new edges to the queue
  3542. queue.push(node);
  3543. queue.push(insertNode(p, node));
  3544. // update point and segment indexes
  3545. tree.remove(p);
  3546. segTree.remove(node);
  3547. segTree.insert(updateBBox(node));
  3548. segTree.insert(updateBBox(node.next));
  3549. }
  3550. }
  3551. // convert the resulting hull linked list to an array of points
  3552. node = last;
  3553. var concave = [];
  3554. do {
  3555. concave.push(node.p);
  3556. node = node.next;
  3557. } while (node !== last);
  3558. concave.push(node.p);
  3559. return concave;
  3560. }
  3561. function findCandidate(tree, a, b, c, d, maxDist, segTree) {
  3562. var queue = new tinyqueue(null, compareDist);
  3563. var node = tree.data;
  3564. // search through the point R-tree with a depth-first search using a priority queue
  3565. // in the order of distance to the edge (b, c)
  3566. while (node) {
  3567. for (var i = 0; i < node.children.length; i++) {
  3568. var child = node.children[i];
  3569. var dist = node.leaf ? sqSegDist(child, b, c) : sqSegBoxDist(b, c, child);
  3570. if (dist > maxDist) continue; // skip the node if it's farther than we ever need
  3571. queue.push({
  3572. node: child,
  3573. dist: dist
  3574. });
  3575. }
  3576. while (queue.length && !queue.peek().node.children) {
  3577. var item = queue.pop();
  3578. var p = item.node;
  3579. // skip all points that are as close to adjacent edges (a,b) and (c,d),
  3580. // and points that would introduce self-intersections when connected
  3581. var d0 = sqSegDist(p, a, b);
  3582. var d1 = sqSegDist(p, c, d);
  3583. if (item.dist < d0 && item.dist < d1 &&
  3584. noIntersections(b, p, segTree) &&
  3585. noIntersections(c, p, segTree)) return p;
  3586. }
  3587. node = queue.pop();
  3588. if (node) node = node.node;
  3589. }
  3590. return null;
  3591. }
  3592. function compareDist(a, b) {
  3593. return a.dist - b.dist;
  3594. }
  3595. // square distance from a segment bounding box to the given one
  3596. function sqSegBoxDist(a, b, bbox) {
  3597. if (inside(a, bbox) || inside(b, bbox)) return 0;
  3598. var d1 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox.minX, bbox.minY, bbox.maxX, bbox.minY);
  3599. if (d1 === 0) return 0;
  3600. var d2 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox.minX, bbox.minY, bbox.minX, bbox.maxY);
  3601. if (d2 === 0) return 0;
  3602. var d3 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox.maxX, bbox.minY, bbox.maxX, bbox.maxY);
  3603. if (d3 === 0) return 0;
  3604. var d4 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox.minX, bbox.maxY, bbox.maxX, bbox.maxY);
  3605. if (d4 === 0) return 0;
  3606. return Math.min(d1, d2, d3, d4);
  3607. }
  3608. function inside(a, bbox) {
  3609. return a[0] >= bbox.minX &&
  3610. a[0] <= bbox.maxX &&
  3611. a[1] >= bbox.minY &&
  3612. a[1] <= bbox.maxY;
  3613. }
  3614. // check if the edge (a,b) doesn't intersect any other edges
  3615. function noIntersections(a, b, segTree) {
  3616. var minX = Math.min(a[0], b[0]);
  3617. var minY = Math.min(a[1], b[1]);
  3618. var maxX = Math.max(a[0], b[0]);
  3619. var maxY = Math.max(a[1], b[1]);
  3620. var edges = segTree.search({minX: minX, minY: minY, maxX: maxX, maxY: maxY});
  3621. for (var i = 0; i < edges.length; i++) {
  3622. if (intersects(edges[i].p, edges[i].next.p, a, b)) return false;
  3623. }
  3624. return true;
  3625. }
  3626. // check if the edges (p1,q1) and (p2,q2) intersect
  3627. function intersects(p1, q1, p2, q2) {
  3628. return p1 !== q2 && q1 !== p2 &&
  3629. orient(p1, q1, p2) > 0 !== orient(p1, q1, q2) > 0 &&
  3630. orient(p2, q2, p1) > 0 !== orient(p2, q2, q1) > 0;
  3631. }
  3632. // update the bounding box of a node's edge
  3633. function updateBBox(node) {
  3634. var p1 = node.p;
  3635. var p2 = node.next.p;
  3636. node.minX = Math.min(p1[0], p2[0]);
  3637. node.minY = Math.min(p1[1], p2[1]);
  3638. node.maxX = Math.max(p1[0], p2[0]);
  3639. node.maxY = Math.max(p1[1], p2[1]);
  3640. return node;
  3641. }
  3642. // speed up convex hull by filtering out points inside quadrilateral formed by 4 extreme points
  3643. function fastConvexHull(points) {
  3644. var left = points[0];
  3645. var top = points[0];
  3646. var right = points[0];
  3647. var bottom = points[0];
  3648. // find the leftmost, rightmost, topmost and bottommost points
  3649. for (var i = 0; i < points.length; i++) {
  3650. var p = points[i];
  3651. if (p[0] < left[0]) left = p;
  3652. if (p[0] > right[0]) right = p;
  3653. if (p[1] < top[1]) top = p;
  3654. if (p[1] > bottom[1]) bottom = p;
  3655. }
  3656. // filter out points that are inside the resulting quadrilateral
  3657. var cull = [left, top, right, bottom];
  3658. var filtered = cull.slice();
  3659. for (i = 0; i < points.length; i++) {
  3660. if (!pointInPolygon(points[i], cull)) filtered.push(points[i]);
  3661. }
  3662. // get convex hull around the filtered points
  3663. var indices = monotoneConvexHull2d(filtered);
  3664. // return the hull as array of points (rather than indices)
  3665. var hull = [];
  3666. for (i = 0; i < indices.length; i++) hull.push(filtered[indices[i]]);
  3667. return hull;
  3668. }
  3669. // create a new node in a doubly linked list
  3670. function insertNode(p, prev) {
  3671. var node = {
  3672. p: p,
  3673. prev: null,
  3674. next: null,
  3675. minX: 0,
  3676. minY: 0,
  3677. maxX: 0,
  3678. maxY: 0
  3679. };
  3680. if (!prev) {
  3681. node.prev = node;
  3682. node.next = node;
  3683. } else {
  3684. node.next = prev.next;
  3685. node.prev = prev;
  3686. prev.next.prev = node;
  3687. prev.next = node;
  3688. }
  3689. return node;
  3690. }
  3691. // square distance between 2 points
  3692. function getSqDist(p1, p2) {
  3693. var dx = p1[0] - p2[0],
  3694. dy = p1[1] - p2[1];
  3695. return dx * dx + dy * dy;
  3696. }
  3697. // square distance from a point to a segment
  3698. function sqSegDist(p, p1, p2) {
  3699. var x = p1[0],
  3700. y = p1[1],
  3701. dx = p2[0] - x,
  3702. dy = p2[1] - y;
  3703. if (dx !== 0 || dy !== 0) {
  3704. var t = ((p[0] - x) * dx + (p[1] - y) * dy) / (dx * dx + dy * dy);
  3705. if (t > 1) {
  3706. x = p2[0];
  3707. y = p2[1];
  3708. } else if (t > 0) {
  3709. x += dx * t;
  3710. y += dy * t;
  3711. }
  3712. }
  3713. dx = p[0] - x;
  3714. dy = p[1] - y;
  3715. return dx * dx + dy * dy;
  3716. }
  3717. // segment to segment distance, ported from http://geomalgorithms.com/a07-_distance.html by Dan Sunday
  3718. function sqSegSegDist(x0, y0, x1, y1, x2, y2, x3, y3) {
  3719. var ux = x1 - x0;
  3720. var uy = y1 - y0;
  3721. var vx = x3 - x2;
  3722. var vy = y3 - y2;
  3723. var wx = x0 - x2;
  3724. var wy = y0 - y2;
  3725. var a = ux * ux + uy * uy;
  3726. var b = ux * vx + uy * vy;
  3727. var c = vx * vx + vy * vy;
  3728. var d = ux * wx + uy * wy;
  3729. var e = vx * wx + vy * wy;
  3730. var D = a * c - b * b;
  3731. var sc, sN, tc, tN;
  3732. var sD = D;
  3733. var tD = D;
  3734. if (D === 0) {
  3735. sN = 0;
  3736. sD = 1;
  3737. tN = e;
  3738. tD = c;
  3739. } else {
  3740. sN = b * e - c * d;
  3741. tN = a * e - b * d;
  3742. if (sN < 0) {
  3743. sN = 0;
  3744. tN = e;
  3745. tD = c;
  3746. } else if (sN > sD) {
  3747. sN = sD;
  3748. tN = e + b;
  3749. tD = c;
  3750. }
  3751. }
  3752. if (tN < 0.0) {
  3753. tN = 0.0;
  3754. if (-d < 0.0) sN = 0.0;
  3755. else if (-d > a) sN = sD;
  3756. else {
  3757. sN = -d;
  3758. sD = a;
  3759. }
  3760. } else if (tN > tD) {
  3761. tN = tD;
  3762. if ((-d + b) < 0.0) sN = 0;
  3763. else if (-d + b > a) sN = sD;
  3764. else {
  3765. sN = -d + b;
  3766. sD = a;
  3767. }
  3768. }
  3769. sc = sN === 0 ? 0 : sN / sD;
  3770. tc = tN === 0 ? 0 : tN / tD;
  3771. var cx = (1 - sc) * x0 + sc * x1;
  3772. var cy = (1 - sc) * y0 + sc * y1;
  3773. var cx2 = (1 - tc) * x2 + tc * x3;
  3774. var cy2 = (1 - tc) * y2 + tc * y3;
  3775. var dx = cx2 - cx;
  3776. var dy = cy2 - cy;
  3777. return dx * dx + dy * dy;
  3778. }
  3779. concaveman_1.default = default_1;
  3780. /**
  3781. * Takes a {@link Feature} or a {@link FeatureCollection} and returns a convex hull {@link Polygon}.
  3782. *
  3783. * Internally this uses
  3784. * the [convex-hull](https://github.com/mikolalysenko/convex-hull) module that
  3785. * implements a [monotone chain hull](http://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain).
  3786. *
  3787. * @name convex
  3788. * @param {GeoJSON} geojson input Feature or FeatureCollection
  3789. * @param {Object} [options={}] Optional parameters
  3790. * @param {number} [options.concavity=Infinity] 1 - thin shape. Infinity - convex hull.
  3791. * @returns {Feature<Polygon>} a convex hull
  3792. * @example
  3793. * var points = turf.featureCollection([
  3794. * turf.point([10.195312, 43.755225]),
  3795. * turf.point([10.404052, 43.8424511]),
  3796. * turf.point([10.579833, 43.659924]),
  3797. * turf.point([10.360107, 43.516688]),
  3798. * turf.point([10.14038, 43.588348]),
  3799. * turf.point([10.195312, 43.755225])
  3800. * ]);
  3801. *
  3802. * var hull = turf.convex(points);
  3803. *
  3804. * //addToMap
  3805. * var addToMap = [points, hull]
  3806. */
  3807. function convex(geojson, options) {
  3808. // Optional parameters
  3809. options = options || {};
  3810. if (!isObject(options)) throw new Error('options is invalid');
  3811. var concavity = options.concavity || Infinity;
  3812. var points$$1 = [];
  3813. // Convert all points to flat 2D coordinate Array
  3814. coordEach(geojson, function (coord) {
  3815. points$$1.push([coord[0], coord[1]]);
  3816. });
  3817. if (!points$$1.length) return null;
  3818. var convexHull = concaveman_1(points$$1, concavity);
  3819. // Convex hull should have at least 3 different vertices in order to create a valid polygon
  3820. if (convexHull.length > 3) {
  3821. return polygon([convexHull]);
  3822. }
  3823. return null;
  3824. }
  3825. // http://en.wikipedia.org/wiki/Even%E2%80%93odd_rule
  3826. // modified from: https://github.com/substack/point-in-polygon/blob/master/index.js
  3827. // which was modified from http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
  3828. /**
  3829. * Takes a {@link Point} and a {@link Polygon} or {@link MultiPolygon} and determines if the point resides inside the polygon. The polygon can
  3830. * be convex or concave. The function accounts for holes.
  3831. *
  3832. * @name booleanPointInPolygon
  3833. * @param {Coord} point input point
  3834. * @param {Feature<Polygon|MultiPolygon>} polygon input polygon or multipolygon
  3835. * @param {Object} [options={}] Optional parameters
  3836. * @param {boolean} [options.ignoreBoundary=false] True if polygon boundary should be ignored when determining if the point is inside the polygon otherwise false.
  3837. * @returns {boolean} `true` if the Point is inside the Polygon; `false` if the Point is not inside the Polygon
  3838. * @example
  3839. * var pt = turf.point([-77, 44]);
  3840. * var poly = turf.polygon([[
  3841. * [-81, 41],
  3842. * [-81, 47],
  3843. * [-72, 47],
  3844. * [-72, 41],
  3845. * [-81, 41]
  3846. * ]]);
  3847. *
  3848. * turf.booleanPointInPolygon(pt, poly);
  3849. * //= true
  3850. */
  3851. function booleanPointInPolygon(point, polygon, options) {
  3852. // Optional parameters
  3853. options = options || {};
  3854. if (typeof options !== 'object') throw new Error('options is invalid');
  3855. var ignoreBoundary = options.ignoreBoundary;
  3856. // validation
  3857. if (!point) throw new Error('point is required');
  3858. if (!polygon) throw new Error('polygon is required');
  3859. var pt = getCoord(point);
  3860. var polys = getCoords(polygon);
  3861. var type = (polygon.geometry) ? polygon.geometry.type : polygon.type;
  3862. var bbox = polygon.bbox;
  3863. // Quick elimination if point is not inside bbox
  3864. if (bbox && inBBox(pt, bbox) === false) return false;
  3865. // normalize to multipolygon
  3866. if (type === 'Polygon') polys = [polys];
  3867. for (var i = 0, insidePoly = false; i < polys.length && !insidePoly; i++) {
  3868. // check if it is in the outer ring first
  3869. if (inRing(pt, polys[i][0], ignoreBoundary)) {
  3870. var inHole = false;
  3871. var k = 1;
  3872. // check for the point in any of the holes
  3873. while (k < polys[i].length && !inHole) {
  3874. if (inRing(pt, polys[i][k], !ignoreBoundary)) {
  3875. inHole = true;
  3876. }
  3877. k++;
  3878. }
  3879. if (!inHole) insidePoly = true;
  3880. }
  3881. }
  3882. return insidePoly;
  3883. }
  3884. /**
  3885. * inRing
  3886. *
  3887. * @private
  3888. * @param {Array<number>} pt [x,y]
  3889. * @param {Array<Array<number>>} ring [[x,y], [x,y],..]
  3890. * @param {boolean} ignoreBoundary ignoreBoundary
  3891. * @returns {boolean} inRing
  3892. */
  3893. function inRing(pt, ring, ignoreBoundary) {
  3894. var isInside = false;
  3895. if (ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1]) ring = ring.slice(0, ring.length - 1);
  3896. for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {
  3897. var xi = ring[i][0], yi = ring[i][1];
  3898. var xj = ring[j][0], yj = ring[j][1];
  3899. var onBoundary = (pt[1] * (xi - xj) + yi * (xj - pt[0]) + yj * (pt[0] - xi) === 0) &&
  3900. ((xi - pt[0]) * (xj - pt[0]) <= 0) && ((yi - pt[1]) * (yj - pt[1]) <= 0);
  3901. if (onBoundary) return !ignoreBoundary;
  3902. var intersect = ((yi > pt[1]) !== (yj > pt[1])) &&
  3903. (pt[0] < (xj - xi) * (pt[1] - yi) / (yj - yi) + xi);
  3904. if (intersect) isInside = !isInside;
  3905. }
  3906. return isInside;
  3907. }
  3908. /**
  3909. * inBBox
  3910. *
  3911. * @private
  3912. * @param {Position} pt point [x,y]
  3913. * @param {BBox} bbox BBox [west, south, east, north]
  3914. * @returns {boolean} true/false if point is inside BBox
  3915. */
  3916. function inBBox(pt, bbox) {
  3917. return bbox[0] <= pt[0] &&
  3918. bbox[1] <= pt[1] &&
  3919. bbox[2] >= pt[0] &&
  3920. bbox[3] >= pt[1];
  3921. }
  3922. /**
  3923. * Finds {@link Points} that fall within {@link (Multi)Polygon(s)}.
  3924. *
  3925. * @name pointsWithinPolygon
  3926. * @param {Feauture|FeatureCollection<Point>} points Points as input search
  3927. * @param {FeatureCollection|Geoemtry|Feature<Polygon|MultiPolygon>} polygons Points must be within these (Multi)Polygon(s)
  3928. * @returns {FeatureCollection<Point>} points that land within at least one polygon
  3929. * @example
  3930. * var points = turf.points([
  3931. * [-46.6318, -23.5523],
  3932. * [-46.6246, -23.5325],
  3933. * [-46.6062, -23.5513],
  3934. * [-46.663, -23.554],
  3935. * [-46.643, -23.557]
  3936. * ]);
  3937. *
  3938. * var searchWithin = turf.polygon([[
  3939. * [-46.653,-23.543],
  3940. * [-46.634,-23.5346],
  3941. * [-46.613,-23.543],
  3942. * [-46.614,-23.559],
  3943. * [-46.631,-23.567],
  3944. * [-46.653,-23.560],
  3945. * [-46.653,-23.543]
  3946. * ]]);
  3947. *
  3948. * var ptsWithin = turf.pointsWithinPolygon(points, searchWithin);
  3949. *
  3950. * //addToMap
  3951. * var addToMap = [points, searchWithin, ptsWithin]
  3952. * turf.featureEach(ptsWithin, function (currentFeature) {
  3953. * currentFeature.properties['marker-size'] = 'large';
  3954. * currentFeature.properties['marker-color'] = '#000';
  3955. * });
  3956. */
  3957. function pointsWithinPolygon(points$$1, polygons$$1) {
  3958. var results = [];
  3959. geomEach(polygons$$1, function (polygon$$1) {
  3960. featureEach(points$$1, function (point$$1) {
  3961. if (booleanPointInPolygon(point$$1, polygon$$1)) results.push(point$$1);
  3962. });
  3963. });
  3964. return featureCollection(results);
  3965. }
  3966. //http://en.wikipedia.org/wiki/Delaunay_triangulation
  3967. //https://github.com/ironwallaby/delaunay
  3968. /**
  3969. * Takes a set of {@link Point|points} and creates a
  3970. * [Triangulated Irregular Network](http://en.wikipedia.org/wiki/Triangulated_irregular_network),
  3971. * or a TIN for short, returned as a collection of Polygons. These are often used
  3972. * for developing elevation contour maps or stepped heat visualizations.
  3973. *
  3974. * If an optional z-value property is provided then it is added as properties called `a`, `b`,
  3975. * and `c` representing its value at each of the points that represent the corners of the
  3976. * triangle.
  3977. *
  3978. * @name tin
  3979. * @param {FeatureCollection<Point>} points input points
  3980. * @param {String} [z] name of the property from which to pull z values
  3981. * This is optional: if not given, then there will be no extra data added to the derived triangles.
  3982. * @returns {FeatureCollection<Polygon>} TIN output
  3983. * @example
  3984. * // generate some random point data
  3985. * var points = turf.randomPoint(30, {bbox: [50, 30, 70, 50]});
  3986. *
  3987. * // add a random property to each point between 0 and 9
  3988. * for (var i = 0; i < points.features.length; i++) {
  3989. * points.features[i].properties.z = ~~(Math.random() * 9);
  3990. * }
  3991. * var tin = turf.tin(points, 'z');
  3992. *
  3993. * //addToMap
  3994. * var addToMap = [tin, points]
  3995. * for (var i = 0; i < tin.features.length; i++) {
  3996. * var properties = tin.features[i].properties;
  3997. * properties.fill = '#' + properties.a + properties.b + properties.c;
  3998. * }
  3999. */
  4000. function tin(points$$1, z) {
  4001. if (points$$1.type !== 'FeatureCollection') throw new Error('points must be a FeatureCollection');
  4002. //break down points
  4003. var isPointZ = false;
  4004. return featureCollection(triangulate(points$$1.features.map(function (p) {
  4005. var point$$1 = {
  4006. x: p.geometry.coordinates[0],
  4007. y: p.geometry.coordinates[1]
  4008. };
  4009. if (z) {
  4010. point$$1.z = p.properties[z];
  4011. } else if (p.geometry.coordinates.length === 3) {
  4012. isPointZ = true;
  4013. point$$1.z = p.geometry.coordinates[2];
  4014. }
  4015. return point$$1;
  4016. })).map(function (triangle) {
  4017. var a = [triangle.a.x, triangle.a.y];
  4018. var b = [triangle.b.x, triangle.b.y];
  4019. var c = [triangle.c.x, triangle.c.y];
  4020. var properties = {};
  4021. // Add z coordinates to triangle points if user passed
  4022. // them in that way otherwise add it as a property.
  4023. if (isPointZ) {
  4024. a.push(triangle.a.z);
  4025. b.push(triangle.b.z);
  4026. c.push(triangle.c.z);
  4027. } else {
  4028. properties = {
  4029. a: triangle.a.z,
  4030. b: triangle.b.z,
  4031. c: triangle.c.z
  4032. };
  4033. }
  4034. return polygon([[a, b, c, a]], properties);
  4035. }));
  4036. }
  4037. function Triangle(a, b, c) {
  4038. this.a = a;
  4039. this.b = b;
  4040. this.c = c;
  4041. var A = b.x - a.x,
  4042. B = b.y - a.y,
  4043. C = c.x - a.x,
  4044. D = c.y - a.y,
  4045. E = A * (a.x + b.x) + B * (a.y + b.y),
  4046. F = C * (a.x + c.x) + D * (a.y + c.y),
  4047. G = 2 * (A * (c.y - b.y) - B * (c.x - b.x)),
  4048. dx, dy;
  4049. // If the points of the triangle are collinear, then just find the
  4050. // extremes and use the midpoint as the center of the circumcircle.
  4051. this.x = (D * E - B * F) / G;
  4052. this.y = (A * F - C * E) / G;
  4053. dx = this.x - a.x;
  4054. dy = this.y - a.y;
  4055. this.r = dx * dx + dy * dy;
  4056. }
  4057. function byX(a, b) {
  4058. return b.x - a.x;
  4059. }
  4060. function dedup(edges) {
  4061. var j = edges.length,
  4062. a, b, i, m, n;
  4063. outer:
  4064. while (j) {
  4065. b = edges[--j];
  4066. a = edges[--j];
  4067. i = j;
  4068. while (i) {
  4069. n = edges[--i];
  4070. m = edges[--i];
  4071. if ((a === m && b === n) || (a === n && b === m)) {
  4072. edges.splice(j, 2);
  4073. edges.splice(i, 2);
  4074. j -= 2;
  4075. continue outer;
  4076. }
  4077. }
  4078. }
  4079. }
  4080. function triangulate(vertices) {
  4081. // Bail if there aren't enough vertices to form any triangles.
  4082. if (vertices.length < 3)
  4083. return [];
  4084. // Ensure the vertex array is in order of descending X coordinate
  4085. // (which is needed to ensure a subquadratic runtime), and then find
  4086. // the bounding box around the points.
  4087. vertices.sort(byX);
  4088. var i = vertices.length - 1,
  4089. xmin = vertices[i].x,
  4090. xmax = vertices[0].x,
  4091. ymin = vertices[i].y,
  4092. ymax = ymin,
  4093. epsilon = 1e-12;
  4094. var a,
  4095. b,
  4096. c,
  4097. A,
  4098. B,
  4099. G;
  4100. while (i--) {
  4101. if (vertices[i].y < ymin)
  4102. ymin = vertices[i].y;
  4103. if (vertices[i].y > ymax)
  4104. ymax = vertices[i].y;
  4105. }
  4106. //Find a supertriangle, which is a triangle that surrounds all the
  4107. //vertices. This is used like something of a sentinel value to remove
  4108. //cases in the main algorithm, and is removed before we return any
  4109. // results.
  4110. // Once found, put it in the "open" list. (The "open" list is for
  4111. // triangles who may still need to be considered; the "closed" list is
  4112. // for triangles which do not.)
  4113. var dx = xmax - xmin,
  4114. dy = ymax - ymin,
  4115. dmax = (dx > dy) ? dx : dy,
  4116. xmid = (xmax + xmin) * 0.5,
  4117. ymid = (ymax + ymin) * 0.5,
  4118. open = [
  4119. new Triangle({
  4120. x: xmid - 20 * dmax,
  4121. y: ymid - dmax,
  4122. __sentinel: true
  4123. }, {
  4124. x: xmid,
  4125. y: ymid + 20 * dmax,
  4126. __sentinel: true
  4127. }, {
  4128. x: xmid + 20 * dmax,
  4129. y: ymid - dmax,
  4130. __sentinel: true
  4131. }
  4132. )],
  4133. closed = [],
  4134. edges = [],
  4135. j;
  4136. // Incrementally add each vertex to the mesh.
  4137. i = vertices.length;
  4138. while (i--) {
  4139. // For each open triangle, check to see if the current point is
  4140. // inside it's circumcircle. If it is, remove the triangle and add
  4141. // it's edges to an edge list.
  4142. edges.length = 0;
  4143. j = open.length;
  4144. while (j--) {
  4145. // If this point is to the right of this triangle's circumcircle,
  4146. // then this triangle should never get checked again. Remove it
  4147. // from the open list, add it to the closed list, and skip.
  4148. dx = vertices[i].x - open[j].x;
  4149. if (dx > 0 && dx * dx > open[j].r) {
  4150. closed.push(open[j]);
  4151. open.splice(j, 1);
  4152. continue;
  4153. }
  4154. // If not, skip this triangle.
  4155. dy = vertices[i].y - open[j].y;
  4156. if (dx * dx + dy * dy > open[j].r)
  4157. continue;
  4158. // Remove the triangle and add it's edges to the edge list.
  4159. edges.push(
  4160. open[j].a, open[j].b,
  4161. open[j].b, open[j].c,
  4162. open[j].c, open[j].a
  4163. );
  4164. open.splice(j, 1);
  4165. }
  4166. // Remove any doubled edges.
  4167. dedup(edges);
  4168. // Add a new triangle for each edge.
  4169. j = edges.length;
  4170. while (j) {
  4171. b = edges[--j];
  4172. a = edges[--j];
  4173. c = vertices[i];
  4174. // Avoid adding colinear triangles (which have error-prone
  4175. // circumcircles)
  4176. A = b.x - a.x;
  4177. B = b.y - a.y;
  4178. G = 2 * (A * (c.y - b.y) - B * (c.x - b.x));
  4179. if (Math.abs(G) > epsilon) {
  4180. open.push(new Triangle(a, b, c));
  4181. }
  4182. }
  4183. }
  4184. // Copy any remaining open triangles to the closed list, and then
  4185. // remove any triangles that share a vertex with the supertriangle.
  4186. Array.prototype.push.apply(closed, open);
  4187. i = closed.length;
  4188. while (i--)
  4189. if (closed[i].a.__sentinel ||
  4190. closed[i].b.__sentinel ||
  4191. closed[i].c.__sentinel)
  4192. closed.splice(i, 1);
  4193. return closed;
  4194. }
  4195. //http://en.wikipedia.org/wiki/Haversine_formula
  4196. //http://www.movable-type.co.uk/scripts/latlong.html
  4197. /**
  4198. * Calculates the distance between two {@link Point|points} in degrees, radians,
  4199. * miles, or kilometers. This uses the
  4200. * [Haversine formula](http://en.wikipedia.org/wiki/Haversine_formula)
  4201. * to account for global curvature.
  4202. *
  4203. * @name distance
  4204. * @param {Coord} from origin point
  4205. * @param {Coord} to destination point
  4206. * @param {Object} [options={}] Optional parameters
  4207. * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers
  4208. * @returns {number} distance between the two points
  4209. * @example
  4210. * var from = turf.point([-75.343, 39.984]);
  4211. * var to = turf.point([-75.534, 39.123]);
  4212. * var options = {units: 'miles'};
  4213. *
  4214. * var distance = turf.distance(from, to, options);
  4215. *
  4216. * //addToMap
  4217. * var addToMap = [from, to];
  4218. * from.properties.distance = distance;
  4219. * to.properties.distance = distance;
  4220. */
  4221. function distance(from, to, options) {
  4222. // Optional parameters
  4223. options = options || {};
  4224. if (!isObject(options)) throw new Error('options is invalid');
  4225. var units = options.units;
  4226. var coordinates1 = getCoord(from);
  4227. var coordinates2 = getCoord(to);
  4228. var dLat = degreesToRadians((coordinates2[1] - coordinates1[1]));
  4229. var dLon = degreesToRadians((coordinates2[0] - coordinates1[0]));
  4230. var lat1 = degreesToRadians(coordinates1[1]);
  4231. var lat2 = degreesToRadians(coordinates2[1]);
  4232. var a = Math.pow(Math.sin(dLat / 2), 2) +
  4233. Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1) * Math.cos(lat2);
  4234. return radiansToLength(2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)), units);
  4235. }
  4236. /**
  4237. * Returns a cloned copy of the passed GeoJSON Object, including possible 'Foreign Members'.
  4238. * ~3-5x faster than the common JSON.parse + JSON.stringify combo method.
  4239. *
  4240. * @name clone
  4241. * @param {GeoJSON} geojson GeoJSON Object
  4242. * @returns {GeoJSON} cloned GeoJSON Object
  4243. * @example
  4244. * var line = turf.lineString([[-74, 40], [-78, 42], [-82, 35]], {color: 'red'});
  4245. *
  4246. * var lineCloned = turf.clone(line);
  4247. */
  4248. function clone(geojson) {
  4249. if (!geojson) throw new Error('geojson is required');
  4250. switch (geojson.type) {
  4251. case 'Feature':
  4252. return cloneFeature(geojson);
  4253. case 'FeatureCollection':
  4254. return cloneFeatureCollection(geojson);
  4255. case 'Point':
  4256. case 'LineString':
  4257. case 'Polygon':
  4258. case 'MultiPoint':
  4259. case 'MultiLineString':
  4260. case 'MultiPolygon':
  4261. case 'GeometryCollection':
  4262. return cloneGeometry(geojson);
  4263. default:
  4264. throw new Error('unknown GeoJSON type');
  4265. }
  4266. }
  4267. /**
  4268. * Clone Feature
  4269. *
  4270. * @private
  4271. * @param {Feature<any>} geojson GeoJSON Feature
  4272. * @returns {Feature<any>} cloned Feature
  4273. */
  4274. function cloneFeature(geojson) {
  4275. var cloned = {type: 'Feature'};
  4276. // Preserve Foreign Members
  4277. Object.keys(geojson).forEach(function (key) {
  4278. switch (key) {
  4279. case 'type':
  4280. case 'properties':
  4281. case 'geometry':
  4282. return;
  4283. default:
  4284. cloned[key] = geojson[key];
  4285. }
  4286. });
  4287. // Add properties & geometry last
  4288. cloned.properties = cloneProperties(geojson.properties);
  4289. cloned.geometry = cloneGeometry(geojson.geometry);
  4290. return cloned;
  4291. }
  4292. /**
  4293. * Clone Properties
  4294. *
  4295. * @private
  4296. * @param {Object} properties GeoJSON Properties
  4297. * @returns {Object} cloned Properties
  4298. */
  4299. function cloneProperties(properties) {
  4300. var cloned = {};
  4301. if (!properties) return cloned;
  4302. Object.keys(properties).forEach(function (key) {
  4303. var value = properties[key];
  4304. if (typeof value === 'object') {
  4305. if (value === null) {
  4306. // handle null
  4307. cloned[key] = null;
  4308. } else if (value.length) {
  4309. // handle Array
  4310. cloned[key] = value.map(function (item) {
  4311. return item;
  4312. });
  4313. } else {
  4314. // handle generic Object
  4315. cloned[key] = cloneProperties(value);
  4316. }
  4317. } else cloned[key] = value;
  4318. });
  4319. return cloned;
  4320. }
  4321. /**
  4322. * Clone Feature Collection
  4323. *
  4324. * @private
  4325. * @param {FeatureCollection<any>} geojson GeoJSON Feature Collection
  4326. * @returns {FeatureCollection<any>} cloned Feature Collection
  4327. */
  4328. function cloneFeatureCollection(geojson) {
  4329. var cloned = {type: 'FeatureCollection'};
  4330. // Preserve Foreign Members
  4331. Object.keys(geojson).forEach(function (key) {
  4332. switch (key) {
  4333. case 'type':
  4334. case 'features':
  4335. return;
  4336. default:
  4337. cloned[key] = geojson[key];
  4338. }
  4339. });
  4340. // Add features
  4341. cloned.features = geojson.features.map(function (feature) {
  4342. return cloneFeature(feature);
  4343. });
  4344. return cloned;
  4345. }
  4346. /**
  4347. * Clone Geometry
  4348. *
  4349. * @private
  4350. * @param {Geometry<any>} geometry GeoJSON Geometry
  4351. * @returns {Geometry<any>} cloned Geometry
  4352. */
  4353. function cloneGeometry(geometry) {
  4354. var geom = {type: geometry.type};
  4355. if (geometry.bbox) geom.bbox = geometry.bbox;
  4356. if (geometry.type === 'GeometryCollection') {
  4357. geom.geometries = geometry.geometries.map(function (geom) {
  4358. return cloneGeometry(geom);
  4359. });
  4360. return geom;
  4361. }
  4362. geom.coordinates = deepSlice(geometry.coordinates);
  4363. return geom;
  4364. }
  4365. /**
  4366. * Deep Slice coordinates
  4367. *
  4368. * @private
  4369. * @param {Coordinates} coords Coordinates
  4370. * @returns {Coordinates} all coordinates sliced
  4371. */
  4372. function deepSlice(coords) {
  4373. if (typeof coords[0] !== 'object') { return coords.slice(); }
  4374. return coords.map(function (coord) {
  4375. return deepSlice(coord);
  4376. });
  4377. }
  4378. var identity = function(x) {
  4379. return x;
  4380. };
  4381. var transform = function(transform) {
  4382. if (transform == null) return identity;
  4383. var x0,
  4384. y0,
  4385. kx = transform.scale[0],
  4386. ky = transform.scale[1],
  4387. dx = transform.translate[0],
  4388. dy = transform.translate[1];
  4389. return function(input, i) {
  4390. if (!i) x0 = y0 = 0;
  4391. var j = 2, n = input.length, output = new Array(n);
  4392. output[0] = (x0 += input[0]) * kx + dx;
  4393. output[1] = (y0 += input[1]) * ky + dy;
  4394. while (j < n) output[j] = input[j], ++j;
  4395. return output;
  4396. };
  4397. };
  4398. var reverse = function(array, n) {
  4399. var t, j = array.length, i = j - n;
  4400. while (i < --j) t = array[i], array[i++] = array[j], array[j] = t;
  4401. };
  4402. function object(topology, o) {
  4403. var transformPoint = transform(topology.transform),
  4404. arcs = topology.arcs;
  4405. function arc(i, points) {
  4406. if (points.length) points.pop();
  4407. for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length; k < n; ++k) {
  4408. points.push(transformPoint(a[k], k));
  4409. }
  4410. if (i < 0) reverse(points, n);
  4411. }
  4412. function point(p) {
  4413. return transformPoint(p);
  4414. }
  4415. function line(arcs) {
  4416. var points = [];
  4417. for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points);
  4418. if (points.length < 2) points.push(points[0]); // This should never happen per the specification.
  4419. return points;
  4420. }
  4421. function ring(arcs) {
  4422. var points = line(arcs);
  4423. while (points.length < 4) points.push(points[0]); // This may happen if an arc has only two points.
  4424. return points;
  4425. }
  4426. function polygon(arcs) {
  4427. return arcs.map(ring);
  4428. }
  4429. function geometry(o) {
  4430. var type = o.type, coordinates;
  4431. switch (type) {
  4432. case "GeometryCollection": return {type: type, geometries: o.geometries.map(geometry)};
  4433. case "Point": coordinates = point(o.coordinates); break;
  4434. case "MultiPoint": coordinates = o.coordinates.map(point); break;
  4435. case "LineString": coordinates = line(o.arcs); break;
  4436. case "MultiLineString": coordinates = o.arcs.map(line); break;
  4437. case "Polygon": coordinates = polygon(o.arcs); break;
  4438. case "MultiPolygon": coordinates = o.arcs.map(polygon); break;
  4439. default: return null;
  4440. }
  4441. return {type: type, coordinates: coordinates};
  4442. }
  4443. return geometry(o);
  4444. }
  4445. var stitch = function(topology, arcs) {
  4446. var stitchedArcs = {},
  4447. fragmentByStart = {},
  4448. fragmentByEnd = {},
  4449. fragments = [],
  4450. emptyIndex = -1;
  4451. // Stitch empty arcs first, since they may be subsumed by other arcs.
  4452. arcs.forEach(function(i, j) {
  4453. var arc = topology.arcs[i < 0 ? ~i : i], t;
  4454. if (arc.length < 3 && !arc[1][0] && !arc[1][1]) {
  4455. t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t;
  4456. }
  4457. });
  4458. arcs.forEach(function(i) {
  4459. var e = ends(i),
  4460. start = e[0],
  4461. end = e[1],
  4462. f, g;
  4463. if (f = fragmentByEnd[start]) {
  4464. delete fragmentByEnd[f.end];
  4465. f.push(i);
  4466. f.end = end;
  4467. if (g = fragmentByStart[end]) {
  4468. delete fragmentByStart[g.start];
  4469. var fg = g === f ? f : f.concat(g);
  4470. fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
  4471. } else {
  4472. fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
  4473. }
  4474. } else if (f = fragmentByStart[end]) {
  4475. delete fragmentByStart[f.start];
  4476. f.unshift(i);
  4477. f.start = start;
  4478. if (g = fragmentByEnd[start]) {
  4479. delete fragmentByEnd[g.end];
  4480. var gf = g === f ? f : g.concat(f);
  4481. fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
  4482. } else {
  4483. fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
  4484. }
  4485. } else {
  4486. f = [i];
  4487. fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f;
  4488. }
  4489. });
  4490. function ends(i) {
  4491. var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1;
  4492. if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; });
  4493. else p1 = arc[arc.length - 1];
  4494. return i < 0 ? [p1, p0] : [p0, p1];
  4495. }
  4496. function flush(fragmentByEnd, fragmentByStart) {
  4497. for (var k in fragmentByEnd) {
  4498. var f = fragmentByEnd[k];
  4499. delete fragmentByStart[f.start];
  4500. delete f.start;
  4501. delete f.end;
  4502. f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; });
  4503. fragments.push(f);
  4504. }
  4505. }
  4506. flush(fragmentByEnd, fragmentByStart);
  4507. flush(fragmentByStart, fragmentByEnd);
  4508. arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); });
  4509. return fragments;
  4510. };
  4511. function planarRingArea(ring) {
  4512. var i = -1, n = ring.length, a, b = ring[n - 1], area = 0;
  4513. while (++i < n) a = b, b = ring[i], area += a[0] * b[1] - a[1] * b[0];
  4514. return Math.abs(area); // Note: doubled area!
  4515. }
  4516. var merge = function(topology) {
  4517. return object(topology, mergeArcs.apply(this, arguments));
  4518. };
  4519. function mergeArcs(topology, objects) {
  4520. var polygonsByArc = {},
  4521. polygons = [],
  4522. groups = [];
  4523. objects.forEach(geometry);
  4524. function geometry(o) {
  4525. switch (o.type) {
  4526. case "GeometryCollection": o.geometries.forEach(geometry); break;
  4527. case "Polygon": extract(o.arcs); break;
  4528. case "MultiPolygon": o.arcs.forEach(extract); break;
  4529. }
  4530. }
  4531. function extract(polygon) {
  4532. polygon.forEach(function(ring) {
  4533. ring.forEach(function(arc) {
  4534. (polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon);
  4535. });
  4536. });
  4537. polygons.push(polygon);
  4538. }
  4539. function area(ring) {
  4540. return planarRingArea(object(topology, {type: "Polygon", arcs: [ring]}).coordinates[0]);
  4541. }
  4542. polygons.forEach(function(polygon) {
  4543. if (!polygon._) {
  4544. var group = [],
  4545. neighbors = [polygon];
  4546. polygon._ = 1;
  4547. groups.push(group);
  4548. while (polygon = neighbors.pop()) {
  4549. group.push(polygon);
  4550. polygon.forEach(function(ring) {
  4551. ring.forEach(function(arc) {
  4552. polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) {
  4553. if (!polygon._) {
  4554. polygon._ = 1;
  4555. neighbors.push(polygon);
  4556. }
  4557. });
  4558. });
  4559. });
  4560. }
  4561. }
  4562. });
  4563. polygons.forEach(function(polygon) {
  4564. delete polygon._;
  4565. });
  4566. return {
  4567. type: "MultiPolygon",
  4568. arcs: groups.map(function(polygons) {
  4569. var arcs = [], n;
  4570. // Extract the exterior (unique) arcs.
  4571. polygons.forEach(function(polygon) {
  4572. polygon.forEach(function(ring) {
  4573. ring.forEach(function(arc) {
  4574. if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) {
  4575. arcs.push(arc);
  4576. }
  4577. });
  4578. });
  4579. });
  4580. // Stitch the arcs into one or more rings.
  4581. arcs = stitch(topology, arcs);
  4582. // If more than one ring is returned,
  4583. // at most one of these rings can be the exterior;
  4584. // choose the one with the greatest absolute area.
  4585. if ((n = arcs.length) > 1) {
  4586. for (var i = 1, k = area(arcs[0]), ki, t; i < n; ++i) {
  4587. if ((ki = area(arcs[i])) > k) {
  4588. t = arcs[0], arcs[0] = arcs[i], arcs[i] = t, k = ki;
  4589. }
  4590. }
  4591. }
  4592. return arcs;
  4593. })
  4594. };
  4595. }
  4596. // Computes the bounding box of the specified hash of GeoJSON objects.
  4597. var bounds = function(objects) {
  4598. var x0 = Infinity,
  4599. y0 = Infinity,
  4600. x1 = -Infinity,
  4601. y1 = -Infinity;
  4602. function boundGeometry(geometry) {
  4603. if (geometry != null && boundGeometryType.hasOwnProperty(geometry.type)) boundGeometryType[geometry.type](geometry);
  4604. }
  4605. var boundGeometryType = {
  4606. GeometryCollection: function(o) { o.geometries.forEach(boundGeometry); },
  4607. Point: function(o) { boundPoint(o.coordinates); },
  4608. MultiPoint: function(o) { o.coordinates.forEach(boundPoint); },
  4609. LineString: function(o) { boundLine(o.arcs); },
  4610. MultiLineString: function(o) { o.arcs.forEach(boundLine); },
  4611. Polygon: function(o) { o.arcs.forEach(boundLine); },
  4612. MultiPolygon: function(o) { o.arcs.forEach(boundMultiLine); }
  4613. };
  4614. function boundPoint(coordinates) {
  4615. var x = coordinates[0],
  4616. y = coordinates[1];
  4617. if (x < x0) x0 = x;
  4618. if (x > x1) x1 = x;
  4619. if (y < y0) y0 = y;
  4620. if (y > y1) y1 = y;
  4621. }
  4622. function boundLine(coordinates) {
  4623. coordinates.forEach(boundPoint);
  4624. }
  4625. function boundMultiLine(coordinates) {
  4626. coordinates.forEach(boundLine);
  4627. }
  4628. for (var key in objects) {
  4629. boundGeometry(objects[key]);
  4630. }
  4631. return x1 >= x0 && y1 >= y0 ? [x0, y0, x1, y1] : undefined;
  4632. };
  4633. var hashset = function(size, hash, equal, type, empty) {
  4634. if (arguments.length === 3) {
  4635. type = Array;
  4636. empty = null;
  4637. }
  4638. var store = new type(size = 1 << Math.max(4, Math.ceil(Math.log(size) / Math.LN2))),
  4639. mask = size - 1;
  4640. for (var i = 0; i < size; ++i) {
  4641. store[i] = empty;
  4642. }
  4643. function add(value) {
  4644. var index = hash(value) & mask,
  4645. match = store[index],
  4646. collisions = 0;
  4647. while (match != empty) {
  4648. if (equal(match, value)) return true;
  4649. if (++collisions >= size) throw new Error("full hashset");
  4650. match = store[index = (index + 1) & mask];
  4651. }
  4652. store[index] = value;
  4653. return true;
  4654. }
  4655. function has(value) {
  4656. var index = hash(value) & mask,
  4657. match = store[index],
  4658. collisions = 0;
  4659. while (match != empty) {
  4660. if (equal(match, value)) return true;
  4661. if (++collisions >= size) break;
  4662. match = store[index = (index + 1) & mask];
  4663. }
  4664. return false;
  4665. }
  4666. function values() {
  4667. var values = [];
  4668. for (var i = 0, n = store.length; i < n; ++i) {
  4669. var match = store[i];
  4670. if (match != empty) values.push(match);
  4671. }
  4672. return values;
  4673. }
  4674. return {
  4675. add: add,
  4676. has: has,
  4677. values: values
  4678. };
  4679. };
  4680. var hashmap = function(size, hash, equal, keyType, keyEmpty, valueType) {
  4681. if (arguments.length === 3) {
  4682. keyType = valueType = Array;
  4683. keyEmpty = null;
  4684. }
  4685. var keystore = new keyType(size = 1 << Math.max(4, Math.ceil(Math.log(size) / Math.LN2))),
  4686. valstore = new valueType(size),
  4687. mask = size - 1;
  4688. for (var i = 0; i < size; ++i) {
  4689. keystore[i] = keyEmpty;
  4690. }
  4691. function set(key, value) {
  4692. var index = hash(key) & mask,
  4693. matchKey = keystore[index],
  4694. collisions = 0;
  4695. while (matchKey != keyEmpty) {
  4696. if (equal(matchKey, key)) return valstore[index] = value;
  4697. if (++collisions >= size) throw new Error("full hashmap");
  4698. matchKey = keystore[index = (index + 1) & mask];
  4699. }
  4700. keystore[index] = key;
  4701. valstore[index] = value;
  4702. return value;
  4703. }
  4704. function maybeSet(key, value) {
  4705. var index = hash(key) & mask,
  4706. matchKey = keystore[index],
  4707. collisions = 0;
  4708. while (matchKey != keyEmpty) {
  4709. if (equal(matchKey, key)) return valstore[index];
  4710. if (++collisions >= size) throw new Error("full hashmap");
  4711. matchKey = keystore[index = (index + 1) & mask];
  4712. }
  4713. keystore[index] = key;
  4714. valstore[index] = value;
  4715. return value;
  4716. }
  4717. function get(key, missingValue) {
  4718. var index = hash(key) & mask,
  4719. matchKey = keystore[index],
  4720. collisions = 0;
  4721. while (matchKey != keyEmpty) {
  4722. if (equal(matchKey, key)) return valstore[index];
  4723. if (++collisions >= size) break;
  4724. matchKey = keystore[index = (index + 1) & mask];
  4725. }
  4726. return missingValue;
  4727. }
  4728. function keys() {
  4729. var keys = [];
  4730. for (var i = 0, n = keystore.length; i < n; ++i) {
  4731. var matchKey = keystore[i];
  4732. if (matchKey != keyEmpty) keys.push(matchKey);
  4733. }
  4734. return keys;
  4735. }
  4736. return {
  4737. set: set,
  4738. maybeSet: maybeSet, // set if unset
  4739. get: get,
  4740. keys: keys
  4741. };
  4742. };
  4743. var equalPoint = function(pointA, pointB) {
  4744. return pointA[0] === pointB[0] && pointA[1] === pointB[1];
  4745. };
  4746. // TODO if quantized, use simpler Int32 hashing?
  4747. var buffer = new ArrayBuffer(16);
  4748. var floats = new Float64Array(buffer);
  4749. var uints = new Uint32Array(buffer);
  4750. var hashPoint = function(point) {
  4751. floats[0] = point[0];
  4752. floats[1] = point[1];
  4753. var hash = uints[0] ^ uints[1];
  4754. hash = hash << 5 ^ hash >> 7 ^ uints[2] ^ uints[3];
  4755. return hash & 0x7fffffff;
  4756. };
  4757. // Given an extracted (pre-)topology, identifies all of the junctions. These are
  4758. // the points at which arcs (lines or rings) will need to be cut so that each
  4759. // arc is represented uniquely.
  4760. //
  4761. // A junction is a point where at least one arc deviates from another arc going
  4762. // through the same point. For example, consider the point B. If there is a arc
  4763. // through ABC and another arc through CBA, then B is not a junction because in
  4764. // both cases the adjacent point pairs are {A,C}. However, if there is an
  4765. // additional arc ABD, then {A,D} != {A,C}, and thus B becomes a junction.
  4766. //
  4767. // For a closed ring ABCA, the first point A’s adjacent points are the second
  4768. // and last point {B,C}. For a line, the first and last point are always
  4769. // considered junctions, even if the line is closed; this ensures that a closed
  4770. // line is never rotated.
  4771. var join = function(topology) {
  4772. var coordinates = topology.coordinates,
  4773. lines = topology.lines,
  4774. rings = topology.rings,
  4775. indexes = index(),
  4776. visitedByIndex = new Int32Array(coordinates.length),
  4777. leftByIndex = new Int32Array(coordinates.length),
  4778. rightByIndex = new Int32Array(coordinates.length),
  4779. junctionByIndex = new Int8Array(coordinates.length),
  4780. junctionCount = 0, // upper bound on number of junctions
  4781. i, n,
  4782. previousIndex,
  4783. currentIndex,
  4784. nextIndex;
  4785. for (i = 0, n = coordinates.length; i < n; ++i) {
  4786. visitedByIndex[i] = leftByIndex[i] = rightByIndex[i] = -1;
  4787. }
  4788. for (i = 0, n = lines.length; i < n; ++i) {
  4789. var line = lines[i],
  4790. lineStart = line[0],
  4791. lineEnd = line[1];
  4792. currentIndex = indexes[lineStart];
  4793. nextIndex = indexes[++lineStart];
  4794. ++junctionCount, junctionByIndex[currentIndex] = 1; // start
  4795. while (++lineStart <= lineEnd) {
  4796. sequence(i, previousIndex = currentIndex, currentIndex = nextIndex, nextIndex = indexes[lineStart]);
  4797. }
  4798. ++junctionCount, junctionByIndex[nextIndex] = 1; // end
  4799. }
  4800. for (i = 0, n = coordinates.length; i < n; ++i) {
  4801. visitedByIndex[i] = -1;
  4802. }
  4803. for (i = 0, n = rings.length; i < n; ++i) {
  4804. var ring = rings[i],
  4805. ringStart = ring[0] + 1,
  4806. ringEnd = ring[1];
  4807. previousIndex = indexes[ringEnd - 1];
  4808. currentIndex = indexes[ringStart - 1];
  4809. nextIndex = indexes[ringStart];
  4810. sequence(i, previousIndex, currentIndex, nextIndex);
  4811. while (++ringStart <= ringEnd) {
  4812. sequence(i, previousIndex = currentIndex, currentIndex = nextIndex, nextIndex = indexes[ringStart]);
  4813. }
  4814. }
  4815. function sequence(i, previousIndex, currentIndex, nextIndex) {
  4816. if (visitedByIndex[currentIndex] === i) return; // ignore self-intersection
  4817. visitedByIndex[currentIndex] = i;
  4818. var leftIndex = leftByIndex[currentIndex];
  4819. if (leftIndex >= 0) {
  4820. var rightIndex = rightByIndex[currentIndex];
  4821. if ((leftIndex !== previousIndex || rightIndex !== nextIndex)
  4822. && (leftIndex !== nextIndex || rightIndex !== previousIndex)) {
  4823. ++junctionCount, junctionByIndex[currentIndex] = 1;
  4824. }
  4825. } else {
  4826. leftByIndex[currentIndex] = previousIndex;
  4827. rightByIndex[currentIndex] = nextIndex;
  4828. }
  4829. }
  4830. function index() {
  4831. var indexByPoint = hashmap(coordinates.length * 1.4, hashIndex, equalIndex, Int32Array, -1, Int32Array),
  4832. indexes = new Int32Array(coordinates.length);
  4833. for (var i = 0, n = coordinates.length; i < n; ++i) {
  4834. indexes[i] = indexByPoint.maybeSet(i, i);
  4835. }
  4836. return indexes;
  4837. }
  4838. function hashIndex(i) {
  4839. return hashPoint(coordinates[i]);
  4840. }
  4841. function equalIndex(i, j) {
  4842. return equalPoint(coordinates[i], coordinates[j]);
  4843. }
  4844. visitedByIndex = leftByIndex = rightByIndex = null;
  4845. var junctionByPoint = hashset(junctionCount * 1.4, hashPoint, equalPoint), j;
  4846. // Convert back to a standard hashset by point for caller convenience.
  4847. for (i = 0, n = coordinates.length; i < n; ++i) {
  4848. if (junctionByIndex[j = indexes[i]]) {
  4849. junctionByPoint.add(coordinates[j]);
  4850. }
  4851. }
  4852. return junctionByPoint;
  4853. };
  4854. // Given an extracted (pre-)topology, cuts (or rotates) arcs so that all shared
  4855. // point sequences are identified. The topology can then be subsequently deduped
  4856. // to remove exact duplicate arcs.
  4857. var cut = function(topology) {
  4858. var junctions = join(topology),
  4859. coordinates = topology.coordinates,
  4860. lines = topology.lines,
  4861. rings = topology.rings,
  4862. next,
  4863. i, n;
  4864. for (i = 0, n = lines.length; i < n; ++i) {
  4865. var line = lines[i],
  4866. lineMid = line[0],
  4867. lineEnd = line[1];
  4868. while (++lineMid < lineEnd) {
  4869. if (junctions.has(coordinates[lineMid])) {
  4870. next = {0: lineMid, 1: line[1]};
  4871. line[1] = lineMid;
  4872. line = line.next = next;
  4873. }
  4874. }
  4875. }
  4876. for (i = 0, n = rings.length; i < n; ++i) {
  4877. var ring = rings[i],
  4878. ringStart = ring[0],
  4879. ringMid = ringStart,
  4880. ringEnd = ring[1],
  4881. ringFixed = junctions.has(coordinates[ringStart]);
  4882. while (++ringMid < ringEnd) {
  4883. if (junctions.has(coordinates[ringMid])) {
  4884. if (ringFixed) {
  4885. next = {0: ringMid, 1: ring[1]};
  4886. ring[1] = ringMid;
  4887. ring = ring.next = next;
  4888. } else { // For the first junction, we can rotate rather than cut.
  4889. rotateArray(coordinates, ringStart, ringEnd, ringEnd - ringMid);
  4890. coordinates[ringEnd] = coordinates[ringStart];
  4891. ringFixed = true;
  4892. ringMid = ringStart; // restart; we may have skipped junctions
  4893. }
  4894. }
  4895. }
  4896. }
  4897. return topology;
  4898. };
  4899. function rotateArray(array, start, end, offset) {
  4900. reverse$1(array, start, end);
  4901. reverse$1(array, start, start + offset);
  4902. reverse$1(array, start + offset, end);
  4903. }
  4904. function reverse$1(array, start, end) {
  4905. for (var mid = start + ((end-- - start) >> 1), t; start < mid; ++start, --end) {
  4906. t = array[start], array[start] = array[end], array[end] = t;
  4907. }
  4908. }
  4909. // Given a cut topology, combines duplicate arcs.
  4910. var dedup$1 = function(topology) {
  4911. var coordinates = topology.coordinates,
  4912. lines = topology.lines, line,
  4913. rings = topology.rings, ring,
  4914. arcCount = lines.length + rings.length,
  4915. i, n;
  4916. delete topology.lines;
  4917. delete topology.rings;
  4918. // Count the number of (non-unique) arcs to initialize the hashmap safely.
  4919. for (i = 0, n = lines.length; i < n; ++i) {
  4920. line = lines[i]; while (line = line.next) ++arcCount;
  4921. }
  4922. for (i = 0, n = rings.length; i < n; ++i) {
  4923. ring = rings[i]; while (ring = ring.next) ++arcCount;
  4924. }
  4925. var arcsByEnd = hashmap(arcCount * 2 * 1.4, hashPoint, equalPoint),
  4926. arcs = topology.arcs = [];
  4927. for (i = 0, n = lines.length; i < n; ++i) {
  4928. line = lines[i];
  4929. do {
  4930. dedupLine(line);
  4931. } while (line = line.next);
  4932. }
  4933. for (i = 0, n = rings.length; i < n; ++i) {
  4934. ring = rings[i];
  4935. if (ring.next) { // arc is no longer closed
  4936. do {
  4937. dedupLine(ring);
  4938. } while (ring = ring.next);
  4939. } else {
  4940. dedupRing(ring);
  4941. }
  4942. }
  4943. function dedupLine(arc) {
  4944. var startPoint,
  4945. endPoint,
  4946. startArcs, startArc,
  4947. endArcs, endArc,
  4948. i, n;
  4949. // Does this arc match an existing arc in order?
  4950. if (startArcs = arcsByEnd.get(startPoint = coordinates[arc[0]])) {
  4951. for (i = 0, n = startArcs.length; i < n; ++i) {
  4952. startArc = startArcs[i];
  4953. if (equalLine(startArc, arc)) {
  4954. arc[0] = startArc[0];
  4955. arc[1] = startArc[1];
  4956. return;
  4957. }
  4958. }
  4959. }
  4960. // Does this arc match an existing arc in reverse order?
  4961. if (endArcs = arcsByEnd.get(endPoint = coordinates[arc[1]])) {
  4962. for (i = 0, n = endArcs.length; i < n; ++i) {
  4963. endArc = endArcs[i];
  4964. if (reverseEqualLine(endArc, arc)) {
  4965. arc[1] = endArc[0];
  4966. arc[0] = endArc[1];
  4967. return;
  4968. }
  4969. }
  4970. }
  4971. if (startArcs) startArcs.push(arc); else arcsByEnd.set(startPoint, [arc]);
  4972. if (endArcs) endArcs.push(arc); else arcsByEnd.set(endPoint, [arc]);
  4973. arcs.push(arc);
  4974. }
  4975. function dedupRing(arc) {
  4976. var endPoint,
  4977. endArcs,
  4978. endArc,
  4979. i, n;
  4980. // Does this arc match an existing line in order, or reverse order?
  4981. // Rings are closed, so their start point and end point is the same.
  4982. if (endArcs = arcsByEnd.get(endPoint = coordinates[arc[0]])) {
  4983. for (i = 0, n = endArcs.length; i < n; ++i) {
  4984. endArc = endArcs[i];
  4985. if (equalRing(endArc, arc)) {
  4986. arc[0] = endArc[0];
  4987. arc[1] = endArc[1];
  4988. return;
  4989. }
  4990. if (reverseEqualRing(endArc, arc)) {
  4991. arc[0] = endArc[1];
  4992. arc[1] = endArc[0];
  4993. return;
  4994. }
  4995. }
  4996. }
  4997. // Otherwise, does this arc match an existing ring in order, or reverse order?
  4998. if (endArcs = arcsByEnd.get(endPoint = coordinates[arc[0] + findMinimumOffset(arc)])) {
  4999. for (i = 0, n = endArcs.length; i < n; ++i) {
  5000. endArc = endArcs[i];
  5001. if (equalRing(endArc, arc)) {
  5002. arc[0] = endArc[0];
  5003. arc[1] = endArc[1];
  5004. return;
  5005. }
  5006. if (reverseEqualRing(endArc, arc)) {
  5007. arc[0] = endArc[1];
  5008. arc[1] = endArc[0];
  5009. return;
  5010. }
  5011. }
  5012. }
  5013. if (endArcs) endArcs.push(arc); else arcsByEnd.set(endPoint, [arc]);
  5014. arcs.push(arc);
  5015. }
  5016. function equalLine(arcA, arcB) {
  5017. var ia = arcA[0], ib = arcB[0],
  5018. ja = arcA[1], jb = arcB[1];
  5019. if (ia - ja !== ib - jb) return false;
  5020. for (; ia <= ja; ++ia, ++ib) if (!equalPoint(coordinates[ia], coordinates[ib])) return false;
  5021. return true;
  5022. }
  5023. function reverseEqualLine(arcA, arcB) {
  5024. var ia = arcA[0], ib = arcB[0],
  5025. ja = arcA[1], jb = arcB[1];
  5026. if (ia - ja !== ib - jb) return false;
  5027. for (; ia <= ja; ++ia, --jb) if (!equalPoint(coordinates[ia], coordinates[jb])) return false;
  5028. return true;
  5029. }
  5030. function equalRing(arcA, arcB) {
  5031. var ia = arcA[0], ib = arcB[0],
  5032. ja = arcA[1], jb = arcB[1],
  5033. n = ja - ia;
  5034. if (n !== jb - ib) return false;
  5035. var ka = findMinimumOffset(arcA),
  5036. kb = findMinimumOffset(arcB);
  5037. for (var i = 0; i < n; ++i) {
  5038. if (!equalPoint(coordinates[ia + (i + ka) % n], coordinates[ib + (i + kb) % n])) return false;
  5039. }
  5040. return true;
  5041. }
  5042. function reverseEqualRing(arcA, arcB) {
  5043. var ia = arcA[0], ib = arcB[0],
  5044. ja = arcA[1], jb = arcB[1],
  5045. n = ja - ia;
  5046. if (n !== jb - ib) return false;
  5047. var ka = findMinimumOffset(arcA),
  5048. kb = n - findMinimumOffset(arcB);
  5049. for (var i = 0; i < n; ++i) {
  5050. if (!equalPoint(coordinates[ia + (i + ka) % n], coordinates[jb - (i + kb) % n])) return false;
  5051. }
  5052. return true;
  5053. }
  5054. // Rings are rotated to a consistent, but arbitrary, start point.
  5055. // This is necessary to detect when a ring and a rotated copy are dupes.
  5056. function findMinimumOffset(arc) {
  5057. var start = arc[0],
  5058. end = arc[1],
  5059. mid = start,
  5060. minimum = mid,
  5061. minimumPoint = coordinates[mid];
  5062. while (++mid < end) {
  5063. var point = coordinates[mid];
  5064. if (point[0] < minimumPoint[0] || point[0] === minimumPoint[0] && point[1] < minimumPoint[1]) {
  5065. minimum = mid;
  5066. minimumPoint = point;
  5067. }
  5068. }
  5069. return minimum - start;
  5070. }
  5071. return topology;
  5072. };
  5073. // Given an array of arcs in absolute (but already quantized!) coordinates,
  5074. // converts to fixed-point delta encoding.
  5075. // This is a destructive operation that modifies the given arcs!
  5076. var delta = function(arcs) {
  5077. var i = -1,
  5078. n = arcs.length;
  5079. while (++i < n) {
  5080. var arc = arcs[i],
  5081. j = 0,
  5082. k = 1,
  5083. m = arc.length,
  5084. point = arc[0],
  5085. x0 = point[0],
  5086. y0 = point[1],
  5087. x1,
  5088. y1;
  5089. while (++j < m) {
  5090. point = arc[j], x1 = point[0], y1 = point[1];
  5091. if (x1 !== x0 || y1 !== y0) arc[k++] = [x1 - x0, y1 - y0], x0 = x1, y0 = y1;
  5092. }
  5093. if (k === 1) arc[k++] = [0, 0]; // Each arc must be an array of two or more positions.
  5094. arc.length = k;
  5095. }
  5096. return arcs;
  5097. };
  5098. // Extracts the lines and rings from the specified hash of geometry objects.
  5099. //
  5100. // Returns an object with three properties:
  5101. //
  5102. // * coordinates - shared buffer of [x, y] coordinates
  5103. // * lines - lines extracted from the hash, of the form [start, end]
  5104. // * rings - rings extracted from the hash, of the form [start, end]
  5105. //
  5106. // For each ring or line, start and end represent inclusive indexes into the
  5107. // coordinates buffer. For rings (and closed lines), coordinates[start] equals
  5108. // coordinates[end].
  5109. //
  5110. // For each line or polygon geometry in the input hash, including nested
  5111. // geometries as in geometry collections, the `coordinates` array is replaced
  5112. // with an equivalent `arcs` array that, for each line (for line string
  5113. // geometries) or ring (for polygon geometries), points to one of the above
  5114. // lines or rings.
  5115. var extract = function(objects) {
  5116. var index = -1,
  5117. lines = [],
  5118. rings = [],
  5119. coordinates = [];
  5120. function extractGeometry(geometry) {
  5121. if (geometry && extractGeometryType.hasOwnProperty(geometry.type)) extractGeometryType[geometry.type](geometry);
  5122. }
  5123. var extractGeometryType = {
  5124. GeometryCollection: function(o) { o.geometries.forEach(extractGeometry); },
  5125. LineString: function(o) { o.arcs = extractLine(o.arcs); },
  5126. MultiLineString: function(o) { o.arcs = o.arcs.map(extractLine); },
  5127. Polygon: function(o) { o.arcs = o.arcs.map(extractRing); },
  5128. MultiPolygon: function(o) { o.arcs = o.arcs.map(extractMultiRing); }
  5129. };
  5130. function extractLine(line) {
  5131. for (var i = 0, n = line.length; i < n; ++i) coordinates[++index] = line[i];
  5132. var arc = {0: index - n + 1, 1: index};
  5133. lines.push(arc);
  5134. return arc;
  5135. }
  5136. function extractRing(ring) {
  5137. for (var i = 0, n = ring.length; i < n; ++i) coordinates[++index] = ring[i];
  5138. var arc = {0: index - n + 1, 1: index};
  5139. rings.push(arc);
  5140. return arc;
  5141. }
  5142. function extractMultiRing(rings) {
  5143. return rings.map(extractRing);
  5144. }
  5145. for (var key in objects) {
  5146. extractGeometry(objects[key]);
  5147. }
  5148. return {
  5149. type: "Topology",
  5150. coordinates: coordinates,
  5151. lines: lines,
  5152. rings: rings,
  5153. objects: objects
  5154. };
  5155. };
  5156. // Given a hash of GeoJSON objects, returns a hash of GeoJSON geometry objects.
  5157. // Any null input geometry objects are represented as {type: null} in the output.
  5158. // Any feature.{id,properties,bbox} are transferred to the output geometry object.
  5159. // Each output geometry object is a shallow copy of the input (e.g., properties, coordinates)!
  5160. var geometry$1 = function(inputs) {
  5161. var outputs = {}, key;
  5162. for (key in inputs) outputs[key] = geomifyObject(inputs[key]);
  5163. return outputs;
  5164. };
  5165. function geomifyObject(input) {
  5166. return input == null ? {type: null}
  5167. : (input.type === "FeatureCollection" ? geomifyFeatureCollection
  5168. : input.type === "Feature" ? geomifyFeature
  5169. : geomifyGeometry)(input);
  5170. }
  5171. function geomifyFeatureCollection(input) {
  5172. var output = {type: "GeometryCollection", geometries: input.features.map(geomifyFeature)};
  5173. if (input.bbox != null) output.bbox = input.bbox;
  5174. return output;
  5175. }
  5176. function geomifyFeature(input) {
  5177. var output = geomifyGeometry(input.geometry), key; // eslint-disable-line no-unused-vars
  5178. if (input.id != null) output.id = input.id;
  5179. if (input.bbox != null) output.bbox = input.bbox;
  5180. for (key in input.properties) { output.properties = input.properties; break; }
  5181. return output;
  5182. }
  5183. function geomifyGeometry(input) {
  5184. if (input == null) return {type: null};
  5185. var output = input.type === "GeometryCollection" ? {type: "GeometryCollection", geometries: input.geometries.map(geomifyGeometry)}
  5186. : input.type === "Point" || input.type === "MultiPoint" ? {type: input.type, coordinates: input.coordinates}
  5187. : {type: input.type, arcs: input.coordinates}; // TODO Check for unknown types?
  5188. if (input.bbox != null) output.bbox = input.bbox;
  5189. return output;
  5190. }
  5191. var prequantize = function(objects, bbox, n) {
  5192. var x0 = bbox[0],
  5193. y0 = bbox[1],
  5194. x1 = bbox[2],
  5195. y1 = bbox[3],
  5196. kx = x1 - x0 ? (n - 1) / (x1 - x0) : 1,
  5197. ky = y1 - y0 ? (n - 1) / (y1 - y0) : 1;
  5198. function quantizePoint(input) {
  5199. return [Math.round((input[0] - x0) * kx), Math.round((input[1] - y0) * ky)];
  5200. }
  5201. function quantizePoints(input, m) {
  5202. var i = -1,
  5203. j = 0,
  5204. n = input.length,
  5205. output = new Array(n), // pessimistic
  5206. pi,
  5207. px,
  5208. py,
  5209. x,
  5210. y;
  5211. while (++i < n) {
  5212. pi = input[i];
  5213. x = Math.round((pi[0] - x0) * kx);
  5214. y = Math.round((pi[1] - y0) * ky);
  5215. if (x !== px || y !== py) output[j++] = [px = x, py = y]; // non-coincident points
  5216. }
  5217. output.length = j;
  5218. while (j < m) j = output.push([output[0][0], output[0][1]]);
  5219. return output;
  5220. }
  5221. function quantizeLine(input) {
  5222. return quantizePoints(input, 2);
  5223. }
  5224. function quantizeRing(input) {
  5225. return quantizePoints(input, 4);
  5226. }
  5227. function quantizePolygon(input) {
  5228. return input.map(quantizeRing);
  5229. }
  5230. function quantizeGeometry(o) {
  5231. if (o != null && quantizeGeometryType.hasOwnProperty(o.type)) quantizeGeometryType[o.type](o);
  5232. }
  5233. var quantizeGeometryType = {
  5234. GeometryCollection: function(o) { o.geometries.forEach(quantizeGeometry); },
  5235. Point: function(o) { o.coordinates = quantizePoint(o.coordinates); },
  5236. MultiPoint: function(o) { o.coordinates = o.coordinates.map(quantizePoint); },
  5237. LineString: function(o) { o.arcs = quantizeLine(o.arcs); },
  5238. MultiLineString: function(o) { o.arcs = o.arcs.map(quantizeLine); },
  5239. Polygon: function(o) { o.arcs = quantizePolygon(o.arcs); },
  5240. MultiPolygon: function(o) { o.arcs = o.arcs.map(quantizePolygon); }
  5241. };
  5242. for (var key in objects) {
  5243. quantizeGeometry(objects[key]);
  5244. }
  5245. return {
  5246. scale: [1 / kx, 1 / ky],
  5247. translate: [x0, y0]
  5248. };
  5249. };
  5250. // Constructs the TopoJSON Topology for the specified hash of features.
  5251. // Each object in the specified hash must be a GeoJSON object,
  5252. // meaning FeatureCollection, a Feature or a geometry object.
  5253. var topology = function(objects, quantization) {
  5254. var bbox = bounds(objects = geometry$1(objects)),
  5255. transform = quantization > 0 && bbox && prequantize(objects, bbox, quantization),
  5256. topology = dedup$1(cut(extract(objects))),
  5257. coordinates = topology.coordinates,
  5258. indexByArc = hashmap(topology.arcs.length * 1.4, hashArc, equalArc);
  5259. objects = topology.objects; // for garbage collection
  5260. topology.bbox = bbox;
  5261. topology.arcs = topology.arcs.map(function(arc, i) {
  5262. indexByArc.set(arc, i);
  5263. return coordinates.slice(arc[0], arc[1] + 1);
  5264. });
  5265. delete topology.coordinates;
  5266. coordinates = null;
  5267. function indexGeometry(geometry) {
  5268. if (geometry && indexGeometryType.hasOwnProperty(geometry.type)) indexGeometryType[geometry.type](geometry);
  5269. }
  5270. var indexGeometryType = {
  5271. GeometryCollection: function(o) { o.geometries.forEach(indexGeometry); },
  5272. LineString: function(o) { o.arcs = indexArcs(o.arcs); },
  5273. MultiLineString: function(o) { o.arcs = o.arcs.map(indexArcs); },
  5274. Polygon: function(o) { o.arcs = o.arcs.map(indexArcs); },
  5275. MultiPolygon: function(o) { o.arcs = o.arcs.map(indexMultiArcs); }
  5276. };
  5277. function indexArcs(arc) {
  5278. var indexes = [];
  5279. do {
  5280. var index = indexByArc.get(arc);
  5281. indexes.push(arc[0] < arc[1] ? index : ~index);
  5282. } while (arc = arc.next);
  5283. return indexes;
  5284. }
  5285. function indexMultiArcs(arcs) {
  5286. return arcs.map(indexArcs);
  5287. }
  5288. for (var key in objects) {
  5289. indexGeometry(objects[key]);
  5290. }
  5291. if (transform) {
  5292. topology.transform = transform;
  5293. topology.arcs = delta(topology.arcs);
  5294. }
  5295. return topology;
  5296. };
  5297. function hashArc(arc) {
  5298. var i = arc[0], j = arc[1], t;
  5299. if (j < i) t = i, i = j, j = t;
  5300. return i + 31 * j;
  5301. }
  5302. function equalArc(arcA, arcB) {
  5303. var ia = arcA[0], ja = arcA[1],
  5304. ib = arcB[0], jb = arcB[1], t;
  5305. if (ja < ia) t = ia, ia = ja, ja = t;
  5306. if (jb < ib) t = ib, ib = jb, jb = t;
  5307. return ia === ib && ja === jb;
  5308. }
  5309. /**
  5310. * Merges all connected (non-forking, non-junctioning) line strings into single lineStrings.
  5311. * [LineString] -> LineString|MultiLineString
  5312. *
  5313. * @param {FeatureCollection<LineString|MultiLineString>} geojson Lines to dissolve
  5314. * @param {Object} [options={}] Optional parameters
  5315. * @param {boolean} [options.mutate=false] Prevent input mutation
  5316. * @returns {Feature<LineString|MultiLineString>} Dissolved lines
  5317. */
  5318. function lineDissolve(geojson, options) {
  5319. // Optional parameters
  5320. options = options || {};
  5321. if (!isObject(options)) throw new Error('options is invalid');
  5322. var mutate = options.mutate;
  5323. // Validation
  5324. if (getType(geojson) !== 'FeatureCollection') throw new Error('geojson must be a FeatureCollection');
  5325. if (!geojson.features.length) throw new Error('geojson is empty');
  5326. // Clone geojson to avoid side effects
  5327. if (mutate === false || mutate === undefined) geojson = clone(geojson);
  5328. var result = [];
  5329. var lastLine = lineReduce(geojson, function (previousLine, currentLine) {
  5330. // Attempt to merge this LineString with the other LineStrings, updating
  5331. // the reference as it is merged with others and grows.
  5332. var merged = mergeLineStrings(previousLine, currentLine);
  5333. // Accumulate the merged LineString
  5334. if (merged) return merged;
  5335. // Put the unmerged LineString back into the list
  5336. else {
  5337. result.push(previousLine);
  5338. return currentLine;
  5339. }
  5340. });
  5341. // Append the last line
  5342. if (lastLine) result.push(lastLine);
  5343. // Return null if no lines were dissolved
  5344. if (!result.length) return null;
  5345. // Return LineString if only 1 line was dissolved
  5346. else if (result.length === 1) return result[0];
  5347. // Return MultiLineString if multiple lines were dissolved with gaps
  5348. else return multiLineString(result.map(function (line) { return line.coordinates; }));
  5349. }
  5350. // [Number, Number] -> String
  5351. function coordId(coord) {
  5352. return coord[0].toString() + ',' + coord[1].toString();
  5353. }
  5354. /**
  5355. * LineString, LineString -> LineString
  5356. *
  5357. * @private
  5358. * @param {Feature<LineString>} a line1
  5359. * @param {Feature<LineString>} b line2
  5360. * @returns {Feature<LineString>|null} Merged LineString
  5361. */
  5362. function mergeLineStrings(a, b) {
  5363. var coords1 = a.geometry.coordinates;
  5364. var coords2 = b.geometry.coordinates;
  5365. var s1 = coordId(coords1[0]);
  5366. var e1 = coordId(coords1[coords1.length - 1]);
  5367. var s2 = coordId(coords2[0]);
  5368. var e2 = coordId(coords2[coords2.length - 1]);
  5369. // TODO: handle case where more than one of these is true!
  5370. var coords;
  5371. if (s1 === e2) coords = coords2.concat(coords1.slice(1));
  5372. else if (s2 === e1) coords = coords1.concat(coords2.slice(1));
  5373. else if (s1 === s2) coords = coords1.slice(1).reverse().concat(coords2);
  5374. else if (e1 === e2) coords = coords1.concat(coords2.reverse().slice(1));
  5375. else return null;
  5376. return lineString(coords);
  5377. }
  5378. /**
  5379. * Dissolves all overlapping (Multi)Polygon
  5380. *
  5381. * @param {FeatureCollection<Polygon|MultiPolygon>} geojson Polygons to dissolve
  5382. * @param {Object} [options={}] Optional parameters
  5383. * @param {boolean} [options.mutate=false] Prevent input mutation
  5384. * @returns {Feature<Polygon|MultiPolygon>} Dissolved Polygons
  5385. */
  5386. function polygonDissolve(geojson, options) {
  5387. // Optional parameters
  5388. options = options || {};
  5389. if (!isObject(options)) throw new Error('options is invalid');
  5390. var mutate = options.mutate;
  5391. // Validation
  5392. if (getType(geojson) !== 'FeatureCollection') throw new Error('geojson must be a FeatureCollection');
  5393. if (!geojson.features.length) throw new Error('geojson is empty');
  5394. // Clone geojson to avoid side effects
  5395. // Topojson modifies in place, so we need to deep clone first
  5396. if (mutate === false || mutate === undefined) geojson = clone(geojson);
  5397. var geoms = [];
  5398. flattenEach(geojson, function (feature$$1) {
  5399. geoms.push(feature$$1.geometry);
  5400. });
  5401. var topo = topology({geoms: geometryCollection(geoms).geometry});
  5402. return merge(topo, topo.objects.geoms.geometries);
  5403. }
  5404. /**
  5405. * Transform function: attempts to dissolve geojson objects where possible
  5406. * [GeoJSON] -> GeoJSON geometry
  5407. *
  5408. * @private
  5409. * @param {FeatureCollection<LineString|MultiLineString|Polygon|MultiPolygon>} geojson Features to dissolved
  5410. * @param {Object} [options={}] Optional parameters
  5411. * @param {boolean} [options.mutate=false] Prevent input mutation
  5412. * @returns {Feature<MultiLineString|MultiPolygon>} Dissolved Features
  5413. */
  5414. function dissolve(geojson, options) {
  5415. // Optional parameters
  5416. options = options || {};
  5417. if (!isObject(options)) throw new Error('options is invalid');
  5418. var mutate = options.mutate;
  5419. // Validation
  5420. if (getType(geojson) !== 'FeatureCollection') throw new Error('geojson must be a FeatureCollection');
  5421. if (!geojson.features.length) throw new Error('geojson is empty');
  5422. // Clone geojson to avoid side effects
  5423. // Topojson modifies in place, so we need to deep clone first
  5424. if (mutate === false || mutate === undefined) geojson = clone(geojson);
  5425. // Assert homogenity
  5426. var type = getHomogenousType(geojson);
  5427. if (!type) throw new Error('geojson must be homogenous');
  5428. switch (type) {
  5429. case 'LineString':
  5430. return lineDissolve(geojson, options);
  5431. case 'Polygon':
  5432. return polygonDissolve(geojson, options);
  5433. default:
  5434. throw new Error(type + ' is not supported');
  5435. }
  5436. }
  5437. /**
  5438. * Checks if GeoJSON is Homogenous
  5439. *
  5440. * @private
  5441. * @param {GeoJSON} geojson GeoJSON
  5442. * @returns {string|null} Homogenous type or null if multiple types
  5443. */
  5444. function getHomogenousType(geojson) {
  5445. var types = {};
  5446. flattenEach(geojson, function (feature$$1) {
  5447. types[feature$$1.geometry.type] = true;
  5448. });
  5449. var keys = Object.keys(types);
  5450. if (keys.length === 1) return keys[0];
  5451. return null;
  5452. }
  5453. /**
  5454. * Takes a set of {@link Point|points} and returns a concave hull Polygon or MultiPolygon.
  5455. * Internally, this uses [turf-tin](https://github.com/Turfjs/turf-tin) to generate geometries.
  5456. *
  5457. * @name concave
  5458. * @param {FeatureCollection<Point>} points input points
  5459. * @param {Object} [options={}] Optional parameters
  5460. * @param {number} [options.maxEdge=Infinity] the length (in 'units') of an edge necessary for part of the hull to become concave.
  5461. * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers
  5462. * @returns {Feature<(Polygon|MultiPolygon)>|null} a concave hull (null value is returned if unable to compute hull)
  5463. * @example
  5464. * var points = turf.featureCollection([
  5465. * turf.point([-63.601226, 44.642643]),
  5466. * turf.point([-63.591442, 44.651436]),
  5467. * turf.point([-63.580799, 44.648749]),
  5468. * turf.point([-63.573589, 44.641788]),
  5469. * turf.point([-63.587665, 44.64533]),
  5470. * turf.point([-63.595218, 44.64765])
  5471. * ]);
  5472. * var options = {units: 'miles', maxEdge: 1};
  5473. *
  5474. * var hull = turf.concave(points, options);
  5475. *
  5476. * //addToMap
  5477. * var addToMap = [points, hull]
  5478. */
  5479. function concave(points$$1, options) {
  5480. // Optional parameters
  5481. options = options || {};
  5482. if (!isObject(options)) throw new Error('options is invalid');
  5483. // validation
  5484. if (!points$$1) throw new Error('points is required');
  5485. var maxEdge = options.maxEdge || Infinity;
  5486. if (!isNumber(maxEdge)) throw new Error('maxEdge is invalid');
  5487. var cleaned = removeDuplicates(points$$1);
  5488. var tinPolys = tin(cleaned);
  5489. // calculate length of all edges and area of all triangles
  5490. // and remove triangles that fail the max length test
  5491. tinPolys.features = tinPolys.features.filter(function (triangle) {
  5492. var pt1 = triangle.geometry.coordinates[0][0];
  5493. var pt2 = triangle.geometry.coordinates[0][1];
  5494. var pt3 = triangle.geometry.coordinates[0][2];
  5495. var dist1 = distance(pt1, pt2, options);
  5496. var dist2 = distance(pt2, pt3, options);
  5497. var dist3 = distance(pt1, pt3, options);
  5498. return (dist1 <= maxEdge && dist2 <= maxEdge && dist3 <= maxEdge);
  5499. });
  5500. if (tinPolys.features.length < 1) return null;
  5501. // merge the adjacent triangles
  5502. var dissolved = dissolve(tinPolys, options);
  5503. // geojson-dissolve always returns a MultiPolygon
  5504. if (dissolved.coordinates.length === 1) {
  5505. dissolved.coordinates = dissolved.coordinates[0];
  5506. dissolved.type = 'Polygon';
  5507. }
  5508. return feature(dissolved);
  5509. }
  5510. /**
  5511. * Removes duplicated points in a collection returning a new collection
  5512. *
  5513. * @private
  5514. * @param {FeatureCollection<Point>} points to be cleaned
  5515. * @returns {FeatureCollection<Point>} cleaned set of points
  5516. */
  5517. function removeDuplicates(points$$1) {
  5518. var cleaned = [];
  5519. var existing = {};
  5520. featureEach(points$$1, function (pt) {
  5521. if (!pt.geometry) return;
  5522. var key = pt.geometry.coordinates.join('-');
  5523. if (!existing.hasOwnProperty(key)) {
  5524. cleaned.push(pt);
  5525. existing[key] = true;
  5526. }
  5527. });
  5528. return featureCollection(cleaned);
  5529. }
  5530. /**
  5531. * Merges a specified property from a FeatureCollection of points into a
  5532. * FeatureCollection of polygons. Given an `inProperty` on points and an `outProperty`
  5533. * for polygons, this finds every point that lies within each polygon, collects the
  5534. * `inProperty` values from those points, and adds them as an array to `outProperty`
  5535. * on the polygon.
  5536. *
  5537. * @name collect
  5538. * @param {FeatureCollection<Polygon>} polygons polygons with values on which to aggregate
  5539. * @param {FeatureCollection<Point>} points points to be aggregated
  5540. * @param {string} inProperty property to be nested from
  5541. * @param {string} outProperty property to be nested into
  5542. * @returns {FeatureCollection<Polygon>} polygons with properties listed based on `outField`
  5543. * @example
  5544. * var poly1 = turf.polygon([[[0,0],[10,0],[10,10],[0,10],[0,0]]]);
  5545. * var poly2 = turf.polygon([[[10,0],[20,10],[20,20],[20,0],[10,0]]]);
  5546. * var polyFC = turf.featureCollection([poly1, poly2]);
  5547. * var pt1 = turf.point([5,5], {population: 200});
  5548. * var pt2 = turf.point([1,3], {population: 600});
  5549. * var pt3 = turf.point([14,2], {population: 100});
  5550. * var pt4 = turf.point([13,1], {population: 200});
  5551. * var pt5 = turf.point([19,7], {population: 300});
  5552. * var pointFC = turf.featureCollection([pt1, pt2, pt3, pt4, pt5]);
  5553. * var collected = turf.collect(polyFC, pointFC, 'population', 'values');
  5554. * var values = collected.features[0].properties.values
  5555. * //=values => [200, 600]
  5556. *
  5557. * //addToMap
  5558. * var addToMap = [pointFC, collected]
  5559. */
  5560. function collect(polygons, points, inProperty, outProperty) {
  5561. var rtree = rbush_1(6);
  5562. var treeItems = points.features.map(function (item) {
  5563. return {
  5564. minX: item.geometry.coordinates[0],
  5565. minY: item.geometry.coordinates[1],
  5566. maxX: item.geometry.coordinates[0],
  5567. maxY: item.geometry.coordinates[1],
  5568. property: item.properties[inProperty]
  5569. };
  5570. });
  5571. rtree.load(treeItems);
  5572. polygons.features.forEach(function (poly) {
  5573. if (!poly.properties) {
  5574. poly.properties = {};
  5575. }
  5576. var bbox$$1 = bbox(poly);
  5577. var potentialPoints = rtree.search({minX: bbox$$1[0], minY: bbox$$1[1], maxX: bbox$$1[2], maxY: bbox$$1[3]});
  5578. var values = [];
  5579. potentialPoints.forEach(function (pt) {
  5580. if (booleanPointInPolygon([pt.minX, pt.minY], poly)) {
  5581. values.push(pt.property);
  5582. }
  5583. });
  5584. poly.properties[outProperty] = values;
  5585. });
  5586. return polygons;
  5587. }
  5588. /**
  5589. * Takes input features and flips all of their coordinates from `[x, y]` to `[y, x]`.
  5590. *
  5591. * @name flip
  5592. * @param {GeoJSON} geojson input features
  5593. * @param {Object} [options={}] Optional parameters
  5594. * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
  5595. * @returns {GeoJSON} a feature or set of features of the same type as `input` with flipped coordinates
  5596. * @example
  5597. * var serbia = turf.point([20.566406, 43.421008]);
  5598. *
  5599. * var saudiArabia = turf.flip(serbia);
  5600. *
  5601. * //addToMap
  5602. * var addToMap = [serbia, saudiArabia];
  5603. */
  5604. function flip(geojson, options) {
  5605. // Optional parameters
  5606. options = options || {};
  5607. if (!isObject(options)) throw new Error('options is invalid');
  5608. var mutate = options.mutate;
  5609. if (!geojson) throw new Error('geojson is required');
  5610. // ensure that we don't modify features in-place and changes to the
  5611. // output do not change the previous feature, including changes to nested
  5612. // properties.
  5613. if (mutate === false || mutate === undefined) geojson = clone(geojson);
  5614. coordEach(geojson, function (coord) {
  5615. var x = coord[0];
  5616. var y = coord[1];
  5617. coord[0] = y;
  5618. coord[1] = x;
  5619. });
  5620. return geojson;
  5621. }
  5622. /**
  5623. * Removes redundant coordinates from any GeoJSON Geometry.
  5624. *
  5625. * @name cleanCoords
  5626. * @param {Geometry|Feature} geojson Feature or Geometry
  5627. * @param {Object} [options={}] Optional parameters
  5628. * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated
  5629. * @returns {Geometry|Feature} the cleaned input Feature/Geometry
  5630. * @example
  5631. * var line = turf.lineString([[0, 0], [0, 2], [0, 5], [0, 8], [0, 8], [0, 10]]);
  5632. * var multiPoint = turf.multiPoint([[0, 0], [0, 0], [2, 2]]);
  5633. *
  5634. * turf.cleanCoords(line).geometry.coordinates;
  5635. * //= [[0, 0], [0, 10]]
  5636. *
  5637. * turf.cleanCoords(multiPoint).geometry.coordinates;
  5638. * //= [[0, 0], [2, 2]]
  5639. */
  5640. function cleanCoords(geojson, options) {
  5641. // Backwards compatible with v4.0
  5642. var mutate = (typeof options === 'object') ? options.mutate : options;
  5643. if (!geojson) throw new Error('geojson is required');
  5644. var type = getType(geojson);
  5645. // Store new "clean" points in this Array
  5646. var newCoords = [];
  5647. switch (type) {
  5648. case 'LineString':
  5649. newCoords = cleanLine(geojson);
  5650. break;
  5651. case 'MultiLineString':
  5652. case 'Polygon':
  5653. getCoords(geojson).forEach(function (line) {
  5654. newCoords.push(cleanLine(line));
  5655. });
  5656. break;
  5657. case 'MultiPolygon':
  5658. getCoords(geojson).forEach(function (polygons$$1) {
  5659. var polyPoints = [];
  5660. polygons$$1.forEach(function (ring) {
  5661. polyPoints.push(cleanLine(ring));
  5662. });
  5663. newCoords.push(polyPoints);
  5664. });
  5665. break;
  5666. case 'Point':
  5667. return geojson;
  5668. case 'MultiPoint':
  5669. var existing = {};
  5670. getCoords(geojson).forEach(function (coord) {
  5671. var key = coord.join('-');
  5672. if (!existing.hasOwnProperty(key)) {
  5673. newCoords.push(coord);
  5674. existing[key] = true;
  5675. }
  5676. });
  5677. break;
  5678. default:
  5679. throw new Error(type + ' geometry not supported');
  5680. }
  5681. // Support input mutation
  5682. if (geojson.coordinates) {
  5683. if (mutate === true) {
  5684. geojson.coordinates = newCoords;
  5685. return geojson;
  5686. }
  5687. return {type: type, coordinates: newCoords};
  5688. } else {
  5689. if (mutate === true) {
  5690. geojson.geometry.coordinates = newCoords;
  5691. return geojson;
  5692. }
  5693. return feature({type: type, coordinates: newCoords}, geojson.properties, geojson.bbox, geojson.id);
  5694. }
  5695. }
  5696. /**
  5697. * Clean Coords
  5698. *
  5699. * @private
  5700. * @param {Array<number>|LineString} line Line
  5701. * @returns {Array<number>} Cleaned coordinates
  5702. */
  5703. function cleanLine(line) {
  5704. var points$$1 = getCoords(line);
  5705. // handle "clean" segment
  5706. if (points$$1.length === 2 && !equals(points$$1[0], points$$1[1])) return points$$1;
  5707. var prevPoint, point$$1, nextPoint;
  5708. var newPoints = [];
  5709. var secondToLast = points$$1.length - 1;
  5710. newPoints.push(points$$1[0]);
  5711. for (var i = 1; i < secondToLast; i++) {
  5712. prevPoint = points$$1[i - 1];
  5713. point$$1 = points$$1[i];
  5714. nextPoint = points$$1[i + 1];
  5715. if (!isPointOnLineSegment(prevPoint, nextPoint, point$$1)) {
  5716. newPoints.push(point$$1);
  5717. }
  5718. }
  5719. newPoints.push(nextPoint);
  5720. return newPoints;
  5721. }
  5722. /**
  5723. * Compares two points and returns if they are equals
  5724. *
  5725. * @private
  5726. * @param {Position} pt1 point
  5727. * @param {Position} pt2 point
  5728. * @returns {boolean} true if they are equals
  5729. */
  5730. function equals(pt1, pt2) {
  5731. return pt1[0] === pt2[0] && pt1[1] === pt2[1];
  5732. }
  5733. /**
  5734. * Returns if `point` is on the segment between `start` and `end`.
  5735. * Borrowed from `@turf/boolean-point-on-line` to speed up the evaluation (instead of using the module as dependency)
  5736. *
  5737. * @private
  5738. * @param {Position} start coord pair of start of line
  5739. * @param {Position} end coord pair of end of line
  5740. * @param {Position} point coord pair of point to check
  5741. * @returns {boolean} true/false
  5742. */
  5743. function isPointOnLineSegment(start, end, point$$1) {
  5744. var x = point$$1[0], y = point$$1[1];
  5745. var startX = start[0], startY = start[1];
  5746. var endX = end[0], endY = end[1];
  5747. var dxc = x - startX;
  5748. var dyc = y - startY;
  5749. var dxl = endX - startX;
  5750. var dyl = endY - startY;
  5751. var cross = dxc * dyl - dyc * dxl;
  5752. if (cross !== 0) return false;
  5753. else if (Math.abs(dxl) >= Math.abs(dyl)) return dxl > 0 ? startX <= x && x <= endX : endX <= x && x <= startX;
  5754. else return dyl > 0 ? startY <= y && y <= endY : endY <= y && y <= startY;
  5755. }
  5756. /*
  5757. (c) 2013, Vladimir Agafonkin
  5758. Simplify.js, a high-performance JS polyline simplification library
  5759. mourner.github.io/simplify-js
  5760. */
  5761. // to suit your point format, run search/replace for '.x' and '.y';
  5762. // for 3D version, see 3d branch (configurability would draw significant performance overhead)
  5763. // square distance between 2 points
  5764. function getSqDist$1(p1, p2) {
  5765. var dx = p1.x - p2.x,
  5766. dy = p1.y - p2.y;
  5767. return dx * dx + dy * dy;
  5768. }
  5769. // square distance from a point to a segment
  5770. function getSqSegDist(p, p1, p2) {
  5771. var x = p1.x,
  5772. y = p1.y,
  5773. dx = p2.x - x,
  5774. dy = p2.y - y;
  5775. if (dx !== 0 || dy !== 0) {
  5776. var t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
  5777. if (t > 1) {
  5778. x = p2.x;
  5779. y = p2.y;
  5780. } else if (t > 0) {
  5781. x += dx * t;
  5782. y += dy * t;
  5783. }
  5784. }
  5785. dx = p.x - x;
  5786. dy = p.y - y;
  5787. return dx * dx + dy * dy;
  5788. }
  5789. // rest of the code doesn't care about point format
  5790. // basic distance-based simplification
  5791. function simplifyRadialDist(points$$1, sqTolerance) {
  5792. var prevPoint = points$$1[0],
  5793. newPoints = [prevPoint],
  5794. point$$1;
  5795. for (var i = 1, len = points$$1.length; i < len; i++) {
  5796. point$$1 = points$$1[i];
  5797. if (getSqDist$1(point$$1, prevPoint) > sqTolerance) {
  5798. newPoints.push(point$$1);
  5799. prevPoint = point$$1;
  5800. }
  5801. }
  5802. if (prevPoint !== point$$1) newPoints.push(point$$1);
  5803. return newPoints;
  5804. }
  5805. function simplifyDPStep(points$$1, first, last, sqTolerance, simplified) {
  5806. var maxSqDist = sqTolerance,
  5807. index;
  5808. for (var i = first + 1; i < last; i++) {
  5809. var sqDist = getSqSegDist(points$$1[i], points$$1[first], points$$1[last]);
  5810. if (sqDist > maxSqDist) {
  5811. index = i;
  5812. maxSqDist = sqDist;
  5813. }
  5814. }
  5815. if (maxSqDist > sqTolerance) {
  5816. if (index - first > 1) simplifyDPStep(points$$1, first, index, sqTolerance, simplified);
  5817. simplified.push(points$$1[index]);
  5818. if (last - index > 1) simplifyDPStep(points$$1, index, last, sqTolerance, simplified);
  5819. }
  5820. }
  5821. // simplification using Ramer-Douglas-Peucker algorithm
  5822. function simplifyDouglasPeucker(points$$1, sqTolerance) {
  5823. var last = points$$1.length - 1;
  5824. var simplified = [points$$1[0]];
  5825. simplifyDPStep(points$$1, 0, last, sqTolerance, simplified);
  5826. simplified.push(points$$1[last]);
  5827. return simplified;
  5828. }
  5829. // both algorithms combined for awesome performance
  5830. function simplify$2(points$$1, tolerance, highestQuality) {
  5831. if (points$$1.length <= 2) return points$$1;
  5832. var sqTolerance = tolerance !== undefined ? tolerance * tolerance : 1;
  5833. points$$1 = highestQuality ? points$$1 : simplifyRadialDist(points$$1, sqTolerance);
  5834. points$$1 = simplifyDouglasPeucker(points$$1, sqTolerance);
  5835. return points$$1;
  5836. }
  5837. /**
  5838. * Takes a {@link GeoJSON} object and returns a simplified version. Internally uses
  5839. * [simplify-js](http://mourner.github.io/simplify-js/) to perform simplification using the Ramer-Douglas-Peucker algorithm.
  5840. *
  5841. * @name simplify
  5842. * @param {GeoJSON} geojson object to be simplified
  5843. * @param {Object} [options={}] Optional parameters
  5844. * @param {number} [options.tolerance=1] simplification tolerance
  5845. * @param {boolean} [options.highQuality=false] whether or not to spend more time to create a higher-quality simplification with a different algorithm
  5846. * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
  5847. * @returns {GeoJSON} a simplified GeoJSON
  5848. * @example
  5849. * var geojson = turf.polygon([[
  5850. * [-70.603637, -33.399918],
  5851. * [-70.614624, -33.395332],
  5852. * [-70.639343, -33.392466],
  5853. * [-70.659942, -33.394759],
  5854. * [-70.683975, -33.404504],
  5855. * [-70.697021, -33.419406],
  5856. * [-70.701141, -33.434306],
  5857. * [-70.700454, -33.446339],
  5858. * [-70.694274, -33.458369],
  5859. * [-70.682601, -33.465816],
  5860. * [-70.668869, -33.472117],
  5861. * [-70.646209, -33.473835],
  5862. * [-70.624923, -33.472117],
  5863. * [-70.609817, -33.468107],
  5864. * [-70.595397, -33.458369],
  5865. * [-70.587158, -33.442901],
  5866. * [-70.587158, -33.426283],
  5867. * [-70.590591, -33.414248],
  5868. * [-70.594711, -33.406224],
  5869. * [-70.603637, -33.399918]
  5870. * ]]);
  5871. * var options = {tolerance: 0.01, highQuality: false};
  5872. * var simplified = turf.simplify(geojson, options);
  5873. *
  5874. * //addToMap
  5875. * var addToMap = [geojson, simplified]
  5876. */
  5877. function simplify(geojson, options) {
  5878. // Optional parameters
  5879. options = options || {};
  5880. if (!isObject(options)) throw new Error('options is invalid');
  5881. var tolerance = options.tolerance !== undefined ? options.tolerance : 1;
  5882. var highQuality = options.highQuality || false;
  5883. var mutate = options.mutate || false;
  5884. if (!geojson) throw new Error('geojson is required');
  5885. if (tolerance && tolerance < 0) throw new Error('invalid tolerance');
  5886. // Clone geojson to avoid side effects
  5887. if (mutate !== true) geojson = clone(geojson);
  5888. geomEach(geojson, function (geom) {
  5889. simplifyGeom(geom, tolerance, highQuality);
  5890. });
  5891. return geojson;
  5892. }
  5893. /**
  5894. * Simplifies a feature's coordinates
  5895. *
  5896. * @private
  5897. * @param {Geometry} geometry to be simplified
  5898. * @param {number} [tolerance=1] simplification tolerance
  5899. * @param {boolean} [highQuality=false] whether or not to spend more time to create a higher-quality simplification with a different algorithm
  5900. * @returns {Geometry} output
  5901. */
  5902. function simplifyGeom(geometry$$1, tolerance, highQuality) {
  5903. var type = geometry$$1.type;
  5904. // "unsimplyfiable" geometry types
  5905. if (type === 'Point' || type === 'MultiPoint') return geometry$$1;
  5906. // Remove any extra coordinates
  5907. cleanCoords(geometry$$1, true);
  5908. var coordinates = geometry$$1.coordinates;
  5909. switch (type) {
  5910. case 'LineString':
  5911. geometry$$1['coordinates'] = simplifyLine(coordinates, tolerance, highQuality);
  5912. break;
  5913. case 'MultiLineString':
  5914. geometry$$1['coordinates'] = coordinates.map(function (lines) {
  5915. return simplifyLine(lines, tolerance, highQuality);
  5916. });
  5917. break;
  5918. case 'Polygon':
  5919. geometry$$1['coordinates'] = simplifyPolygon(coordinates, tolerance, highQuality);
  5920. break;
  5921. case 'MultiPolygon':
  5922. geometry$$1['coordinates'] = coordinates.map(function (rings) {
  5923. return simplifyPolygon(rings, tolerance, highQuality);
  5924. });
  5925. }
  5926. return geometry$$1;
  5927. }
  5928. /**
  5929. * Simplifies the coordinates of a LineString with simplify-js
  5930. *
  5931. * @private
  5932. * @param {Array<number>} coordinates to be processed
  5933. * @param {number} tolerance simplification tolerance
  5934. * @param {boolean} highQuality whether or not to spend more time to create a higher-quality
  5935. * @returns {Array<Array<number>>} simplified coords
  5936. */
  5937. function simplifyLine(coordinates, tolerance, highQuality) {
  5938. return simplify$2(coordinates.map(function (coord) {
  5939. return {x: coord[0], y: coord[1], z: coord[2]};
  5940. }), tolerance, highQuality).map(function (coords) {
  5941. return (coords.z) ? [coords.x, coords.y, coords.z] : [coords.x, coords.y];
  5942. });
  5943. }
  5944. /**
  5945. * Simplifies the coordinates of a Polygon with simplify-js
  5946. *
  5947. * @private
  5948. * @param {Array<number>} coordinates to be processed
  5949. * @param {number} tolerance simplification tolerance
  5950. * @param {boolean} highQuality whether or not to spend more time to create a higher-quality
  5951. * @returns {Array<Array<Array<number>>>} simplified coords
  5952. */
  5953. function simplifyPolygon(coordinates, tolerance, highQuality) {
  5954. return coordinates.map(function (ring) {
  5955. var pts = ring.map(function (coord) {
  5956. return {x: coord[0], y: coord[1]};
  5957. });
  5958. if (pts.length < 4) {
  5959. throw new Error('invalid polygon');
  5960. }
  5961. var simpleRing = simplify$2(pts, tolerance, highQuality).map(function (coords) {
  5962. return [coords.x, coords.y];
  5963. });
  5964. //remove 1 percent of tolerance until enough points to make a triangle
  5965. while (!checkValidity(simpleRing)) {
  5966. tolerance -= tolerance * 0.01;
  5967. simpleRing = simplify$2(pts, tolerance, highQuality).map(function (coords) {
  5968. return [coords.x, coords.y];
  5969. });
  5970. }
  5971. if (
  5972. (simpleRing[simpleRing.length - 1][0] !== simpleRing[0][0]) ||
  5973. (simpleRing[simpleRing.length - 1][1] !== simpleRing[0][1])) {
  5974. simpleRing.push(simpleRing[0]);
  5975. }
  5976. return simpleRing;
  5977. });
  5978. }
  5979. /**
  5980. * Returns true if ring has at least 3 coordinates and its first coordinate is the same as its last
  5981. *
  5982. * @private
  5983. * @param {Array<number>} ring coordinates to be checked
  5984. * @returns {boolean} true if valid
  5985. */
  5986. function checkValidity(ring) {
  5987. if (ring.length < 3) return false;
  5988. //if the last point is the same as the first, it's not a triangle
  5989. return !(ring.length === 3 && ((ring[2][0] === ring[0][0]) && (ring[2][1] === ring[0][1])));
  5990. }
  5991. /* eslint-disable */
  5992. /**
  5993. * BezierSpline
  5994. * https://github.com/leszekr/bezier-spline-js
  5995. *
  5996. * @private
  5997. * @copyright
  5998. * Copyright (c) 2013 Leszek Rybicki
  5999. *
  6000. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6001. * of this software and associated documentation files (the "Software"), to deal
  6002. * in the Software without restriction, including without limitation the rights
  6003. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  6004. * copies of the Software, and to permit persons to whom the Software is
  6005. * furnished to do so, subject to the following conditions:
  6006. *
  6007. * The above copyright notice and this permission notice shall be included in all
  6008. * copies or substantial portions of the Software.
  6009. *
  6010. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  6011. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  6012. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  6013. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  6014. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  6015. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  6016. * SOFTWARE.
  6017. */
  6018. var Spline = function (options) {
  6019. this.points = options.points || [];
  6020. this.duration = options.duration || 10000;
  6021. this.sharpness = options.sharpness || 0.85;
  6022. this.centers = [];
  6023. this.controls = [];
  6024. this.stepLength = options.stepLength || 60;
  6025. this.length = this.points.length;
  6026. this.delay = 0;
  6027. // this is to ensure compatibility with the 2d version
  6028. for (var i = 0; i < this.length; i++) this.points[i].z = this.points[i].z || 0;
  6029. for (var i = 0; i < this.length - 1; i++) {
  6030. var p1 = this.points[i];
  6031. var p2 = this.points[i + 1];
  6032. this.centers.push({
  6033. x: (p1.x + p2.x) / 2,
  6034. y: (p1.y + p2.y) / 2,
  6035. z: (p1.z + p2.z) / 2
  6036. });
  6037. }
  6038. this.controls.push([this.points[0], this.points[0]]);
  6039. for (var i = 0; i < this.centers.length - 1; i++) {
  6040. var p1 = this.centers[i];
  6041. var p2 = this.centers[i + 1];
  6042. var dx = this.points[i + 1].x - (this.centers[i].x + this.centers[i + 1].x) / 2;
  6043. var dy = this.points[i + 1].y - (this.centers[i].y + this.centers[i + 1].y) / 2;
  6044. var dz = this.points[i + 1].z - (this.centers[i].y + this.centers[i + 1].z) / 2;
  6045. this.controls.push([{
  6046. x: (1.0 - this.sharpness) * this.points[i + 1].x + this.sharpness * (this.centers[i].x + dx),
  6047. y: (1.0 - this.sharpness) * this.points[i + 1].y + this.sharpness * (this.centers[i].y + dy),
  6048. z: (1.0 - this.sharpness) * this.points[i + 1].z + this.sharpness * (this.centers[i].z + dz)},
  6049. {
  6050. x: (1.0 - this.sharpness) * this.points[i + 1].x + this.sharpness * (this.centers[i + 1].x + dx),
  6051. y: (1.0 - this.sharpness) * this.points[i + 1].y + this.sharpness * (this.centers[i + 1].y + dy),
  6052. z: (1.0 - this.sharpness) * this.points[i + 1].z + this.sharpness * (this.centers[i + 1].z + dz)}]);
  6053. }
  6054. this.controls.push([this.points[this.length - 1], this.points[this.length - 1]]);
  6055. this.steps = this.cacheSteps(this.stepLength);
  6056. return this;
  6057. };
  6058. /*
  6059. Caches an array of equidistant (more or less) points on the curve.
  6060. */
  6061. Spline.prototype.cacheSteps = function (mindist) {
  6062. var steps = [];
  6063. var laststep = this.pos(0);
  6064. steps.push(0);
  6065. for (var t = 0; t < this.duration; t += 10) {
  6066. var step = this.pos(t);
  6067. var dist = Math.sqrt((step.x - laststep.x) * (step.x - laststep.x) + (step.y - laststep.y) * (step.y - laststep.y) + (step.z - laststep.z) * (step.z - laststep.z));
  6068. if (dist > mindist) {
  6069. steps.push(t);
  6070. laststep = step;
  6071. }
  6072. }
  6073. return steps;
  6074. };
  6075. /*
  6076. returns angle and speed in the given point in the curve
  6077. */
  6078. Spline.prototype.vector = function (t) {
  6079. var p1 = this.pos(t + 10);
  6080. var p2 = this.pos(t - 10);
  6081. return {
  6082. angle:180 * Math.atan2(p1.y - p2.y, p1.x - p2.x) / 3.14,
  6083. speed:Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y) + (p2.z - p1.z) * (p2.z - p1.z))
  6084. };
  6085. };
  6086. /*
  6087. Gets the position of the point, given time.
  6088. WARNING: The speed is not constant. The time it takes between control points is constant.
  6089. For constant speed, use Spline.steps[i];
  6090. */
  6091. Spline.prototype.pos = function (time) {
  6092. function bezier(t, p1, c1, c2, p2) {
  6093. var B = function (t) {
  6094. var t2 = t * t, t3 = t2 * t;
  6095. return [(t3), (3 * t2 * (1 - t)), (3 * t * (1 - t) * (1 - t)), ((1 - t) * (1 - t) * (1 - t))];
  6096. };
  6097. var b = B(t);
  6098. var pos = {
  6099. x : p2.x * b[0] + c2.x * b[1] + c1.x * b[2] + p1.x * b[3],
  6100. y : p2.y * b[0] + c2.y * b[1] + c1.y * b[2] + p1.y * b[3],
  6101. z : p2.z * b[0] + c2.z * b[1] + c1.z * b[2] + p1.z * b[3]
  6102. };
  6103. return pos;
  6104. }
  6105. var t = time - this.delay;
  6106. if (t < 0) t = 0;
  6107. if (t > this.duration) t = this.duration - 1;
  6108. //t = t-this.delay;
  6109. var t2 = (t) / this.duration;
  6110. if (t2 >= 1) return this.points[this.length - 1];
  6111. var n = Math.floor((this.points.length - 1) * t2);
  6112. var t1 = (this.length - 1) * t2 - n;
  6113. return bezier(t1, this.points[n], this.controls[n][1], this.controls[n + 1][0], this.points[n + 1]);
  6114. };
  6115. /**
  6116. * Takes a {@link LineString|line} and returns a curved version
  6117. * by applying a [Bezier spline](http://en.wikipedia.org/wiki/B%C3%A9zier_spline)
  6118. * algorithm.
  6119. *
  6120. * The bezier spline implementation is by [Leszek Rybicki](http://leszek.rybicki.cc/).
  6121. *
  6122. * @name bezierSpline
  6123. * @param {Feature<LineString>} line input LineString
  6124. * @param {Object} [options={}] Optional parameters
  6125. * @param {number} [options.resolution=10000] time in milliseconds between points
  6126. * @param {number} [options.sharpness=0.85] a measure of how curvy the path should be between splines
  6127. * @returns {Feature<LineString>} curved line
  6128. * @example
  6129. * var line = turf.lineString([
  6130. * [-76.091308, 18.427501],
  6131. * [-76.695556, 18.729501],
  6132. * [-76.552734, 19.40443],
  6133. * [-74.61914, 19.134789],
  6134. * [-73.652343, 20.07657],
  6135. * [-73.157958, 20.210656]
  6136. * ]);
  6137. *
  6138. * var curved = turf.bezierSpline(line);
  6139. *
  6140. * //addToMap
  6141. * var addToMap = [line, curved]
  6142. * curved.properties = { stroke: '#0F0' };
  6143. */
  6144. function bezier(line, options) {
  6145. // Optional params
  6146. options = options || {};
  6147. if (!isObject(options)) throw new Error('options is invalid');
  6148. var resolution = options.resolution || 10000;
  6149. var sharpness = options.sharpness || 0.85;
  6150. // validation
  6151. if (!line) throw new Error('line is required');
  6152. if (!isNumber(resolution)) throw new Error('resolution must be an number');
  6153. if (!isNumber(sharpness)) throw new Error('sharpness must be an number');
  6154. var coords = [];
  6155. var spline = new Spline({
  6156. points: getGeom(line).coordinates.map(function (pt) {
  6157. return {x: pt[0], y: pt[1]};
  6158. }),
  6159. duration: resolution,
  6160. sharpness: sharpness
  6161. });
  6162. for (var i = 0; i < spline.duration; i += 10) {
  6163. var pos = spline.pos(i);
  6164. if (Math.floor(i / 100) % 2 === 0) {
  6165. coords.push([pos.x, pos.y]);
  6166. }
  6167. }
  6168. return lineString(coords, line.properties);
  6169. }
  6170. /**
  6171. * Takes a set of {@link Point|points} and a set of {@link Polygon|polygons} and performs a spatial join.
  6172. *
  6173. * @name tag
  6174. * @param {FeatureCollection<Point>} points input points
  6175. * @param {FeatureCollection<Polygon>} polygons input polygons
  6176. * @param {string} field property in `polygons` to add to joined {<Point>} features
  6177. * @param {string} outField property in `points` in which to store joined property from `polygons`
  6178. * @returns {FeatureCollection<Point>} points with `containingPolyId` property containing values from `polyId`
  6179. * @example
  6180. * var pt1 = turf.point([-77, 44]);
  6181. * var pt2 = turf.point([-77, 38]);
  6182. * var poly1 = turf.polygon([[
  6183. * [-81, 41],
  6184. * [-81, 47],
  6185. * [-72, 47],
  6186. * [-72, 41],
  6187. * [-81, 41]
  6188. * ]], {pop: 3000});
  6189. * var poly2 = turf.polygon([[
  6190. * [-81, 35],
  6191. * [-81, 41],
  6192. * [-72, 41],
  6193. * [-72, 35],
  6194. * [-81, 35]
  6195. * ]], {pop: 1000});
  6196. *
  6197. * var points = turf.featureCollection([pt1, pt2]);
  6198. * var polygons = turf.featureCollection([poly1, poly2]);
  6199. *
  6200. * var tagged = turf.tag(points, polygons, 'pop', 'population');
  6201. *
  6202. * //addToMap
  6203. * var addToMap = [tagged, polygons]
  6204. */
  6205. function tag(points, polygons, field, outField) {
  6206. // prevent mutations
  6207. points = clone(points);
  6208. polygons = clone(polygons);
  6209. featureEach(points, function (pt) {
  6210. if (!pt.properties) pt.properties = {};
  6211. featureEach(polygons, function (poly) {
  6212. if (pt.properties[outField] === undefined) {
  6213. if (booleanPointInPolygon(pt, poly)) pt.properties[outField] = poly.properties[field];
  6214. }
  6215. });
  6216. });
  6217. return points;
  6218. }
  6219. // http://stackoverflow.com/questions/11935175/sampling-a-random-subset-from-an-array
  6220. /**
  6221. * Takes a {@link FeatureCollection} and returns a FeatureCollection with given number of {@link Feature|features} at random.
  6222. *
  6223. * @name sample
  6224. * @param {FeatureCollection} featurecollection set of input features
  6225. * @param {number} num number of features to select
  6226. * @returns {FeatureCollection} a FeatureCollection with `n` features
  6227. * @example
  6228. * var points = turf.randomPoint(100, {bbox: [-80, 30, -60, 60]});
  6229. *
  6230. * var sample = turf.sample(points, 5);
  6231. *
  6232. * //addToMap
  6233. * var addToMap = [points, sample]
  6234. * turf.featureEach(sample, function (currentFeature) {
  6235. * currentFeature.properties['marker-size'] = 'large';
  6236. * currentFeature.properties['marker-color'] = '#000';
  6237. * });
  6238. */
  6239. function sample(featurecollection, num) {
  6240. if (!featurecollection) throw new Error('featurecollection is required');
  6241. if (num === null || num === undefined) throw new Error('num is required');
  6242. if (typeof num !== 'number') throw new Error('num must be a number');
  6243. var outFC = featureCollection(getRandomSubarray(featurecollection.features, num));
  6244. return outFC;
  6245. }
  6246. function getRandomSubarray(arr, size) {
  6247. var shuffled = arr.slice(0), i = arr.length, min = i - size, temp, index;
  6248. while (i-- > min) {
  6249. index = Math.floor((i + 1) * Math.random());
  6250. temp = shuffled[index];
  6251. shuffled[index] = shuffled[i];
  6252. shuffled[i] = temp;
  6253. }
  6254. return shuffled.slice(min);
  6255. }
  6256. /**
  6257. * Takes a bbox and returns an equivalent {@link Polygon|polygon}.
  6258. *
  6259. * @name bboxPolygon
  6260. * @param {BBox} bbox extent in [minX, minY, maxX, maxY] order
  6261. * @returns {Feature<Polygon>} a Polygon representation of the bounding box
  6262. * @example
  6263. * var bbox = [0, 0, 10, 10];
  6264. *
  6265. * var poly = turf.bboxPolygon(bbox);
  6266. *
  6267. * //addToMap
  6268. * var addToMap = [poly]
  6269. */
  6270. function bboxPolygon(bbox) {
  6271. validateBBox(bbox);
  6272. // Convert BBox positions to Numbers
  6273. // No performance loss for including Number()
  6274. // https://github.com/Turfjs/turf/issues/1119
  6275. var west = Number(bbox[0]);
  6276. var south = Number(bbox[1]);
  6277. var east = Number(bbox[2]);
  6278. var north = Number(bbox[3]);
  6279. if (bbox.length === 6) throw new Error('@turf/bbox-polygon does not support BBox with 6 positions');
  6280. var lowLeft = [west, south];
  6281. var topLeft = [west, north];
  6282. var topRight = [east, north];
  6283. var lowRight = [east, south];
  6284. return polygon([[
  6285. lowLeft,
  6286. lowRight,
  6287. topRight,
  6288. topLeft,
  6289. lowLeft
  6290. ]]);
  6291. }
  6292. /**
  6293. * Takes any number of features and returns a rectangular {@link Polygon} that encompasses all vertices.
  6294. *
  6295. * @name envelope
  6296. * @param {GeoJSON} geojson input features
  6297. * @returns {Feature<Polygon>} a rectangular Polygon feature that encompasses all vertices
  6298. * @example
  6299. * var features = turf.featureCollection([
  6300. * turf.point([-75.343, 39.984], {"name": "Location A"}),
  6301. * turf.point([-75.833, 39.284], {"name": "Location B"}),
  6302. * turf.point([-75.534, 39.123], {"name": "Location C"})
  6303. * ]);
  6304. *
  6305. * var enveloped = turf.envelope(features);
  6306. *
  6307. * //addToMap
  6308. * var addToMap = [features, enveloped];
  6309. */
  6310. function envelope(geojson) {
  6311. return bboxPolygon(bbox(geojson));
  6312. }
  6313. /**
  6314. * Takes a bounding box and calculates the minimum square bounding box that
  6315. * would contain the input.
  6316. *
  6317. * @name square
  6318. * @param {BBox} bbox extent in [west, south, east, north] order
  6319. * @returns {BBox} a square surrounding `bbox`
  6320. * @example
  6321. * var bbox = [-20, -20, -15, 0];
  6322. * var squared = turf.square(bbox);
  6323. *
  6324. * //addToMap
  6325. * var addToMap = [turf.bboxPolygon(bbox), turf.bboxPolygon(squared)]
  6326. */
  6327. function square(bbox) {
  6328. var west = bbox[0];
  6329. var south = bbox[1];
  6330. var east = bbox[2];
  6331. var north = bbox[3];
  6332. var horizontalDistance = distance(bbox.slice(0, 2), [east, south]);
  6333. var verticalDistance = distance(bbox.slice(0, 2), [west, north]);
  6334. if (horizontalDistance >= verticalDistance) {
  6335. var verticalMidpoint = (south + north) / 2;
  6336. return [
  6337. west,
  6338. verticalMidpoint - ((east - west) / 2),
  6339. east,
  6340. verticalMidpoint + ((east - west) / 2)
  6341. ];
  6342. } else {
  6343. var horizontalMidpoint = (west + east) / 2;
  6344. return [
  6345. horizontalMidpoint - ((north - south) / 2),
  6346. south,
  6347. horizontalMidpoint + ((north - south) / 2),
  6348. north
  6349. ];
  6350. }
  6351. }
  6352. //http://en.wikipedia.org/wiki/Haversine_formula
  6353. //http://www.movable-type.co.uk/scripts/latlong.html
  6354. /**
  6355. * Takes a {@link Point} and calculates the location of a destination point given a distance in degrees, radians, miles, or kilometers; and bearing in degrees. This uses the [Haversine formula](http://en.wikipedia.org/wiki/Haversine_formula) to account for global curvature.
  6356. *
  6357. * @name destination
  6358. * @param {Coord} origin starting point
  6359. * @param {number} distance distance from the origin point
  6360. * @param {number} bearing ranging from -180 to 180
  6361. * @param {Object} [options={}] Optional parameters
  6362. * @param {string} [options.units='kilometers'] miles, kilometers, degrees, or radians
  6363. * @param {Object} [options.properties={}] Translate properties to Point
  6364. * @returns {Feature<Point>} destination point
  6365. * @example
  6366. * var point = turf.point([-75.343, 39.984]);
  6367. * var distance = 50;
  6368. * var bearing = 90;
  6369. * var options = {units: 'miles'};
  6370. *
  6371. * var destination = turf.destination(point, distance, bearing, options);
  6372. *
  6373. * //addToMap
  6374. * var addToMap = [point, destination]
  6375. * destination.properties['marker-color'] = '#f00';
  6376. * point.properties['marker-color'] = '#0f0';
  6377. */
  6378. function destination(origin, distance, bearing, options) {
  6379. // Optional parameters
  6380. options = options || {};
  6381. if (!isObject(options)) throw new Error('options is invalid');
  6382. var units = options.units;
  6383. var properties = options.properties;
  6384. // Handle input
  6385. var coordinates1 = getCoord(origin);
  6386. var longitude1 = degreesToRadians(coordinates1[0]);
  6387. var latitude1 = degreesToRadians(coordinates1[1]);
  6388. var bearing_rad = degreesToRadians(bearing);
  6389. var radians = lengthToRadians(distance, units);
  6390. // Main
  6391. var latitude2 = Math.asin(Math.sin(latitude1) * Math.cos(radians) +
  6392. Math.cos(latitude1) * Math.sin(radians) * Math.cos(bearing_rad));
  6393. var longitude2 = longitude1 + Math.atan2(Math.sin(bearing_rad) * Math.sin(radians) * Math.cos(latitude1),
  6394. Math.cos(radians) - Math.sin(latitude1) * Math.sin(latitude2));
  6395. var lng = radiansToDegrees(longitude2);
  6396. var lat = radiansToDegrees(latitude2);
  6397. return point([lng, lat], properties);
  6398. }
  6399. /**
  6400. * Takes a {@link Point} and calculates the circle polygon given a radius in degrees, radians, miles, or kilometers; and steps for precision.
  6401. *
  6402. * @name circle
  6403. * @param {Feature<Point>|number[]} center center point
  6404. * @param {number} radius radius of the circle
  6405. * @param {Object} [options={}] Optional parameters
  6406. * @param {number} [options.steps=64] number of steps
  6407. * @param {string} [options.units='kilometers'] miles, kilometers, degrees, or radians
  6408. * @param {Object} [options.properties={}] properties
  6409. * @returns {Feature<Polygon>} circle polygon
  6410. * @example
  6411. * var center = [-75.343, 39.984];
  6412. * var radius = 5;
  6413. * var options = {steps: 10, units: 'kilometers', properties: {foo: 'bar'}};
  6414. * var circle = turf.circle(center, radius, options);
  6415. *
  6416. * //addToMap
  6417. * var addToMap = [turf.point(center), circle]
  6418. */
  6419. function circle(center, radius, options) {
  6420. // Optional params
  6421. options = options || {};
  6422. var steps = options.steps || 64;
  6423. var properties = options.properties;
  6424. // validation
  6425. if (!center) throw new Error('center is required');
  6426. if (!radius) throw new Error('radius is required');
  6427. if (typeof options !== 'object') throw new Error('options must be an object');
  6428. if (typeof steps !== 'number') throw new Error('steps must be a number');
  6429. // default params
  6430. steps = steps || 64;
  6431. properties = properties || center.properties || {};
  6432. var coordinates = [];
  6433. for (var i = 0; i < steps; i++) {
  6434. coordinates.push(destination(center, radius, i * -360 / steps, options).geometry.coordinates);
  6435. }
  6436. coordinates.push(coordinates[0]);
  6437. return polygon([coordinates], properties);
  6438. }
  6439. //http://en.wikipedia.org/wiki/Haversine_formula
  6440. //http://www.movable-type.co.uk/scripts/latlong.html
  6441. /**
  6442. * Takes two {@link Point|points} and finds the geographic bearing between them,
  6443. * i.e. the angle measured in degrees from the north line (0 degrees)
  6444. *
  6445. * @name bearing
  6446. * @param {Coord} start starting Point
  6447. * @param {Coord} end ending Point
  6448. * @param {Object} [options={}] Optional parameters
  6449. * @param {boolean} [options.final=false] calculates the final bearing if true
  6450. * @returns {number} bearing in decimal degrees, between -180 and 180 degrees (positive clockwise)
  6451. * @example
  6452. * var point1 = turf.point([-75.343, 39.984]);
  6453. * var point2 = turf.point([-75.534, 39.123]);
  6454. *
  6455. * var bearing = turf.bearing(point1, point2);
  6456. *
  6457. * //addToMap
  6458. * var addToMap = [point1, point2]
  6459. * point1.properties['marker-color'] = '#f00'
  6460. * point2.properties['marker-color'] = '#0f0'
  6461. * point1.properties.bearing = bearing
  6462. */
  6463. function bearing(start, end, options) {
  6464. // Optional parameters
  6465. options = options || {};
  6466. if (!isObject(options)) throw new Error('options is invalid');
  6467. var final = options.final;
  6468. // Reverse calculation
  6469. if (final === true) return calculateFinalBearing(start, end);
  6470. var coordinates1 = getCoord(start);
  6471. var coordinates2 = getCoord(end);
  6472. var lon1 = degreesToRadians(coordinates1[0]);
  6473. var lon2 = degreesToRadians(coordinates2[0]);
  6474. var lat1 = degreesToRadians(coordinates1[1]);
  6475. var lat2 = degreesToRadians(coordinates2[1]);
  6476. var a = Math.sin(lon2 - lon1) * Math.cos(lat2);
  6477. var b = Math.cos(lat1) * Math.sin(lat2) -
  6478. Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1);
  6479. return radiansToDegrees(Math.atan2(a, b));
  6480. }
  6481. /**
  6482. * Calculates Final Bearing
  6483. *
  6484. * @private
  6485. * @param {Coord} start starting Point
  6486. * @param {Coord} end ending Point
  6487. * @returns {number} bearing
  6488. */
  6489. function calculateFinalBearing(start, end) {
  6490. // Swap start & end
  6491. var bear = bearing(end, start);
  6492. bear = (bear + 180) % 360;
  6493. return bear;
  6494. }
  6495. /**
  6496. * Takes two {@link Point|points} and returns a point midway between them.
  6497. * The midpoint is calculated geodesically, meaning the curvature of the earth is taken into account.
  6498. *
  6499. * @name midpoint
  6500. * @param {Coord} point1 first point
  6501. * @param {Coord} point2 second point
  6502. * @returns {Feature<Point>} a point midway between `pt1` and `pt2`
  6503. * @example
  6504. * var point1 = turf.point([144.834823, -37.771257]);
  6505. * var point2 = turf.point([145.14244, -37.830937]);
  6506. *
  6507. * var midpoint = turf.midpoint(point1, point2);
  6508. *
  6509. * //addToMap
  6510. * var addToMap = [point1, point2, midpoint];
  6511. * midpoint.properties['marker-color'] = '#f00';
  6512. */
  6513. function midpoint(point1, point2) {
  6514. var dist = distance(point1, point2);
  6515. var heading = bearing(point1, point2);
  6516. var midpoint = destination(point1, dist / 2, heading);
  6517. return midpoint;
  6518. }
  6519. /**
  6520. * Takes a {@link Feature} or {@link FeatureCollection} and returns the absolute center point of all features.
  6521. *
  6522. * @name center
  6523. * @param {GeoJSON} geojson GeoJSON to be centered
  6524. * @param {Object} [options={}] Optional parameters
  6525. * @param {Object} [options.properties={}] an Object that is used as the {@link Feature}'s properties
  6526. * @returns {Feature<Point>} a Point feature at the absolute center point of all input features
  6527. * @example
  6528. * var features = turf.featureCollection([
  6529. * turf.point( [-97.522259, 35.4691]),
  6530. * turf.point( [-97.502754, 35.463455]),
  6531. * turf.point( [-97.508269, 35.463245])
  6532. * ]);
  6533. *
  6534. * var center = turf.center(features);
  6535. *
  6536. * //addToMap
  6537. * var addToMap = [features, center]
  6538. * center.properties['marker-size'] = 'large';
  6539. * center.properties['marker-color'] = '#000';
  6540. */
  6541. function center(geojson, options) {
  6542. // Optional parameters
  6543. options = options || {};
  6544. if (!isObject(options)) throw new Error('options is invalid');
  6545. var properties = options.properties;
  6546. // Input validation
  6547. if (!geojson) throw new Error('geojson is required');
  6548. var ext = bbox(geojson);
  6549. var x = (ext[0] + ext[2]) / 2;
  6550. var y = (ext[1] + ext[3]) / 2;
  6551. return point([x, y], properties);
  6552. }
  6553. /**
  6554. * Takes one or more features and calculates the centroid using the mean of all vertices.
  6555. * This lessens the effect of small islands and artifacts when calculating the centroid of a set of polygons.
  6556. *
  6557. * @name centroid
  6558. * @param {GeoJSON} geojson GeoJSON to be centered
  6559. * @param {Object} [properties={}] an Object that is used as the {@link Feature}'s properties
  6560. * @returns {Feature<Point>} the centroid of the input features
  6561. * @example
  6562. * var polygon = turf.polygon([[[-81, 41], [-88, 36], [-84, 31], [-80, 33], [-77, 39], [-81, 41]]]);
  6563. *
  6564. * var centroid = turf.centroid(polygon);
  6565. *
  6566. * //addToMap
  6567. * var addToMap = [polygon, centroid]
  6568. */
  6569. function centroid(geojson, properties) {
  6570. var xSum = 0;
  6571. var ySum = 0;
  6572. var len = 0;
  6573. coordEach(geojson, function (coord) {
  6574. xSum += coord[0];
  6575. ySum += coord[1];
  6576. len++;
  6577. }, true);
  6578. return point([xSum / len, ySum / len], properties);
  6579. }
  6580. /**
  6581. * Takes any {@link Feature} or a {@link FeatureCollection} and returns its [center of mass](https://en.wikipedia.org/wiki/Center_of_mass) using this formula: [Centroid of Polygon](https://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon).
  6582. *
  6583. * @name centerOfMass
  6584. * @param {GeoJSON} geojson GeoJSON to be centered
  6585. * @param {Object} [properties={}] an Object that is used as the {@link Feature}'s properties
  6586. * @returns {Feature<Point>} the center of mass
  6587. * @example
  6588. * var polygon = turf.polygon([[[-81, 41], [-88, 36], [-84, 31], [-80, 33], [-77, 39], [-81, 41]]]);
  6589. *
  6590. * var center = turf.centerOfMass(polygon);
  6591. *
  6592. * //addToMap
  6593. * var addToMap = [polygon, center]
  6594. */
  6595. function centerOfMass(geojson, properties) {
  6596. switch (getType(geojson)) {
  6597. case 'Point':
  6598. return geojson;
  6599. case 'Polygon':
  6600. var coords = [];
  6601. coordEach(geojson, function (coord) {
  6602. coords.push(coord);
  6603. });
  6604. // First, we neutralize the feature (set it around coordinates [0,0]) to prevent rounding errors
  6605. // We take any point to translate all the points around 0
  6606. var centre = centroid(geojson, properties);
  6607. var translation = centre.geometry.coordinates;
  6608. var sx = 0;
  6609. var sy = 0;
  6610. var sArea = 0;
  6611. var i, pi, pj, xi, xj, yi, yj, a;
  6612. var neutralizedPoints = coords.map(function (point$$1) {
  6613. return [
  6614. point$$1[0] - translation[0],
  6615. point$$1[1] - translation[1]
  6616. ];
  6617. });
  6618. for (i = 0; i < coords.length - 1; i++) {
  6619. // pi is the current point
  6620. pi = neutralizedPoints[i];
  6621. xi = pi[0];
  6622. yi = pi[1];
  6623. // pj is the next point (pi+1)
  6624. pj = neutralizedPoints[i + 1];
  6625. xj = pj[0];
  6626. yj = pj[1];
  6627. // a is the common factor to compute the signed area and the final coordinates
  6628. a = xi * yj - xj * yi;
  6629. // sArea is the sum used to compute the signed area
  6630. sArea += a;
  6631. // sx and sy are the sums used to compute the final coordinates
  6632. sx += (xi + xj) * a;
  6633. sy += (yi + yj) * a;
  6634. }
  6635. // Shape has no area: fallback on turf.centroid
  6636. if (sArea === 0) {
  6637. return centre;
  6638. } else {
  6639. // Compute the signed area, and factorize 1/6A
  6640. var area = sArea * 0.5;
  6641. var areaFactor = 1 / (6 * area);
  6642. // Compute the final coordinates, adding back the values that have been neutralized
  6643. return point([
  6644. translation[0] + areaFactor * sx,
  6645. translation[1] + areaFactor * sy
  6646. ], properties);
  6647. }
  6648. default:
  6649. // Not a polygon: Compute the convex hull and work with that
  6650. var hull = convex(geojson);
  6651. if (hull) return centerOfMass(hull, properties);
  6652. // Hull is empty: fallback on the centroid
  6653. else return centroid(geojson, properties);
  6654. }
  6655. }
  6656. /**
  6657. * Combines a {@link FeatureCollection} of {@link Point}, {@link LineString}, or {@link Polygon} features
  6658. * into {@link MultiPoint}, {@link MultiLineString}, or {@link MultiPolygon} features.
  6659. *
  6660. * @name combine
  6661. * @param {FeatureCollection<Point|LineString|Polygon>} fc a FeatureCollection of any type
  6662. * @returns {FeatureCollection<MultiPoint|MultiLineString|MultiPolygon>} a FeatureCollection of corresponding type to input
  6663. * @example
  6664. * var fc = turf.featureCollection([
  6665. * turf.point([19.026432, 47.49134]),
  6666. * turf.point([19.074497, 47.509548])
  6667. * ]);
  6668. *
  6669. * var combined = turf.combine(fc);
  6670. *
  6671. * //addToMap
  6672. * var addToMap = [combined]
  6673. */
  6674. function combine(fc) {
  6675. var groups = {
  6676. MultiPoint: {coordinates: [], properties: []},
  6677. MultiLineString: {coordinates: [], properties: []},
  6678. MultiPolygon: {coordinates: [], properties: []}
  6679. };
  6680. var multiMapping = Object.keys(groups).reduce(function (memo, item) {
  6681. memo[item.replace('Multi', '')] = item;
  6682. return memo;
  6683. }, {});
  6684. function addToGroup(feature$$1, key, multi) {
  6685. if (!multi) {
  6686. groups[key].coordinates.push(feature$$1.geometry.coordinates);
  6687. } else {
  6688. groups[key].coordinates = groups[key].coordinates.concat(feature$$1.geometry.coordinates);
  6689. }
  6690. groups[key].properties.push(feature$$1.properties);
  6691. }
  6692. featureEach(fc, function (feature$$1) {
  6693. if (!feature$$1.geometry) return;
  6694. if (groups[feature$$1.geometry.type]) {
  6695. addToGroup(feature$$1, feature$$1.geometry.type, true);
  6696. } else if (multiMapping[feature$$1.geometry.type]) {
  6697. addToGroup(feature$$1, multiMapping[feature$$1.geometry.type], false);
  6698. }
  6699. });
  6700. return featureCollection(Object.keys(groups)
  6701. .filter(function (key) {
  6702. return groups[key].coordinates.length;
  6703. })
  6704. .sort()
  6705. .map(function (key) {
  6706. var geometry$$1 = { type: key, coordinates: groups[key].coordinates };
  6707. var properties = { collectedProperties: groups[key].properties };
  6708. return feature(geometry$$1, properties);
  6709. }));
  6710. }
  6711. /**
  6712. * Takes a feature or set of features and returns all positions as {@link Point|points}.
  6713. *
  6714. * @name explode
  6715. * @param {GeoJSON} geojson input features
  6716. * @returns {FeatureCollection<point>} points representing the exploded input features
  6717. * @throws {Error} if it encounters an unknown geometry type
  6718. * @example
  6719. * var polygon = turf.polygon([[[-81, 41], [-88, 36], [-84, 31], [-80, 33], [-77, 39], [-81, 41]]]);
  6720. *
  6721. * var explode = turf.explode(polygon);
  6722. *
  6723. * //addToMap
  6724. * var addToMap = [polygon, explode]
  6725. */
  6726. function explode(geojson) {
  6727. var points$$1 = [];
  6728. if (geojson.type === 'FeatureCollection') {
  6729. featureEach(geojson, function (feature$$1) {
  6730. coordEach(feature$$1, function (coord) {
  6731. points$$1.push(point(coord, feature$$1.properties));
  6732. });
  6733. });
  6734. } else {
  6735. coordEach(geojson, function (coord) {
  6736. points$$1.push(point(coord, geojson.properties));
  6737. });
  6738. }
  6739. return featureCollection(points$$1);
  6740. }
  6741. var earcut_1 = earcut;
  6742. var default_1$2 = earcut;
  6743. function earcut(data, holeIndices, dim) {
  6744. dim = dim || 2;
  6745. var hasHoles = holeIndices && holeIndices.length,
  6746. outerLen = hasHoles ? holeIndices[0] * dim : data.length,
  6747. outerNode = linkedList(data, 0, outerLen, dim, true),
  6748. triangles = [];
  6749. if (!outerNode) return triangles;
  6750. var minX, minY, maxX, maxY, x, y, invSize;
  6751. if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
  6752. // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
  6753. if (data.length > 80 * dim) {
  6754. minX = maxX = data[0];
  6755. minY = maxY = data[1];
  6756. for (var i = dim; i < outerLen; i += dim) {
  6757. x = data[i];
  6758. y = data[i + 1];
  6759. if (x < minX) minX = x;
  6760. if (y < minY) minY = y;
  6761. if (x > maxX) maxX = x;
  6762. if (y > maxY) maxY = y;
  6763. }
  6764. // minX, minY and invSize are later used to transform coords into integers for z-order calculation
  6765. invSize = Math.max(maxX - minX, maxY - minY);
  6766. invSize = invSize !== 0 ? 1 / invSize : 0;
  6767. }
  6768. earcutLinked(outerNode, triangles, dim, minX, minY, invSize);
  6769. return triangles;
  6770. }
  6771. // create a circular doubly linked list from polygon points in the specified winding order
  6772. function linkedList(data, start, end, dim, clockwise) {
  6773. var i, last;
  6774. if (clockwise === (signedArea(data, start, end, dim) > 0)) {
  6775. for (i = start; i < end; i += dim) last = insertNode$1(i, data[i], data[i + 1], last);
  6776. } else {
  6777. for (i = end - dim; i >= start; i -= dim) last = insertNode$1(i, data[i], data[i + 1], last);
  6778. }
  6779. if (last && equals$1(last, last.next)) {
  6780. removeNode(last);
  6781. last = last.next;
  6782. }
  6783. return last;
  6784. }
  6785. // eliminate colinear or duplicate points
  6786. function filterPoints(start, end) {
  6787. if (!start) return start;
  6788. if (!end) end = start;
  6789. var p = start,
  6790. again;
  6791. do {
  6792. again = false;
  6793. if (!p.steiner && (equals$1(p, p.next) || area(p.prev, p, p.next) === 0)) {
  6794. removeNode(p);
  6795. p = end = p.prev;
  6796. if (p === p.next) break;
  6797. again = true;
  6798. } else {
  6799. p = p.next;
  6800. }
  6801. } while (again || p !== end);
  6802. return end;
  6803. }
  6804. // main ear slicing loop which triangulates a polygon (given as a linked list)
  6805. function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
  6806. if (!ear) return;
  6807. // interlink polygon nodes in z-order
  6808. if (!pass && invSize) indexCurve(ear, minX, minY, invSize);
  6809. var stop = ear,
  6810. prev, next;
  6811. // iterate through ears, slicing them one by one
  6812. while (ear.prev !== ear.next) {
  6813. prev = ear.prev;
  6814. next = ear.next;
  6815. if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
  6816. // cut off the triangle
  6817. triangles.push(prev.i / dim);
  6818. triangles.push(ear.i / dim);
  6819. triangles.push(next.i / dim);
  6820. removeNode(ear);
  6821. // skipping the next vertice leads to less sliver triangles
  6822. ear = next.next;
  6823. stop = next.next;
  6824. continue;
  6825. }
  6826. ear = next;
  6827. // if we looped through the whole remaining polygon and can't find any more ears
  6828. if (ear === stop) {
  6829. // try filtering points and slicing again
  6830. if (!pass) {
  6831. earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
  6832. // if this didn't work, try curing all small self-intersections locally
  6833. } else if (pass === 1) {
  6834. ear = cureLocalIntersections(ear, triangles, dim);
  6835. earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
  6836. // as a last resort, try splitting the remaining polygon into two
  6837. } else if (pass === 2) {
  6838. splitEarcut(ear, triangles, dim, minX, minY, invSize);
  6839. }
  6840. break;
  6841. }
  6842. }
  6843. }
  6844. // check whether a polygon node forms a valid ear with adjacent nodes
  6845. function isEar(ear) {
  6846. var a = ear.prev,
  6847. b = ear,
  6848. c = ear.next;
  6849. if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
  6850. // now make sure we don't have other points inside the potential ear
  6851. var p = ear.next.next;
  6852. while (p !== ear.prev) {
  6853. if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
  6854. area(p.prev, p, p.next) >= 0) return false;
  6855. p = p.next;
  6856. }
  6857. return true;
  6858. }
  6859. function isEarHashed(ear, minX, minY, invSize) {
  6860. var a = ear.prev,
  6861. b = ear,
  6862. c = ear.next;
  6863. if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
  6864. // triangle bbox; min & max are calculated like this for speed
  6865. var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x),
  6866. minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y),
  6867. maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x),
  6868. maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y);
  6869. // z-order range for the current triangle bbox;
  6870. var minZ = zOrder(minTX, minTY, minX, minY, invSize),
  6871. maxZ = zOrder(maxTX, maxTY, minX, minY, invSize);
  6872. // first look for points inside the triangle in increasing z-order
  6873. var p = ear.nextZ;
  6874. while (p && p.z <= maxZ) {
  6875. if (p !== ear.prev && p !== ear.next &&
  6876. pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
  6877. area(p.prev, p, p.next) >= 0) return false;
  6878. p = p.nextZ;
  6879. }
  6880. // then look for points in decreasing z-order
  6881. p = ear.prevZ;
  6882. while (p && p.z >= minZ) {
  6883. if (p !== ear.prev && p !== ear.next &&
  6884. pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
  6885. area(p.prev, p, p.next) >= 0) return false;
  6886. p = p.prevZ;
  6887. }
  6888. return true;
  6889. }
  6890. // go through all polygon nodes and cure small local self-intersections
  6891. function cureLocalIntersections(start, triangles, dim) {
  6892. var p = start;
  6893. do {
  6894. var a = p.prev,
  6895. b = p.next.next;
  6896. if (!equals$1(a, b) && intersects$2(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
  6897. triangles.push(a.i / dim);
  6898. triangles.push(p.i / dim);
  6899. triangles.push(b.i / dim);
  6900. // remove two nodes involved
  6901. removeNode(p);
  6902. removeNode(p.next);
  6903. p = start = b;
  6904. }
  6905. p = p.next;
  6906. } while (p !== start);
  6907. return p;
  6908. }
  6909. // try splitting polygon into two and triangulate them independently
  6910. function splitEarcut(start, triangles, dim, minX, minY, invSize) {
  6911. // look for a valid diagonal that divides the polygon into two
  6912. var a = start;
  6913. do {
  6914. var b = a.next.next;
  6915. while (b !== a.prev) {
  6916. if (a.i !== b.i && isValidDiagonal(a, b)) {
  6917. // split the polygon in two by the diagonal
  6918. var c = splitPolygon(a, b);
  6919. // filter colinear points around the cuts
  6920. a = filterPoints(a, a.next);
  6921. c = filterPoints(c, c.next);
  6922. // run earcut on each half
  6923. earcutLinked(a, triangles, dim, minX, minY, invSize);
  6924. earcutLinked(c, triangles, dim, minX, minY, invSize);
  6925. return;
  6926. }
  6927. b = b.next;
  6928. }
  6929. a = a.next;
  6930. } while (a !== start);
  6931. }
  6932. // link every hole into the outer loop, producing a single-ring polygon without holes
  6933. function eliminateHoles(data, holeIndices, outerNode, dim) {
  6934. var queue = [],
  6935. i, len, start, end, list;
  6936. for (i = 0, len = holeIndices.length; i < len; i++) {
  6937. start = holeIndices[i] * dim;
  6938. end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
  6939. list = linkedList(data, start, end, dim, false);
  6940. if (list === list.next) list.steiner = true;
  6941. queue.push(getLeftmost(list));
  6942. }
  6943. queue.sort(compareX);
  6944. // process holes from left to right
  6945. for (i = 0; i < queue.length; i++) {
  6946. eliminateHole(queue[i], outerNode);
  6947. outerNode = filterPoints(outerNode, outerNode.next);
  6948. }
  6949. return outerNode;
  6950. }
  6951. function compareX(a, b) {
  6952. return a.x - b.x;
  6953. }
  6954. // find a bridge between vertices that connects hole with an outer ring and and link it
  6955. function eliminateHole(hole, outerNode) {
  6956. outerNode = findHoleBridge(hole, outerNode);
  6957. if (outerNode) {
  6958. var b = splitPolygon(outerNode, hole);
  6959. filterPoints(b, b.next);
  6960. }
  6961. }
  6962. // David Eberly's algorithm for finding a bridge between hole and outer polygon
  6963. function findHoleBridge(hole, outerNode) {
  6964. var p = outerNode,
  6965. hx = hole.x,
  6966. hy = hole.y,
  6967. qx = -Infinity,
  6968. m;
  6969. // find a segment intersected by a ray from the hole's leftmost point to the left;
  6970. // segment's endpoint with lesser x will be potential connection point
  6971. do {
  6972. if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
  6973. var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
  6974. if (x <= hx && x > qx) {
  6975. qx = x;
  6976. if (x === hx) {
  6977. if (hy === p.y) return p;
  6978. if (hy === p.next.y) return p.next;
  6979. }
  6980. m = p.x < p.next.x ? p : p.next;
  6981. }
  6982. }
  6983. p = p.next;
  6984. } while (p !== outerNode);
  6985. if (!m) return null;
  6986. if (hx === qx) return m.prev; // hole touches outer segment; pick lower endpoint
  6987. // look for points inside the triangle of hole point, segment intersection and endpoint;
  6988. // if there are no points found, we have a valid connection;
  6989. // otherwise choose the point of the minimum angle with the ray as connection point
  6990. var stop = m,
  6991. mx = m.x,
  6992. my = m.y,
  6993. tanMin = Infinity,
  6994. tan;
  6995. p = m.next;
  6996. while (p !== stop) {
  6997. if (hx >= p.x && p.x >= mx && hx !== p.x &&
  6998. pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
  6999. tan = Math.abs(hy - p.y) / (hx - p.x); // tangential
  7000. if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && locallyInside(p, hole)) {
  7001. m = p;
  7002. tanMin = tan;
  7003. }
  7004. }
  7005. p = p.next;
  7006. }
  7007. return m;
  7008. }
  7009. // interlink polygon nodes in z-order
  7010. function indexCurve(start, minX, minY, invSize) {
  7011. var p = start;
  7012. do {
  7013. if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, invSize);
  7014. p.prevZ = p.prev;
  7015. p.nextZ = p.next;
  7016. p = p.next;
  7017. } while (p !== start);
  7018. p.prevZ.nextZ = null;
  7019. p.prevZ = null;
  7020. sortLinked(p);
  7021. }
  7022. // Simon Tatham's linked list merge sort algorithm
  7023. // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
  7024. function sortLinked(list) {
  7025. var i, p, q, e, tail, numMerges, pSize, qSize,
  7026. inSize = 1;
  7027. do {
  7028. p = list;
  7029. list = null;
  7030. tail = null;
  7031. numMerges = 0;
  7032. while (p) {
  7033. numMerges++;
  7034. q = p;
  7035. pSize = 0;
  7036. for (i = 0; i < inSize; i++) {
  7037. pSize++;
  7038. q = q.nextZ;
  7039. if (!q) break;
  7040. }
  7041. qSize = inSize;
  7042. while (pSize > 0 || (qSize > 0 && q)) {
  7043. if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
  7044. e = p;
  7045. p = p.nextZ;
  7046. pSize--;
  7047. } else {
  7048. e = q;
  7049. q = q.nextZ;
  7050. qSize--;
  7051. }
  7052. if (tail) tail.nextZ = e;
  7053. else list = e;
  7054. e.prevZ = tail;
  7055. tail = e;
  7056. }
  7057. p = q;
  7058. }
  7059. tail.nextZ = null;
  7060. inSize *= 2;
  7061. } while (numMerges > 1);
  7062. return list;
  7063. }
  7064. // z-order of a point given coords and inverse of the longer side of data bbox
  7065. function zOrder(x, y, minX, minY, invSize) {
  7066. // coords are transformed into non-negative 15-bit integer range
  7067. x = 32767 * (x - minX) * invSize;
  7068. y = 32767 * (y - minY) * invSize;
  7069. x = (x | (x << 8)) & 0x00FF00FF;
  7070. x = (x | (x << 4)) & 0x0F0F0F0F;
  7071. x = (x | (x << 2)) & 0x33333333;
  7072. x = (x | (x << 1)) & 0x55555555;
  7073. y = (y | (y << 8)) & 0x00FF00FF;
  7074. y = (y | (y << 4)) & 0x0F0F0F0F;
  7075. y = (y | (y << 2)) & 0x33333333;
  7076. y = (y | (y << 1)) & 0x55555555;
  7077. return x | (y << 1);
  7078. }
  7079. // find the leftmost node of a polygon ring
  7080. function getLeftmost(start) {
  7081. var p = start,
  7082. leftmost = start;
  7083. do {
  7084. if (p.x < leftmost.x) leftmost = p;
  7085. p = p.next;
  7086. } while (p !== start);
  7087. return leftmost;
  7088. }
  7089. // check if a point lies within a convex triangle
  7090. function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
  7091. return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 &&
  7092. (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 &&
  7093. (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;
  7094. }
  7095. // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
  7096. function isValidDiagonal(a, b) {
  7097. return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) &&
  7098. locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b);
  7099. }
  7100. // signed area of a triangle
  7101. function area(p, q, r) {
  7102. return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
  7103. }
  7104. // check if two points are equal
  7105. function equals$1(p1, p2) {
  7106. return p1.x === p2.x && p1.y === p2.y;
  7107. }
  7108. // check if two segments intersect
  7109. function intersects$2(p1, q1, p2, q2) {
  7110. if ((equals$1(p1, q1) && equals$1(p2, q2)) ||
  7111. (equals$1(p1, q2) && equals$1(p2, q1))) return true;
  7112. return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 &&
  7113. area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0;
  7114. }
  7115. // check if a polygon diagonal intersects any polygon segments
  7116. function intersectsPolygon(a, b) {
  7117. var p = a;
  7118. do {
  7119. if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
  7120. intersects$2(p, p.next, a, b)) return true;
  7121. p = p.next;
  7122. } while (p !== a);
  7123. return false;
  7124. }
  7125. // check if a polygon diagonal is locally inside the polygon
  7126. function locallyInside(a, b) {
  7127. return area(a.prev, a, a.next) < 0 ?
  7128. area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :
  7129. area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
  7130. }
  7131. // check if the middle point of a polygon diagonal is inside the polygon
  7132. function middleInside(a, b) {
  7133. var p = a,
  7134. inside = false,
  7135. px = (a.x + b.x) / 2,
  7136. py = (a.y + b.y) / 2;
  7137. do {
  7138. if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&
  7139. (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))
  7140. inside = !inside;
  7141. p = p.next;
  7142. } while (p !== a);
  7143. return inside;
  7144. }
  7145. // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
  7146. // if one belongs to the outer ring and another to a hole, it merges it into a single ring
  7147. function splitPolygon(a, b) {
  7148. var a2 = new Node(a.i, a.x, a.y),
  7149. b2 = new Node(b.i, b.x, b.y),
  7150. an = a.next,
  7151. bp = b.prev;
  7152. a.next = b;
  7153. b.prev = a;
  7154. a2.next = an;
  7155. an.prev = a2;
  7156. b2.next = a2;
  7157. a2.prev = b2;
  7158. bp.next = b2;
  7159. b2.prev = bp;
  7160. return b2;
  7161. }
  7162. // create a node and optionally link it with previous one (in a circular doubly linked list)
  7163. function insertNode$1(i, x, y, last) {
  7164. var p = new Node(i, x, y);
  7165. if (!last) {
  7166. p.prev = p;
  7167. p.next = p;
  7168. } else {
  7169. p.next = last.next;
  7170. p.prev = last;
  7171. last.next.prev = p;
  7172. last.next = p;
  7173. }
  7174. return p;
  7175. }
  7176. function removeNode(p) {
  7177. p.next.prev = p.prev;
  7178. p.prev.next = p.next;
  7179. if (p.prevZ) p.prevZ.nextZ = p.nextZ;
  7180. if (p.nextZ) p.nextZ.prevZ = p.prevZ;
  7181. }
  7182. function Node(i, x, y) {
  7183. // vertice index in coordinates array
  7184. this.i = i;
  7185. // vertex coordinates
  7186. this.x = x;
  7187. this.y = y;
  7188. // previous and next vertice nodes in a polygon ring
  7189. this.prev = null;
  7190. this.next = null;
  7191. // z-order curve value
  7192. this.z = null;
  7193. // previous and next nodes in z-order
  7194. this.prevZ = null;
  7195. this.nextZ = null;
  7196. // indicates whether this is a steiner point
  7197. this.steiner = false;
  7198. }
  7199. // return a percentage difference between the polygon area and its triangulation area;
  7200. // used to verify correctness of triangulation
  7201. earcut.deviation = function (data, holeIndices, dim, triangles) {
  7202. var hasHoles = holeIndices && holeIndices.length;
  7203. var outerLen = hasHoles ? holeIndices[0] * dim : data.length;
  7204. var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));
  7205. if (hasHoles) {
  7206. for (var i = 0, len = holeIndices.length; i < len; i++) {
  7207. var start = holeIndices[i] * dim;
  7208. var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
  7209. polygonArea -= Math.abs(signedArea(data, start, end, dim));
  7210. }
  7211. }
  7212. var trianglesArea = 0;
  7213. for (i = 0; i < triangles.length; i += 3) {
  7214. var a = triangles[i] * dim;
  7215. var b = triangles[i + 1] * dim;
  7216. var c = triangles[i + 2] * dim;
  7217. trianglesArea += Math.abs(
  7218. (data[a] - data[c]) * (data[b + 1] - data[a + 1]) -
  7219. (data[a] - data[b]) * (data[c + 1] - data[a + 1]));
  7220. }
  7221. return polygonArea === 0 && trianglesArea === 0 ? 0 :
  7222. Math.abs((trianglesArea - polygonArea) / polygonArea);
  7223. };
  7224. function signedArea(data, start, end, dim) {
  7225. var sum = 0;
  7226. for (var i = start, j = end - dim; i < end; i += dim) {
  7227. sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
  7228. j = i;
  7229. }
  7230. return sum;
  7231. }
  7232. // turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts
  7233. earcut.flatten = function (data) {
  7234. var dim = data[0][0].length,
  7235. result = {vertices: [], holes: [], dimensions: dim},
  7236. holeIndex = 0;
  7237. for (var i = 0; i < data.length; i++) {
  7238. for (var j = 0; j < data[i].length; j++) {
  7239. for (var d = 0; d < dim; d++) result.vertices.push(data[i][j][d]);
  7240. }
  7241. if (i > 0) {
  7242. holeIndex += data[i - 1].length;
  7243. result.holes.push(holeIndex);
  7244. }
  7245. }
  7246. return result;
  7247. };
  7248. earcut_1.default = default_1$2;
  7249. /**
  7250. * Tesselates a {@link Feature<Polygon>} into a {@link FeatureCollection<Polygon>} of triangles
  7251. * using [earcut](https://github.com/mapbox/earcut).
  7252. *
  7253. * @name tesselate
  7254. * @param {Feature<Polygon>} poly the polygon to tesselate
  7255. * @returns {FeatureCollection<Polygon>} a geometrycollection feature
  7256. * @example
  7257. * var poly = turf.polygon([[[11, 0], [22, 4], [31, 0], [31, 11], [21, 15], [11, 11], [11, 0]]]);
  7258. * var triangles = turf.tesselate(poly);
  7259. *
  7260. * //addToMap
  7261. * var addToMap = [poly, triangles]
  7262. */
  7263. function tesselate(poly) {
  7264. if (!poly.geometry || (poly.geometry.type !== 'Polygon' && poly.geometry.type !== 'MultiPolygon')) {
  7265. throw new Error('input must be a Polygon or MultiPolygon');
  7266. }
  7267. var fc = {type: 'FeatureCollection', features: []};
  7268. if (poly.geometry.type === 'Polygon') {
  7269. fc.features = processPolygon(poly.geometry.coordinates);
  7270. } else {
  7271. poly.geometry.coordinates.forEach(function (coordinates) {
  7272. fc.features = fc.features.concat(processPolygon(coordinates));
  7273. });
  7274. }
  7275. return fc;
  7276. }
  7277. function processPolygon(coordinates) {
  7278. var data = flattenCoords(coordinates);
  7279. var dim = 2;
  7280. var result = earcut_1(data.vertices, data.holes, dim);
  7281. var features = [];
  7282. var vertices = [];
  7283. result.forEach(function (vert, i) {
  7284. var index = result[i];
  7285. vertices.push([data.vertices[index * dim], data.vertices[index * dim + 1]]);
  7286. });
  7287. for (var i = 0; i < vertices.length; i += 3) {
  7288. var coords = vertices.slice(i, i + 3);
  7289. coords.push(vertices[i]);
  7290. features.push(polygon([coords]));
  7291. }
  7292. return features;
  7293. }
  7294. function flattenCoords(data) {
  7295. var dim = data[0][0].length,
  7296. result = {vertices: [], holes: [], dimensions: dim},
  7297. holeIndex = 0;
  7298. for (var i = 0; i < data.length; i++) {
  7299. for (var j = 0; j < data[i].length; j++) {
  7300. for (var d = 0; d < dim; d++) result.vertices.push(data[i][j][d]);
  7301. }
  7302. if (i > 0) {
  7303. holeIndex += data[i - 1].length;
  7304. result.holes.push(holeIndex);
  7305. }
  7306. }
  7307. return result;
  7308. }
  7309. /**
  7310. * Takes a reference {@link Point|point} and a FeatureCollection of Features
  7311. * with Point geometries and returns the
  7312. * point from the FeatureCollection closest to the reference. This calculation
  7313. * is geodesic.
  7314. *
  7315. * @name nearestPoint
  7316. * @param {Coord} targetPoint the reference point
  7317. * @param {FeatureCollection<Point>} points against input point set
  7318. * @returns {Feature<Point>} the closest point in the set to the reference point
  7319. * @example
  7320. * var targetPoint = turf.point([28.965797, 41.010086], {"marker-color": "#0F0"});
  7321. * var points = turf.featureCollection([
  7322. * turf.point([28.973865, 41.011122]),
  7323. * turf.point([28.948459, 41.024204]),
  7324. * turf.point([28.938674, 41.013324])
  7325. * ]);
  7326. *
  7327. * var nearest = turf.nearestPoint(targetPoint, points);
  7328. *
  7329. * //addToMap
  7330. * var addToMap = [targetPoint, points, nearest];
  7331. * nearest.properties['marker-color'] = '#F00';
  7332. */
  7333. function nearestPoint(targetPoint, points) {
  7334. // Input validation
  7335. if (!targetPoint) throw new Error('targetPoint is required');
  7336. if (!points) throw new Error('points is required');
  7337. var nearest;
  7338. var minDist = Infinity;
  7339. featureEach(points, function (pt, featureIndex) {
  7340. var distanceToPoint = distance(targetPoint, pt);
  7341. if (distanceToPoint < minDist) {
  7342. nearest = clone(pt);
  7343. nearest.properties.featureIndex = featureIndex;
  7344. nearest.properties.distanceToPoint = distanceToPoint;
  7345. minDist = distanceToPoint;
  7346. }
  7347. });
  7348. return nearest;
  7349. }
  7350. function quickselect$3(arr, k, left, right, compare) {
  7351. quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare$2);
  7352. }
  7353. function quickselectStep(arr, k, left, right, compare) {
  7354. while (right > left) {
  7355. if (right - left > 600) {
  7356. var n = right - left + 1;
  7357. var m = k - left + 1;
  7358. var z = Math.log(n);
  7359. var s = 0.5 * Math.exp(2 * z / 3);
  7360. var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
  7361. var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
  7362. var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
  7363. quickselectStep(arr, k, newLeft, newRight, compare);
  7364. }
  7365. var t = arr[k];
  7366. var i = left;
  7367. var j = right;
  7368. swap$1(arr, left, k);
  7369. if (compare(arr[right], t) > 0) swap$1(arr, left, right);
  7370. while (i < j) {
  7371. swap$1(arr, i, j);
  7372. i++;
  7373. j--;
  7374. while (compare(arr[i], t) < 0) i++;
  7375. while (compare(arr[j], t) > 0) j--;
  7376. }
  7377. if (compare(arr[left], t) === 0) swap$1(arr, left, j);
  7378. else {
  7379. j++;
  7380. swap$1(arr, j, right);
  7381. }
  7382. if (j <= k) left = j + 1;
  7383. if (k <= j) right = j - 1;
  7384. }
  7385. }
  7386. function swap$1(arr, i, j) {
  7387. var tmp = arr[i];
  7388. arr[i] = arr[j];
  7389. arr[j] = tmp;
  7390. }
  7391. function defaultCompare$2(a, b) {
  7392. return a < b ? -1 : a > b ? 1 : 0;
  7393. }
  7394. function rbush$4(maxEntries, format) {
  7395. if (!(this instanceof rbush$4)) return new rbush$4(maxEntries, format);
  7396. // max entries in a node is 9 by default; min node fill is 40% for best performance
  7397. this._maxEntries = Math.max(4, maxEntries || 9);
  7398. this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
  7399. if (format) {
  7400. this._initFormat(format);
  7401. }
  7402. this.clear();
  7403. }
  7404. rbush$4.prototype = {
  7405. all: function () {
  7406. return this._all(this.data, []);
  7407. },
  7408. search: function (bbox) {
  7409. var node = this.data,
  7410. result = [],
  7411. toBBox = this.toBBox;
  7412. if (!intersects$4(bbox, node)) return result;
  7413. var nodesToSearch = [],
  7414. i, len, child, childBBox;
  7415. while (node) {
  7416. for (i = 0, len = node.children.length; i < len; i++) {
  7417. child = node.children[i];
  7418. childBBox = node.leaf ? toBBox(child) : child;
  7419. if (intersects$4(bbox, childBBox)) {
  7420. if (node.leaf) result.push(child);
  7421. else if (contains$1(bbox, childBBox)) this._all(child, result);
  7422. else nodesToSearch.push(child);
  7423. }
  7424. }
  7425. node = nodesToSearch.pop();
  7426. }
  7427. return result;
  7428. },
  7429. collides: function (bbox) {
  7430. var node = this.data,
  7431. toBBox = this.toBBox;
  7432. if (!intersects$4(bbox, node)) return false;
  7433. var nodesToSearch = [],
  7434. i, len, child, childBBox;
  7435. while (node) {
  7436. for (i = 0, len = node.children.length; i < len; i++) {
  7437. child = node.children[i];
  7438. childBBox = node.leaf ? toBBox(child) : child;
  7439. if (intersects$4(bbox, childBBox)) {
  7440. if (node.leaf || contains$1(bbox, childBBox)) return true;
  7441. nodesToSearch.push(child);
  7442. }
  7443. }
  7444. node = nodesToSearch.pop();
  7445. }
  7446. return false;
  7447. },
  7448. load: function (data) {
  7449. if (!(data && data.length)) return this;
  7450. if (data.length < this._minEntries) {
  7451. for (var i = 0, len = data.length; i < len; i++) {
  7452. this.insert(data[i]);
  7453. }
  7454. return this;
  7455. }
  7456. // recursively build the tree with the given data from scratch using OMT algorithm
  7457. var node = this._build(data.slice(), 0, data.length - 1, 0);
  7458. if (!this.data.children.length) {
  7459. // save as is if tree is empty
  7460. this.data = node;
  7461. } else if (this.data.height === node.height) {
  7462. // split root if trees have the same height
  7463. this._splitRoot(this.data, node);
  7464. } else {
  7465. if (this.data.height < node.height) {
  7466. // swap trees if inserted one is bigger
  7467. var tmpNode = this.data;
  7468. this.data = node;
  7469. node = tmpNode;
  7470. }
  7471. // insert the small tree into the large tree at appropriate level
  7472. this._insert(node, this.data.height - node.height - 1, true);
  7473. }
  7474. return this;
  7475. },
  7476. insert: function (item) {
  7477. if (item) this._insert(item, this.data.height - 1);
  7478. return this;
  7479. },
  7480. clear: function () {
  7481. this.data = createNode$1([]);
  7482. return this;
  7483. },
  7484. remove: function (item, equalsFn) {
  7485. if (!item) return this;
  7486. var node = this.data,
  7487. bbox = this.toBBox(item),
  7488. path = [],
  7489. indexes = [],
  7490. i, parent, index, goingUp;
  7491. // depth-first iterative tree traversal
  7492. while (node || path.length) {
  7493. if (!node) { // go up
  7494. node = path.pop();
  7495. parent = path[path.length - 1];
  7496. i = indexes.pop();
  7497. goingUp = true;
  7498. }
  7499. if (node.leaf) { // check current node
  7500. index = findItem$1(item, node.children, equalsFn);
  7501. if (index !== -1) {
  7502. // item found, remove the item and condense tree upwards
  7503. node.children.splice(index, 1);
  7504. path.push(node);
  7505. this._condense(path);
  7506. return this;
  7507. }
  7508. }
  7509. if (!goingUp && !node.leaf && contains$1(node, bbox)) { // go down
  7510. path.push(node);
  7511. indexes.push(i);
  7512. i = 0;
  7513. parent = node;
  7514. node = node.children[0];
  7515. } else if (parent) { // go right
  7516. i++;
  7517. node = parent.children[i];
  7518. goingUp = false;
  7519. } else node = null; // nothing found
  7520. }
  7521. return this;
  7522. },
  7523. toBBox: function (item) { return item; },
  7524. compareMinX: compareNodeMinX$1,
  7525. compareMinY: compareNodeMinY$1,
  7526. toJSON: function () { return this.data; },
  7527. fromJSON: function (data) {
  7528. this.data = data;
  7529. return this;
  7530. },
  7531. _all: function (node, result) {
  7532. var nodesToSearch = [];
  7533. while (node) {
  7534. if (node.leaf) result.push.apply(result, node.children);
  7535. else nodesToSearch.push.apply(nodesToSearch, node.children);
  7536. node = nodesToSearch.pop();
  7537. }
  7538. return result;
  7539. },
  7540. _build: function (items, left, right, height) {
  7541. var N = right - left + 1,
  7542. M = this._maxEntries,
  7543. node;
  7544. if (N <= M) {
  7545. // reached leaf level; return leaf
  7546. node = createNode$1(items.slice(left, right + 1));
  7547. calcBBox$1(node, this.toBBox);
  7548. return node;
  7549. }
  7550. if (!height) {
  7551. // target height of the bulk-loaded tree
  7552. height = Math.ceil(Math.log(N) / Math.log(M));
  7553. // target number of root entries to maximize storage utilization
  7554. M = Math.ceil(N / Math.pow(M, height - 1));
  7555. }
  7556. node = createNode$1([]);
  7557. node.leaf = false;
  7558. node.height = height;
  7559. // split the items into M mostly square tiles
  7560. var N2 = Math.ceil(N / M),
  7561. N1 = N2 * Math.ceil(Math.sqrt(M)),
  7562. i, j, right2, right3;
  7563. multiSelect$1(items, left, right, N1, this.compareMinX);
  7564. for (i = left; i <= right; i += N1) {
  7565. right2 = Math.min(i + N1 - 1, right);
  7566. multiSelect$1(items, i, right2, N2, this.compareMinY);
  7567. for (j = i; j <= right2; j += N2) {
  7568. right3 = Math.min(j + N2 - 1, right2);
  7569. // pack each entry recursively
  7570. node.children.push(this._build(items, j, right3, height - 1));
  7571. }
  7572. }
  7573. calcBBox$1(node, this.toBBox);
  7574. return node;
  7575. },
  7576. _chooseSubtree: function (bbox, node, level, path) {
  7577. var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
  7578. while (true) {
  7579. path.push(node);
  7580. if (node.leaf || path.length - 1 === level) break;
  7581. minArea = minEnlargement = Infinity;
  7582. for (i = 0, len = node.children.length; i < len; i++) {
  7583. child = node.children[i];
  7584. area = bboxArea$1(child);
  7585. enlargement = enlargedArea$1(bbox, child) - area;
  7586. // choose entry with the least area enlargement
  7587. if (enlargement < minEnlargement) {
  7588. minEnlargement = enlargement;
  7589. minArea = area < minArea ? area : minArea;
  7590. targetNode = child;
  7591. } else if (enlargement === minEnlargement) {
  7592. // otherwise choose one with the smallest area
  7593. if (area < minArea) {
  7594. minArea = area;
  7595. targetNode = child;
  7596. }
  7597. }
  7598. }
  7599. node = targetNode || node.children[0];
  7600. }
  7601. return node;
  7602. },
  7603. _insert: function (item, level, isNode) {
  7604. var toBBox = this.toBBox,
  7605. bbox = isNode ? item : toBBox(item),
  7606. insertPath = [];
  7607. // find the best node for accommodating the item, saving all nodes along the path too
  7608. var node = this._chooseSubtree(bbox, this.data, level, insertPath);
  7609. // put the item into the node
  7610. node.children.push(item);
  7611. extend$1(node, bbox);
  7612. // split on node overflow; propagate upwards if necessary
  7613. while (level >= 0) {
  7614. if (insertPath[level].children.length > this._maxEntries) {
  7615. this._split(insertPath, level);
  7616. level--;
  7617. } else break;
  7618. }
  7619. // adjust bboxes along the insertion path
  7620. this._adjustParentBBoxes(bbox, insertPath, level);
  7621. },
  7622. // split overflowed node into two
  7623. _split: function (insertPath, level) {
  7624. var node = insertPath[level],
  7625. M = node.children.length,
  7626. m = this._minEntries;
  7627. this._chooseSplitAxis(node, m, M);
  7628. var splitIndex = this._chooseSplitIndex(node, m, M);
  7629. var newNode = createNode$1(node.children.splice(splitIndex, node.children.length - splitIndex));
  7630. newNode.height = node.height;
  7631. newNode.leaf = node.leaf;
  7632. calcBBox$1(node, this.toBBox);
  7633. calcBBox$1(newNode, this.toBBox);
  7634. if (level) insertPath[level - 1].children.push(newNode);
  7635. else this._splitRoot(node, newNode);
  7636. },
  7637. _splitRoot: function (node, newNode) {
  7638. // split root node
  7639. this.data = createNode$1([node, newNode]);
  7640. this.data.height = node.height + 1;
  7641. this.data.leaf = false;
  7642. calcBBox$1(this.data, this.toBBox);
  7643. },
  7644. _chooseSplitIndex: function (node, m, M) {
  7645. var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
  7646. minOverlap = minArea = Infinity;
  7647. for (i = m; i <= M - m; i++) {
  7648. bbox1 = distBBox$1(node, 0, i, this.toBBox);
  7649. bbox2 = distBBox$1(node, i, M, this.toBBox);
  7650. overlap = intersectionArea$1(bbox1, bbox2);
  7651. area = bboxArea$1(bbox1) + bboxArea$1(bbox2);
  7652. // choose distribution with minimum overlap
  7653. if (overlap < minOverlap) {
  7654. minOverlap = overlap;
  7655. index = i;
  7656. minArea = area < minArea ? area : minArea;
  7657. } else if (overlap === minOverlap) {
  7658. // otherwise choose distribution with minimum area
  7659. if (area < minArea) {
  7660. minArea = area;
  7661. index = i;
  7662. }
  7663. }
  7664. }
  7665. return index;
  7666. },
  7667. // sorts node children by the best axis for split
  7668. _chooseSplitAxis: function (node, m, M) {
  7669. var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX$1,
  7670. compareMinY = node.leaf ? this.compareMinY : compareNodeMinY$1,
  7671. xMargin = this._allDistMargin(node, m, M, compareMinX),
  7672. yMargin = this._allDistMargin(node, m, M, compareMinY);
  7673. // if total distributions margin value is minimal for x, sort by minX,
  7674. // otherwise it's already sorted by minY
  7675. if (xMargin < yMargin) node.children.sort(compareMinX);
  7676. },
  7677. // total margin of all possible split distributions where each node is at least m full
  7678. _allDistMargin: function (node, m, M, compare) {
  7679. node.children.sort(compare);
  7680. var toBBox = this.toBBox,
  7681. leftBBox = distBBox$1(node, 0, m, toBBox),
  7682. rightBBox = distBBox$1(node, M - m, M, toBBox),
  7683. margin = bboxMargin$1(leftBBox) + bboxMargin$1(rightBBox),
  7684. i, child;
  7685. for (i = m; i < M - m; i++) {
  7686. child = node.children[i];
  7687. extend$1(leftBBox, node.leaf ? toBBox(child) : child);
  7688. margin += bboxMargin$1(leftBBox);
  7689. }
  7690. for (i = M - m - 1; i >= m; i--) {
  7691. child = node.children[i];
  7692. extend$1(rightBBox, node.leaf ? toBBox(child) : child);
  7693. margin += bboxMargin$1(rightBBox);
  7694. }
  7695. return margin;
  7696. },
  7697. _adjustParentBBoxes: function (bbox, path, level) {
  7698. // adjust bboxes along the given tree path
  7699. for (var i = level; i >= 0; i--) {
  7700. extend$1(path[i], bbox);
  7701. }
  7702. },
  7703. _condense: function (path) {
  7704. // go through the path, removing empty nodes and updating bboxes
  7705. for (var i = path.length - 1, siblings; i >= 0; i--) {
  7706. if (path[i].children.length === 0) {
  7707. if (i > 0) {
  7708. siblings = path[i - 1].children;
  7709. siblings.splice(siblings.indexOf(path[i]), 1);
  7710. } else this.clear();
  7711. } else calcBBox$1(path[i], this.toBBox);
  7712. }
  7713. },
  7714. _initFormat: function (format) {
  7715. // data format (minX, minY, maxX, maxY accessors)
  7716. // uses eval-type function compilation instead of just accepting a toBBox function
  7717. // because the algorithms are very sensitive to sorting functions performance,
  7718. // so they should be dead simple and without inner calls
  7719. var compareArr = ['return a', ' - b', ';'];
  7720. this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
  7721. this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
  7722. this.toBBox = new Function('a',
  7723. 'return {minX: a' + format[0] +
  7724. ', minY: a' + format[1] +
  7725. ', maxX: a' + format[2] +
  7726. ', maxY: a' + format[3] + '};');
  7727. }
  7728. };
  7729. function findItem$1(item, items, equalsFn) {
  7730. if (!equalsFn) return items.indexOf(item);
  7731. for (var i = 0; i < items.length; i++) {
  7732. if (equalsFn(item, items[i])) return i;
  7733. }
  7734. return -1;
  7735. }
  7736. // calculate node's bbox from bboxes of its children
  7737. function calcBBox$1(node, toBBox) {
  7738. distBBox$1(node, 0, node.children.length, toBBox, node);
  7739. }
  7740. // min bounding rectangle of node children from k to p-1
  7741. function distBBox$1(node, k, p, toBBox, destNode) {
  7742. if (!destNode) destNode = createNode$1(null);
  7743. destNode.minX = Infinity;
  7744. destNode.minY = Infinity;
  7745. destNode.maxX = -Infinity;
  7746. destNode.maxY = -Infinity;
  7747. for (var i = k, child; i < p; i++) {
  7748. child = node.children[i];
  7749. extend$1(destNode, node.leaf ? toBBox(child) : child);
  7750. }
  7751. return destNode;
  7752. }
  7753. function extend$1(a, b) {
  7754. a.minX = Math.min(a.minX, b.minX);
  7755. a.minY = Math.min(a.minY, b.minY);
  7756. a.maxX = Math.max(a.maxX, b.maxX);
  7757. a.maxY = Math.max(a.maxY, b.maxY);
  7758. return a;
  7759. }
  7760. function compareNodeMinX$1(a, b) { return a.minX - b.minX; }
  7761. function compareNodeMinY$1(a, b) { return a.minY - b.minY; }
  7762. function bboxArea$1(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }
  7763. function bboxMargin$1(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
  7764. function enlargedArea$1(a, b) {
  7765. return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
  7766. (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
  7767. }
  7768. function intersectionArea$1(a, b) {
  7769. var minX = Math.max(a.minX, b.minX),
  7770. minY = Math.max(a.minY, b.minY),
  7771. maxX = Math.min(a.maxX, b.maxX),
  7772. maxY = Math.min(a.maxY, b.maxY);
  7773. return Math.max(0, maxX - minX) *
  7774. Math.max(0, maxY - minY);
  7775. }
  7776. function contains$1(a, b) {
  7777. return a.minX <= b.minX &&
  7778. a.minY <= b.minY &&
  7779. b.maxX <= a.maxX &&
  7780. b.maxY <= a.maxY;
  7781. }
  7782. function intersects$4(a, b) {
  7783. return b.minX <= a.maxX &&
  7784. b.minY <= a.maxY &&
  7785. b.maxX >= a.minX &&
  7786. b.maxY >= a.minY;
  7787. }
  7788. function createNode$1(children) {
  7789. return {
  7790. children: children,
  7791. height: 1,
  7792. leaf: true,
  7793. minX: Infinity,
  7794. minY: Infinity,
  7795. maxX: -Infinity,
  7796. maxY: -Infinity
  7797. };
  7798. }
  7799. // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
  7800. // combines selection algorithm with binary divide & conquer approach
  7801. function multiSelect$1(arr, left, right, n, compare) {
  7802. var stack = [left, right],
  7803. mid;
  7804. while (stack.length) {
  7805. right = stack.pop();
  7806. left = stack.pop();
  7807. if (right - left <= n) continue;
  7808. mid = left + Math.ceil((right - left) / n / 2) * n;
  7809. quickselect$3(arr, mid, left, right, compare);
  7810. stack.push(left, mid, mid, right);
  7811. }
  7812. }
  7813. /**
  7814. * GeoJSON implementation of [RBush](https://github.com/mourner/rbush#rbush) spatial index.
  7815. *
  7816. * @name rbush
  7817. * @param {number} [maxEntries=9] defines the maximum number of entries in a tree node. 9 (used by default) is a
  7818. * reasonable choice for most applications. Higher value means faster insertion and slower search, and vice versa.
  7819. * @returns {RBush} GeoJSON RBush
  7820. * @example
  7821. * import geojsonRbush from 'geojson-rbush';
  7822. * var tree = geojsonRbush();
  7823. */
  7824. function geojsonRbush(maxEntries) {
  7825. var tree = rbush$4(maxEntries);
  7826. /**
  7827. * [insert](https://github.com/mourner/rbush#data-format)
  7828. *
  7829. * @param {Feature<any>} feature insert single GeoJSON Feature
  7830. * @returns {RBush} GeoJSON RBush
  7831. * @example
  7832. * var polygon = {
  7833. * "type": "Feature",
  7834. * "properties": {},
  7835. * "geometry": {
  7836. * "type": "Polygon",
  7837. * "coordinates": [[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]
  7838. * }
  7839. * }
  7840. * tree.insert(polygon)
  7841. */
  7842. tree.insert = function (feature) {
  7843. if (Array.isArray(feature)) {
  7844. var bbox = feature;
  7845. feature = bboxPolygon$2(bbox);
  7846. feature.bbox = bbox;
  7847. } else {
  7848. feature.bbox = feature.bbox ? feature.bbox : turfBBox(feature);
  7849. }
  7850. return rbush$4.prototype.insert.call(this, feature);
  7851. };
  7852. /**
  7853. * [load](https://github.com/mourner/rbush#bulk-inserting-data)
  7854. *
  7855. * @param {BBox[]|FeatureCollection<any>} features load entire GeoJSON FeatureCollection
  7856. * @returns {RBush} GeoJSON RBush
  7857. * @example
  7858. * var polygons = {
  7859. * "type": "FeatureCollection",
  7860. * "features": [
  7861. * {
  7862. * "type": "Feature",
  7863. * "properties": {},
  7864. * "geometry": {
  7865. * "type": "Polygon",
  7866. * "coordinates": [[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]
  7867. * }
  7868. * },
  7869. * {
  7870. * "type": "Feature",
  7871. * "properties": {},
  7872. * "geometry": {
  7873. * "type": "Polygon",
  7874. * "coordinates": [[[-93, 32], [-83, 32], [-83, 39], [-93, 39], [-93, 32]]]
  7875. * }
  7876. * }
  7877. * ]
  7878. * }
  7879. * tree.load(polygons)
  7880. */
  7881. tree.load = function (features) {
  7882. var load = [];
  7883. // Load an Array of BBox
  7884. if (Array.isArray(features)) {
  7885. features.forEach(function (bbox) {
  7886. var feature = bboxPolygon$2(bbox);
  7887. feature.bbox = bbox;
  7888. load.push(feature);
  7889. });
  7890. } else {
  7891. // Load FeatureCollection
  7892. featureEach(features, function (feature) {
  7893. feature.bbox = feature.bbox ? feature.bbox : turfBBox(feature);
  7894. load.push(feature);
  7895. });
  7896. }
  7897. return rbush$4.prototype.load.call(this, load);
  7898. };
  7899. /**
  7900. * [remove](https://github.com/mourner/rbush#removing-data)
  7901. *
  7902. * @param {BBox|Feature<any>} feature remove single GeoJSON Feature
  7903. * @returns {RBush} GeoJSON RBush
  7904. * @example
  7905. * var polygon = {
  7906. * "type": "Feature",
  7907. * "properties": {},
  7908. * "geometry": {
  7909. * "type": "Polygon",
  7910. * "coordinates": [[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]
  7911. * }
  7912. * }
  7913. * tree.remove(polygon)
  7914. */
  7915. tree.remove = function (feature) {
  7916. if (Array.isArray(feature)) {
  7917. var bbox = feature;
  7918. feature = bboxPolygon$2(bbox);
  7919. feature.bbox = bbox;
  7920. }
  7921. return rbush$4.prototype.remove.call(this, feature);
  7922. };
  7923. /**
  7924. * [clear](https://github.com/mourner/rbush#removing-data)
  7925. *
  7926. * @returns {RBush} GeoJSON Rbush
  7927. * @example
  7928. * tree.clear()
  7929. */
  7930. tree.clear = function () {
  7931. return rbush$4.prototype.clear.call(this);
  7932. };
  7933. /**
  7934. * [search](https://github.com/mourner/rbush#search)
  7935. *
  7936. * @param {BBox|FeatureCollection|Feature<any>} geojson search with GeoJSON
  7937. * @returns {FeatureCollection<any>} all features that intersects with the given GeoJSON.
  7938. * @example
  7939. * var polygon = {
  7940. * "type": "Feature",
  7941. * "properties": {},
  7942. * "geometry": {
  7943. * "type": "Polygon",
  7944. * "coordinates": [[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]
  7945. * }
  7946. * }
  7947. * tree.search(polygon)
  7948. */
  7949. tree.search = function (geojson) {
  7950. var features = rbush$4.prototype.search.call(this, this.toBBox(geojson));
  7951. return {
  7952. type: 'FeatureCollection',
  7953. features: features
  7954. };
  7955. };
  7956. /**
  7957. * [collides](https://github.com/mourner/rbush#collisions)
  7958. *
  7959. * @param {BBox|FeatureCollection|Feature<any>} geojson collides with GeoJSON
  7960. * @returns {boolean} true if there are any items intersecting the given GeoJSON, otherwise false.
  7961. * @example
  7962. * var polygon = {
  7963. * "type": "Feature",
  7964. * "properties": {},
  7965. * "geometry": {
  7966. * "type": "Polygon",
  7967. * "coordinates": [[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]
  7968. * }
  7969. * }
  7970. * tree.collides(polygon)
  7971. */
  7972. tree.collides = function (geojson) {
  7973. return rbush$4.prototype.collides.call(this, this.toBBox(geojson));
  7974. };
  7975. /**
  7976. * [all](https://github.com/mourner/rbush#search)
  7977. *
  7978. * @returns {FeatureCollection<any>} all the features in RBush
  7979. * @example
  7980. * tree.all()
  7981. * //=FeatureCollection
  7982. */
  7983. tree.all = function () {
  7984. var features = rbush$4.prototype.all.call(this);
  7985. return {
  7986. type: 'FeatureCollection',
  7987. features: features
  7988. };
  7989. };
  7990. /**
  7991. * [toJSON](https://github.com/mourner/rbush#export-and-import)
  7992. *
  7993. * @returns {any} export data as JSON object
  7994. * @example
  7995. * var exported = tree.toJSON()
  7996. * //=JSON object
  7997. */
  7998. tree.toJSON = function () {
  7999. return rbush$4.prototype.toJSON.call(this);
  8000. };
  8001. /**
  8002. * [fromJSON](https://github.com/mourner/rbush#export-and-import)
  8003. *
  8004. * @param {any} json import previously exported data
  8005. * @returns {RBush} GeoJSON RBush
  8006. * @example
  8007. * var exported = {
  8008. * "children": [
  8009. * {
  8010. * "type": "Feature",
  8011. * "geometry": {
  8012. * "type": "Point",
  8013. * "coordinates": [110, 50]
  8014. * },
  8015. * "properties": {},
  8016. * "bbox": [110, 50, 110, 50]
  8017. * }
  8018. * ],
  8019. * "height": 1,
  8020. * "leaf": true,
  8021. * "minX": 110,
  8022. * "minY": 50,
  8023. * "maxX": 110,
  8024. * "maxY": 50
  8025. * }
  8026. * tree.fromJSON(exported)
  8027. */
  8028. tree.fromJSON = function (json) {
  8029. return rbush$4.prototype.fromJSON.call(this, json);
  8030. };
  8031. /**
  8032. * Converts GeoJSON to {minX, minY, maxX, maxY} schema
  8033. *
  8034. * @private
  8035. * @param {BBox|FeatureCollectio|Feature<any>} geojson feature(s) to retrieve BBox from
  8036. * @returns {Object} converted to {minX, minY, maxX, maxY}
  8037. */
  8038. tree.toBBox = function (geojson) {
  8039. var bbox;
  8040. if (geojson.bbox) bbox = geojson.bbox;
  8041. else if (Array.isArray(geojson) && geojson.length === 4) bbox = geojson;
  8042. else bbox = turfBBox(geojson);
  8043. return {
  8044. minX: bbox[0],
  8045. minY: bbox[1],
  8046. maxX: bbox[2],
  8047. maxY: bbox[3]
  8048. };
  8049. };
  8050. return tree;
  8051. }
  8052. /**
  8053. * Takes a bbox and returns an equivalent {@link Polygon|polygon}.
  8054. *
  8055. * @private
  8056. * @name bboxPolygon
  8057. * @param {Array<number>} bbox extent in [minX, minY, maxX, maxY] order
  8058. * @returns {Feature<Polygon>} a Polygon representation of the bounding box
  8059. * @example
  8060. * var bbox = [0, 0, 10, 10];
  8061. *
  8062. * var poly = turf.bboxPolygon(bbox);
  8063. *
  8064. * //addToMap
  8065. * var addToMap = [poly]
  8066. */
  8067. function bboxPolygon$2(bbox) {
  8068. var lowLeft = [bbox[0], bbox[1]];
  8069. var topLeft = [bbox[0], bbox[3]];
  8070. var topRight = [bbox[2], bbox[3]];
  8071. var lowRight = [bbox[2], bbox[1]];
  8072. var coordinates = [[lowLeft, lowRight, topRight, topLeft, lowLeft]];
  8073. return {
  8074. type: 'Feature',
  8075. bbox: bbox,
  8076. properties: {},
  8077. geometry: {
  8078. type: 'Polygon',
  8079. coordinates: coordinates
  8080. }
  8081. };
  8082. }
  8083. /**
  8084. * Takes a set of features, calculates the bbox of all input features, and returns a bounding box.
  8085. *
  8086. * @private
  8087. * @name bbox
  8088. * @param {FeatureCollection|Feature<any>} geojson input features
  8089. * @returns {Array<number>} bbox extent in [minX, minY, maxX, maxY] order
  8090. * @example
  8091. * var line = turf.lineString([[-74, 40], [-78, 42], [-82, 35]]);
  8092. * var bbox = turf.bbox(line);
  8093. * var bboxPolygon = turf.bboxPolygon(bbox);
  8094. *
  8095. * //addToMap
  8096. * var addToMap = [line, bboxPolygon]
  8097. */
  8098. function turfBBox(geojson) {
  8099. var bbox = [Infinity, Infinity, -Infinity, -Infinity];
  8100. coordEach(geojson, function (coord) {
  8101. if (bbox[0] > coord[0]) bbox[0] = coord[0];
  8102. if (bbox[1] > coord[1]) bbox[1] = coord[1];
  8103. if (bbox[2] < coord[0]) bbox[2] = coord[0];
  8104. if (bbox[3] < coord[1]) bbox[3] = coord[1];
  8105. });
  8106. return bbox;
  8107. }
  8108. /**
  8109. * Creates a {@link FeatureCollection} of 2-vertex {@link LineString} segments from a {@link LineString|(Multi)LineString} or {@link Polygon|(Multi)Polygon}.
  8110. *
  8111. * @name lineSegment
  8112. * @param {Geometry|FeatureCollection|Feature<LineString|MultiLineString|MultiPolygon|Polygon>} geojson GeoJSON Polygon or LineString
  8113. * @returns {FeatureCollection<LineString>} 2-vertex line segments
  8114. * @example
  8115. * var polygon = turf.polygon([[[-50, 5], [-40, -10], [-50, -10], [-40, 5], [-50, 5]]]);
  8116. * var segments = turf.lineSegment(polygon);
  8117. *
  8118. * //addToMap
  8119. * var addToMap = [polygon, segments]
  8120. */
  8121. function lineSegment(geojson) {
  8122. if (!geojson) throw new Error('geojson is required');
  8123. var results = [];
  8124. flattenEach(geojson, function (feature$$1) {
  8125. lineSegmentFeature(feature$$1, results);
  8126. });
  8127. return featureCollection(results);
  8128. }
  8129. /**
  8130. * Line Segment
  8131. *
  8132. * @private
  8133. * @param {Feature<LineString|Polygon>} geojson Line or polygon feature
  8134. * @param {Array} results push to results
  8135. * @returns {void}
  8136. */
  8137. function lineSegmentFeature(geojson, results) {
  8138. var coords = [];
  8139. var geometry$$1 = geojson.geometry;
  8140. switch (geometry$$1.type) {
  8141. case 'Polygon':
  8142. coords = getCoords(geometry$$1);
  8143. break;
  8144. case 'LineString':
  8145. coords = [getCoords(geometry$$1)];
  8146. }
  8147. coords.forEach(function (coord) {
  8148. var segments = createSegments(coord, geojson.properties);
  8149. segments.forEach(function (segment) {
  8150. segment.id = results.length;
  8151. results.push(segment);
  8152. });
  8153. });
  8154. }
  8155. /**
  8156. * Create Segments from LineString coordinates
  8157. *
  8158. * @private
  8159. * @param {LineString} coords LineString coordinates
  8160. * @param {*} properties GeoJSON properties
  8161. * @returns {Array<Feature<LineString>>} line segments
  8162. */
  8163. function createSegments(coords, properties) {
  8164. var segments = [];
  8165. coords.reduce(function (previousCoords, currentCoords) {
  8166. var segment = lineString([previousCoords, currentCoords], properties);
  8167. segment.bbox = bbox$3(previousCoords, currentCoords);
  8168. segments.push(segment);
  8169. return currentCoords;
  8170. });
  8171. return segments;
  8172. }
  8173. /**
  8174. * Create BBox between two coordinates (faster than @turf/bbox)
  8175. *
  8176. * @private
  8177. * @param {Array<number>} coords1 Point coordinate
  8178. * @param {Array<number>} coords2 Point coordinate
  8179. * @returns {BBox} [west, south, east, north]
  8180. */
  8181. function bbox$3(coords1, coords2) {
  8182. var x1 = coords1[0];
  8183. var y1 = coords1[1];
  8184. var x2 = coords2[0];
  8185. var y2 = coords2[1];
  8186. var west = (x1 < x2) ? x1 : x2;
  8187. var south = (y1 < y2) ? y1 : y2;
  8188. var east = (x1 > x2) ? x1 : x2;
  8189. var north = (y1 > y2) ? y1 : y2;
  8190. return [west, south, east, north];
  8191. }
  8192. /**
  8193. * Takes any LineString or Polygon GeoJSON and returns the intersecting point(s).
  8194. *
  8195. * @name lineIntersect
  8196. * @param {Geometry|FeatureCollection|Feature<LineString|MultiLineString|Polygon|MultiPolygon>} line1 any LineString or Polygon
  8197. * @param {Geometry|FeatureCollection|Feature<LineString|MultiLineString|Polygon|MultiPolygon>} line2 any LineString or Polygon
  8198. * @returns {FeatureCollection<Point>} point(s) that intersect both
  8199. * @example
  8200. * var line1 = turf.lineString([[126, -11], [129, -21]]);
  8201. * var line2 = turf.lineString([[123, -18], [131, -14]]);
  8202. * var intersects = turf.lineIntersect(line1, line2);
  8203. *
  8204. * //addToMap
  8205. * var addToMap = [line1, line2, intersects]
  8206. */
  8207. function lineIntersect(line1, line2) {
  8208. var unique = {};
  8209. var results = [];
  8210. // First, normalize geometries to features
  8211. // Then, handle simple 2-vertex segments
  8212. if (line1.type === 'LineString') line1 = feature(line1);
  8213. if (line2.type === 'LineString') line2 = feature(line2);
  8214. if (line1.type === 'Feature' &&
  8215. line2.type === 'Feature' &&
  8216. line1.geometry.type === 'LineString' &&
  8217. line2.geometry.type === 'LineString' &&
  8218. line1.geometry.coordinates.length === 2 &&
  8219. line2.geometry.coordinates.length === 2) {
  8220. var intersect = intersects$3(line1, line2);
  8221. if (intersect) results.push(intersect);
  8222. return featureCollection(results);
  8223. }
  8224. // Handles complex GeoJSON Geometries
  8225. var tree = geojsonRbush();
  8226. tree.load(lineSegment(line2));
  8227. featureEach(lineSegment(line1), function (segment) {
  8228. featureEach(tree.search(segment), function (match) {
  8229. var intersect = intersects$3(segment, match);
  8230. if (intersect) {
  8231. // prevent duplicate points https://github.com/Turfjs/turf/issues/688
  8232. var key = getCoords(intersect).join(',');
  8233. if (!unique[key]) {
  8234. unique[key] = true;
  8235. results.push(intersect);
  8236. }
  8237. }
  8238. });
  8239. });
  8240. return featureCollection(results);
  8241. }
  8242. /**
  8243. * Find a point that intersects LineStrings with two coordinates each
  8244. *
  8245. * @private
  8246. * @param {Feature<LineString>} line1 GeoJSON LineString (Must only contain 2 coordinates)
  8247. * @param {Feature<LineString>} line2 GeoJSON LineString (Must only contain 2 coordinates)
  8248. * @returns {Feature<Point>} intersecting GeoJSON Point
  8249. */
  8250. function intersects$3(line1, line2) {
  8251. var coords1 = getCoords(line1);
  8252. var coords2 = getCoords(line2);
  8253. if (coords1.length !== 2) {
  8254. throw new Error('<intersects> line1 must only contain 2 coordinates');
  8255. }
  8256. if (coords2.length !== 2) {
  8257. throw new Error('<intersects> line2 must only contain 2 coordinates');
  8258. }
  8259. var x1 = coords1[0][0];
  8260. var y1 = coords1[0][1];
  8261. var x2 = coords1[1][0];
  8262. var y2 = coords1[1][1];
  8263. var x3 = coords2[0][0];
  8264. var y3 = coords2[0][1];
  8265. var x4 = coords2[1][0];
  8266. var y4 = coords2[1][1];
  8267. var denom = ((y4 - y3) * (x2 - x1)) - ((x4 - x3) * (y2 - y1));
  8268. var numeA = ((x4 - x3) * (y1 - y3)) - ((y4 - y3) * (x1 - x3));
  8269. var numeB = ((x2 - x1) * (y1 - y3)) - ((y2 - y1) * (x1 - x3));
  8270. if (denom === 0) {
  8271. if (numeA === 0 && numeB === 0) {
  8272. return null;
  8273. }
  8274. return null;
  8275. }
  8276. var uA = numeA / denom;
  8277. var uB = numeB / denom;
  8278. if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) {
  8279. var x = x1 + (uA * (x2 - x1));
  8280. var y = y1 + (uA * (y2 - y1));
  8281. return point([x, y]);
  8282. }
  8283. return null;
  8284. }
  8285. /**
  8286. * Takes a {@link Point} and a {@link LineString} and calculates the closest Point on the (Multi)LineString.
  8287. *
  8288. * @name nearestPointOnLine
  8289. * @param {Geometry|Feature<LineString|MultiLineString>} lines lines to snap to
  8290. * @param {Geometry|Feature<Point>|number[]} pt point to snap from
  8291. * @param {Object} [options={}] Optional parameters
  8292. * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers
  8293. * @returns {Feature<Point>} closest point on the `line` to `point`. The properties object will contain three values: `index`: closest point was found on nth line part, `dist`: distance between pt and the closest point, `location`: distance along the line between start and the closest point.
  8294. * @example
  8295. * var line = turf.lineString([
  8296. * [-77.031669, 38.878605],
  8297. * [-77.029609, 38.881946],
  8298. * [-77.020339, 38.884084],
  8299. * [-77.025661, 38.885821],
  8300. * [-77.021884, 38.889563],
  8301. * [-77.019824, 38.892368]
  8302. * ]);
  8303. * var pt = turf.point([-77.037076, 38.884017]);
  8304. *
  8305. * var snapped = turf.nearestPointOnLine(line, pt, {units: 'miles'});
  8306. *
  8307. * //addToMap
  8308. * var addToMap = [line, pt, snapped];
  8309. * snapped.properties['marker-color'] = '#00f';
  8310. */
  8311. function nearestPointOnLine(lines, pt, options) {
  8312. // Optional parameters
  8313. options = options || {};
  8314. if (!isObject(options)) throw new Error('options is invalid');
  8315. // validation
  8316. var type = (lines.geometry) ? lines.geometry.type : lines.type;
  8317. if (type !== 'LineString' && type !== 'MultiLineString') {
  8318. throw new Error('lines must be LineString or MultiLineString');
  8319. }
  8320. var closestPt = point([Infinity, Infinity], {
  8321. dist: Infinity
  8322. });
  8323. var length = 0.0;
  8324. flattenEach(lines, function (line) {
  8325. var coords = getCoords(line);
  8326. for (var i = 0; i < coords.length - 1; i++) {
  8327. //start
  8328. var start = point(coords[i]);
  8329. start.properties.dist = distance(pt, start, options);
  8330. //stop
  8331. var stop = point(coords[i + 1]);
  8332. stop.properties.dist = distance(pt, stop, options);
  8333. // sectionLength
  8334. var sectionLength = distance(start, stop, options);
  8335. //perpendicular
  8336. var heightDistance = Math.max(start.properties.dist, stop.properties.dist);
  8337. var direction = bearing(start, stop);
  8338. var perpendicularPt1 = destination(pt, heightDistance, direction + 90, options);
  8339. var perpendicularPt2 = destination(pt, heightDistance, direction - 90, options);
  8340. var intersect = lineIntersect(
  8341. lineString([perpendicularPt1.geometry.coordinates, perpendicularPt2.geometry.coordinates]),
  8342. lineString([start.geometry.coordinates, stop.geometry.coordinates])
  8343. );
  8344. var intersectPt = null;
  8345. if (intersect.features.length > 0) {
  8346. intersectPt = intersect.features[0];
  8347. intersectPt.properties.dist = distance(pt, intersectPt, options);
  8348. intersectPt.properties.location = length + distance(start, intersectPt, options);
  8349. }
  8350. if (start.properties.dist < closestPt.properties.dist) {
  8351. closestPt = start;
  8352. closestPt.properties.index = i;
  8353. closestPt.properties.location = length;
  8354. }
  8355. if (stop.properties.dist < closestPt.properties.dist) {
  8356. closestPt = stop;
  8357. closestPt.properties.index = i + 1;
  8358. closestPt.properties.location = length + sectionLength;
  8359. }
  8360. if (intersectPt && intersectPt.properties.dist < closestPt.properties.dist) {
  8361. closestPt = intersectPt;
  8362. closestPt.properties.index = i;
  8363. }
  8364. // update length
  8365. length += sectionLength;
  8366. }
  8367. });
  8368. return closestPt;
  8369. }
  8370. // https://en.wikipedia.org/wiki/Rhumb_line
  8371. /**
  8372. * Takes two {@link Point|points} and finds the bearing angle between them along a Rhumb line
  8373. * i.e. the angle measured in degrees start the north line (0 degrees)
  8374. *
  8375. * @name rhumbBearing
  8376. * @param {Coord} start starting Point
  8377. * @param {Coord} end ending Point
  8378. * @param {Object} [options] Optional parameters
  8379. * @param {boolean} [options.final=false] calculates the final bearing if true
  8380. * @returns {number} bearing from north in decimal degrees, between -180 and 180 degrees (positive clockwise)
  8381. * @example
  8382. * var point1 = turf.point([-75.343, 39.984], {"marker-color": "#F00"});
  8383. * var point2 = turf.point([-75.534, 39.123], {"marker-color": "#00F"});
  8384. *
  8385. * var bearing = turf.rhumbBearing(point1, point2);
  8386. *
  8387. * //addToMap
  8388. * var addToMap = [point1, point2];
  8389. * point1.properties.bearing = bearing;
  8390. * point2.properties.bearing = bearing;
  8391. */
  8392. function rhumbBearing(start, end, options) {
  8393. // Optional parameters
  8394. options = options || {};
  8395. if (!isObject(options)) throw new Error('options is invalid');
  8396. var final = options.final;
  8397. // validation
  8398. if (!start) throw new Error('start point is required');
  8399. if (!end) throw new Error('end point is required');
  8400. var bear360;
  8401. if (final) bear360 = calculateRhumbBearing(getCoord(end), getCoord(start));
  8402. else bear360 = calculateRhumbBearing(getCoord(start), getCoord(end));
  8403. var bear180 = (bear360 > 180) ? -(360 - bear360) : bear360;
  8404. return bear180;
  8405. }
  8406. /**
  8407. * Returns the bearing from ‘this’ point to destination point along a rhumb line.
  8408. * Adapted from Geodesy: https://github.com/chrisveness/geodesy/blob/master/latlon-spherical.js
  8409. *
  8410. * @private
  8411. * @param {Array<number>} from - origin point.
  8412. * @param {Array<number>} to - destination point.
  8413. * @returns {number} Bearing in degrees from north.
  8414. * @example
  8415. * var p1 = new LatLon(51.127, 1.338);
  8416. * var p2 = new LatLon(50.964, 1.853);
  8417. * var d = p1.rhumbBearingTo(p2); // 116.7 m
  8418. */
  8419. function calculateRhumbBearing(from, to) {
  8420. // φ => phi
  8421. // Δλ => deltaLambda
  8422. // Δψ => deltaPsi
  8423. // θ => theta
  8424. var phi1 = degreesToRadians(from[1]);
  8425. var phi2 = degreesToRadians(to[1]);
  8426. var deltaLambda = degreesToRadians((to[0] - from[0]));
  8427. // if deltaLambdaon over 180° take shorter rhumb line across the anti-meridian:
  8428. if (deltaLambda > Math.PI) deltaLambda -= 2 * Math.PI;
  8429. if (deltaLambda < -Math.PI) deltaLambda += 2 * Math.PI;
  8430. var deltaPsi = Math.log(Math.tan(phi2 / 2 + Math.PI / 4) / Math.tan(phi1 / 2 + Math.PI / 4));
  8431. var theta = Math.atan2(deltaLambda, deltaPsi);
  8432. return (radiansToDegrees(theta) + 360) % 360;
  8433. }
  8434. // https://en.wikipedia.org/wiki/Rhumb_line
  8435. /**
  8436. * Calculates the distance along a rhumb line between two {@link Point|points} in degrees, radians,
  8437. * miles, or kilometers.
  8438. *
  8439. * @name rhumbDistance
  8440. * @param {Coord} from origin point
  8441. * @param {Coord} to destination point
  8442. * @param {Object} [options] Optional parameters
  8443. * @param {string} [options.units="kilometers"] can be degrees, radians, miles, or kilometers
  8444. * @returns {number} distance between the two points
  8445. * @example
  8446. * var from = turf.point([-75.343, 39.984]);
  8447. * var to = turf.point([-75.534, 39.123]);
  8448. * var options = {units: 'miles'};
  8449. *
  8450. * var distance = turf.rhumbDistance(from, to, options);
  8451. *
  8452. * //addToMap
  8453. * var addToMap = [from, to];
  8454. * from.properties.distance = distance;
  8455. * to.properties.distance = distance;
  8456. */
  8457. function rhumbDistance(from, to, options) {
  8458. // Optional parameters
  8459. options = options || {};
  8460. if (!isObject(options)) throw new Error('options is invalid');
  8461. var units = options.units;
  8462. // validation
  8463. if (!from) throw new Error('from point is required');
  8464. if (!to) throw new Error('to point is required');
  8465. var origin = getCoord(from);
  8466. var destination = getCoord(to);
  8467. // compensate the crossing of the 180th meridian (https://macwright.org/2016/09/26/the-180th-meridian.html)
  8468. // solution from https://github.com/mapbox/mapbox-gl-js/issues/3250#issuecomment-294887678
  8469. destination[0] += (destination[0] - origin[0] > 180) ? -360 : (origin[0] - destination[0] > 180) ? 360 : 0;
  8470. var distanceInMeters = calculateRhumbDistance(origin, destination);
  8471. var distance = convertLength(distanceInMeters, 'meters', units);
  8472. return distance;
  8473. }
  8474. /**
  8475. * Returns the distance travelling from ‘this’ point to destination point along a rhumb line.
  8476. * Adapted from Geodesy: https://github.com/chrisveness/geodesy/blob/master/latlon-spherical.js
  8477. *
  8478. * @private
  8479. * @param {Array<number>} origin point.
  8480. * @param {Array<number>} destination point.
  8481. * @param {number} [radius=6371e3] - (Mean) radius of earth (defaults to radius in metres).
  8482. * @returns {number} Distance in km between this point and destination point (same units as radius).
  8483. *
  8484. * @example
  8485. * var p1 = new LatLon(51.127, 1.338);
  8486. * var p2 = new LatLon(50.964, 1.853);
  8487. * var d = p1.distanceTo(p2); // 40.31 km
  8488. */
  8489. function calculateRhumbDistance(origin, destination, radius) {
  8490. // φ => phi
  8491. // λ => lambda
  8492. // ψ => psi
  8493. // Δ => Delta
  8494. // δ => delta
  8495. // θ => theta
  8496. radius = (radius === undefined) ? earthRadius : Number(radius);
  8497. // see www.edwilliams.org/avform.htm#Rhumb
  8498. var R = radius;
  8499. var phi1 = origin[1] * Math.PI / 180;
  8500. var phi2 = destination[1] * Math.PI / 180;
  8501. var DeltaPhi = phi2 - phi1;
  8502. var DeltaLambda = Math.abs(destination[0] - origin[0]) * Math.PI / 180;
  8503. // if dLon over 180° take shorter rhumb line across the anti-meridian:
  8504. if (DeltaLambda > Math.PI) DeltaLambda -= 2 * Math.PI;
  8505. // on Mercator projection, longitude distances shrink by latitude; q is the 'stretch factor'
  8506. // q becomes ill-conditioned along E-W line (0/0); use empirical tolerance to avoid it
  8507. var DeltaPsi = Math.log(Math.tan(phi2 / 2 + Math.PI / 4) / Math.tan(phi1 / 2 + Math.PI / 4));
  8508. var q = Math.abs(DeltaPsi) > 10e-12 ? DeltaPhi / DeltaPsi : Math.cos(phi1);
  8509. // distance is pythagoras on 'stretched' Mercator projection
  8510. var delta = Math.sqrt(DeltaPhi * DeltaPhi + q * q * DeltaLambda * DeltaLambda); // angular distance in radians
  8511. var dist = delta * R;
  8512. return dist;
  8513. }
  8514. /**
  8515. * Converts a WGS84 GeoJSON object into Mercator (EPSG:900913) projection
  8516. *
  8517. * @name toMercator
  8518. * @param {GeoJSON|Position} geojson WGS84 GeoJSON object
  8519. * @param {Object} [options] Optional parameters
  8520. * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
  8521. * @returns {GeoJSON} true/false
  8522. * @example
  8523. * var pt = turf.point([-71,41]);
  8524. * var converted = turf.toMercator(pt);
  8525. *
  8526. * //addToMap
  8527. * var addToMap = [pt, converted];
  8528. */
  8529. function toMercator(geojson, options) {
  8530. return convert(geojson, 'mercator', options);
  8531. }
  8532. /**
  8533. * Converts a Mercator (EPSG:900913) GeoJSON object into WGS84 projection
  8534. *
  8535. * @name toWgs84
  8536. * @param {GeoJSON|Position} geojson Mercator GeoJSON object
  8537. * @param {Object} [options] Optional parameters
  8538. * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
  8539. * @returns {GeoJSON} true/false
  8540. * @example
  8541. * var pt = turf.point([-7903683.846322424, 5012341.663847514]);
  8542. * var converted = turf.toWgs84(pt);
  8543. *
  8544. * //addToMap
  8545. * var addToMap = [pt, converted];
  8546. */
  8547. function toWgs84(geojson, options) {
  8548. return convert(geojson, 'wgs84', options);
  8549. }
  8550. /**
  8551. * Converts a GeoJSON coordinates to the defined `projection`
  8552. *
  8553. * @private
  8554. * @param {GeoJSON} geojson GeoJSON Feature or Geometry
  8555. * @param {string} projection defines the projection system to convert the coordinates to
  8556. * @param {Object} [options] Optional parameters
  8557. * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
  8558. * @returns {GeoJSON} true/false
  8559. */
  8560. function convert(geojson, projection, options) {
  8561. // Optional parameters
  8562. options = options || {};
  8563. if (!isObject(options)) throw new Error('options is invalid');
  8564. var mutate = options.mutate;
  8565. // Validation
  8566. if (!geojson) throw new Error('geojson is required');
  8567. // Handle Position
  8568. if (Array.isArray(geojson) && isNumber(geojson[0])) geojson = (projection === 'mercator') ? convertToMercator(geojson) : convertToWgs84(geojson);
  8569. // Handle GeoJSON
  8570. else {
  8571. // Handle possible data mutation
  8572. if (mutate !== true) geojson = clone(geojson);
  8573. coordEach(geojson, function (coord) {
  8574. var newCoord = (projection === 'mercator') ? convertToMercator(coord) : convertToWgs84(coord);
  8575. coord[0] = newCoord[0];
  8576. coord[1] = newCoord[1];
  8577. });
  8578. }
  8579. return geojson;
  8580. }
  8581. /**
  8582. * Convert lon/lat values to 900913 x/y.
  8583. * (from https://github.com/mapbox/sphericalmercator)
  8584. *
  8585. * @private
  8586. * @param {Array<number>} lonLat WGS84 point
  8587. * @returns {Array<number>} Mercator [x, y] point
  8588. */
  8589. function convertToMercator(lonLat) {
  8590. var D2R = Math.PI / 180,
  8591. // 900913 properties
  8592. A = 6378137.0,
  8593. MAXEXTENT = 20037508.342789244;
  8594. // compensate longitudes passing the 180th meridian
  8595. // from https://github.com/proj4js/proj4js/blob/master/lib/common/adjust_lon.js
  8596. var adjusted = (Math.abs(lonLat[0]) <= 180) ? lonLat[0] : (lonLat[0] - (sign(lonLat[0]) * 360));
  8597. var xy = [
  8598. A * adjusted * D2R,
  8599. A * Math.log(Math.tan((Math.PI * 0.25) + (0.5 * lonLat[1] * D2R)))
  8600. ];
  8601. // if xy value is beyond maxextent (e.g. poles), return maxextent
  8602. if (xy[0] > MAXEXTENT) xy[0] = MAXEXTENT;
  8603. if (xy[0] < -MAXEXTENT) xy[0] = -MAXEXTENT;
  8604. if (xy[1] > MAXEXTENT) xy[1] = MAXEXTENT;
  8605. if (xy[1] < -MAXEXTENT) xy[1] = -MAXEXTENT;
  8606. return xy;
  8607. }
  8608. /**
  8609. * Convert 900913 x/y values to lon/lat.
  8610. * (from https://github.com/mapbox/sphericalmercator)
  8611. *
  8612. * @private
  8613. * @param {Array<number>} xy Mercator [x, y] point
  8614. * @returns {Array<number>} WGS84 [lon, lat] point
  8615. */
  8616. function convertToWgs84(xy) {
  8617. // 900913 properties.
  8618. var R2D = 180 / Math.PI;
  8619. var A = 6378137.0;
  8620. return [
  8621. (xy[0] * R2D / A),
  8622. ((Math.PI * 0.5) - 2.0 * Math.atan(Math.exp(-xy[1] / A))) * R2D
  8623. ];
  8624. }
  8625. /**
  8626. * Returns the sign of the input, or zero
  8627. *
  8628. * @private
  8629. * @param {number} x input
  8630. * @returns {number} -1|0|1 output
  8631. */
  8632. function sign(x) {
  8633. return (x < 0) ? -1 : (x > 0) ? 1 : 0;
  8634. }
  8635. var main_es$3 = Object.freeze({
  8636. toMercator: toMercator,
  8637. toWgs84: toWgs84
  8638. });
  8639. // (logic of computation inspired by:
  8640. // https://stackoverflow.com/questions/32771458/distance-from-lat-lng-point-to-minor-arc-segment)
  8641. /**
  8642. * Returns the minimum distance between a {@link Point} and a {@link LineString}, being the distance from a line the
  8643. * minimum distance between the point and any segment of the `LineString`.
  8644. *
  8645. * @name pointToLineDistance
  8646. * @param {Coord} pt Feature or Geometry
  8647. * @param {Feature<LineString>} line GeoJSON Feature or Geometry
  8648. * @param {Object} [options={}] Optional parameters
  8649. * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers
  8650. * @param {boolean} [options.mercator=false] if distance should be on Mercator or WGS84 projection
  8651. * @returns {number} distance between point and line
  8652. * @example
  8653. * var pt = turf.point([0, 0]);
  8654. * var line = turf.lineString([[1, 1],[-1, 1]]);
  8655. *
  8656. * var distance = turf.pointToLineDistance(pt, line, {units: 'miles'});
  8657. * //=69.11854715938406
  8658. */
  8659. function pointToLineDistance(pt, line, options) {
  8660. // Optional parameters
  8661. options = options || {};
  8662. if (!isObject(options)) throw new Error('options is invalid');
  8663. // validation
  8664. if (!pt) throw new Error('pt is required');
  8665. if (Array.isArray(pt)) pt = point(pt);
  8666. else if (pt.type === 'Point') pt = feature(pt);
  8667. else featureOf(pt, 'Point', 'point');
  8668. if (!line) throw new Error('line is required');
  8669. if (Array.isArray(line)) line = lineString(line);
  8670. else if (line.type === 'LineString') line = feature(line);
  8671. else featureOf(line, 'LineString', 'line');
  8672. var distance$$1 = Infinity;
  8673. var p = pt.geometry.coordinates;
  8674. segmentEach(line, function (segment) {
  8675. var a = segment.geometry.coordinates[0];
  8676. var b = segment.geometry.coordinates[1];
  8677. var d = distanceToSegment(p, a, b, options);
  8678. if (distance$$1 > d) distance$$1 = d;
  8679. });
  8680. return distance$$1;
  8681. }
  8682. /**
  8683. * Returns the distance between a point P on a segment AB.
  8684. *
  8685. * @private
  8686. * @param {Array<number>} p external point
  8687. * @param {Array<number>} a first segment point
  8688. * @param {Array<number>} b second segment point
  8689. * @param {Object} [options={}] Optional parameters
  8690. * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers
  8691. * @param {boolean} [options.mercator=false] if distance should be on Mercator or WGS84 projection
  8692. * @returns {number} distance
  8693. */
  8694. function distanceToSegment(p, a, b, options) {
  8695. var mercator = options.mercator;
  8696. var distanceAP = (mercator !== true) ? distance(a, p, options) : euclideanDistance(a, p, options);
  8697. var azimuthAP = bearingToAzimuth((mercator !== true) ? bearing(a, p) : rhumbBearing(a, p));
  8698. var azimuthAB = bearingToAzimuth((mercator !== true) ? bearing(a, b) : rhumbBearing(a, b));
  8699. var angleA = Math.abs(azimuthAP - azimuthAB);
  8700. // if (angleA > 180) angleA = Math.abs(angleA - 360);
  8701. // if the angle PAB is obtuse its projection on the line extending the segment falls outside the segment
  8702. // thus return distance between P and the start point A
  8703. /*
  8704. P__
  8705. |\ \____
  8706. | \ \____
  8707. | \ \____
  8708. | \_____________\
  8709. H A B
  8710. */
  8711. if (angleA > 90) return distanceAP;
  8712. var azimuthBA = (azimuthAB + 180) % 360;
  8713. var azimuthBP = bearingToAzimuth((mercator !== true) ? bearing(b, p) : rhumbBearing(b, p));
  8714. var angleB = Math.abs(azimuthBP - azimuthBA);
  8715. if (angleB > 180) angleB = Math.abs(angleB - 360);
  8716. // also if the angle ABP is acute the projection of P falls outside the segment, on the other side
  8717. // so return the distance between P and the end point B
  8718. /*
  8719. ____P
  8720. ____/ /|
  8721. ____/ / |
  8722. ____/ / |
  8723. /______________/ |
  8724. A B H
  8725. */
  8726. if (angleB > 90) return (mercator !== true) ? distance(p, b, options) : euclideanDistance(p, b, options);
  8727. // finally if the projection falls inside the segment
  8728. // return the distance between P and the segment
  8729. /*
  8730. P
  8731. __/|\
  8732. __/ | \
  8733. __/ | \
  8734. __/ | \
  8735. /____________|____\
  8736. A H B
  8737. */
  8738. if (mercator !== true) return distanceAP * Math.sin(degreesToRadians(angleA));
  8739. return mercatorPH(a, b, p, options);
  8740. }
  8741. /**
  8742. * Returns the distance between a point P on a segment AB, on Mercator projection
  8743. *
  8744. * @private
  8745. * @param {Array<number>} a first segment point
  8746. * @param {Array<number>} b second segment point
  8747. * @param {Array<number>} p external point
  8748. * @param {Object} [options={}] Optional parameters
  8749. * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers
  8750. * @returns {number} distance
  8751. */
  8752. function mercatorPH(a, b, p, options) {
  8753. var delta = 0;
  8754. // translate points if any is crossing the 180th meridian
  8755. if (Math.abs(a[0]) >= 180 || Math.abs(b[0]) >= 180 || Math.abs(p[0]) >= 180) {
  8756. delta = (a[0] > 0 || b[0] > 0 || p[0] > 0) ? -180 : 180;
  8757. }
  8758. var origin = point(p);
  8759. var A = toMercator([a[0] + delta, a[1]]);
  8760. var B = toMercator([b[0] + delta, b[1]]);
  8761. var P = toMercator([p[0] + delta, p[1]]);
  8762. var h = toWgs84(euclideanIntersection(A, B, P));
  8763. if (delta !== 0) h[0] -= delta; // translate back to original position
  8764. var distancePH = rhumbDistance(origin, h, options);
  8765. return distancePH;
  8766. }
  8767. /**
  8768. * Returns the point H projection of a point P on a segment AB, on the euclidean plain
  8769. * from https://stackoverflow.com/questions/10301001/perpendicular-on-a-line-segment-from-a-given-point#answer-12499474
  8770. * P
  8771. * |
  8772. * |
  8773. * _________|____
  8774. * A H B
  8775. *
  8776. * @private
  8777. * @param {Array<number>} a first segment point
  8778. * @param {Array<number>} b second segment point
  8779. * @param {Array<number>} p external point
  8780. * @returns {Array<number>} projected point
  8781. */
  8782. function euclideanIntersection(a, b, p) {
  8783. var x1 = a[0], y1 = a[1],
  8784. x2 = b[0], y2 = b[1],
  8785. x3 = p[0], y3 = p[1];
  8786. var px = x2 - x1, py = y2 - y1;
  8787. var dab = px * px + py * py;
  8788. var u = ((x3 - x1) * px + (y3 - y1) * py) / dab;
  8789. var x = x1 + u * px, y = y1 + u * py;
  8790. return [x, y]; // H
  8791. }
  8792. /**
  8793. * Returns euclidean distance between two points
  8794. *
  8795. * @private
  8796. * @param {Object} from first point
  8797. * @param {Object} to second point
  8798. * @param {Object} [options={}] Optional parameters
  8799. * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers
  8800. * @returns {number} squared distance
  8801. */
  8802. function euclideanDistance(from, to, options) {
  8803. var units = options.units;
  8804. // translate points if any is crossing the 180th meridian
  8805. var delta = 0;
  8806. if (Math.abs(from[0]) >= 180) {
  8807. delta = (from[0] > 0) ? -180 : 180;
  8808. }
  8809. if (Math.abs(to[0]) >= 180) {
  8810. delta = (to[0] > 0) ? -180 : 180;
  8811. }
  8812. var p1 = toMercator([from[0] + delta, from[1]]);
  8813. var p2 = toMercator([to[0] + delta, to[1]]);
  8814. var sqr = function (n) { return n * n; };
  8815. var squareD = sqr(p1[0] - p2[0]) + sqr(p1[1] - p2[1]);
  8816. var d = Math.sqrt(squareD);
  8817. return convertLength(d, 'meters', units);
  8818. }
  8819. /**
  8820. * Returns the closest {@link Point|point}, of a {@link FeatureCollection|collection} of points, to a {@link LineString|line}.
  8821. * The returned point has a `dist` property indicating its distance to the line.
  8822. *
  8823. * @name nearestPointToLine
  8824. * @param {FeatureCollection|GeometryCollection<Point>} points Point Collection
  8825. * @param {Feature|Geometry<LineString>} line Line Feature
  8826. * @param {Object} [options] Optional parameters
  8827. * @param {string} [options.units='kilometers'] unit of the output distance property, can be degrees, radians, miles, or kilometers
  8828. * @param {Object} [options.properties={}] Translate Properties to Point
  8829. * @returns {Feature<Point>} the closest point
  8830. * @example
  8831. * var pt1 = turf.point([0, 0]);
  8832. * var pt2 = turf.point([0.5, 0.5]);
  8833. * var points = turf.featureCollection([pt1, pt2]);
  8834. * var line = turf.lineString([[1,1], [-1,1]]);
  8835. *
  8836. * var nearest = turf.nearestPointToLine(points, line);
  8837. *
  8838. * //addToMap
  8839. * var addToMap = [nearest, line];
  8840. */
  8841. function nearestPointToLine(points$$1, line, options) {
  8842. options = options || {};
  8843. if (!isObject(options)) throw new Error('options is invalid');
  8844. var units = options.units;
  8845. var properties = options.properties || {};
  8846. // validation
  8847. if (!points$$1) throw new Error('points is required');
  8848. points$$1 = normalize(points$$1);
  8849. if (!points$$1.features.length) throw new Error('points must contain features');
  8850. if (!line) throw new Error('line is required');
  8851. if (getType(line) !== 'LineString') throw new Error('line must be a LineString');
  8852. var dist = Infinity;
  8853. var pt = null;
  8854. featureEach(points$$1, function (point$$1) {
  8855. var d = pointToLineDistance(point$$1, line, { units: units });
  8856. if (d < dist) {
  8857. dist = d;
  8858. pt = point$$1;
  8859. }
  8860. });
  8861. /**
  8862. * Translate Properties to final Point, priorities:
  8863. * 1. options.properties
  8864. * 2. inherent Point properties
  8865. * 3. dist custom properties created by NearestPointToLine
  8866. */
  8867. if (pt) pt.properties = Object.assign({dist: dist}, pt.properties, properties);
  8868. return pt;
  8869. }
  8870. /**
  8871. * Convert Collection to FeatureCollection
  8872. *
  8873. * @private
  8874. * @param {FeatureCollection|GeometryCollection<Point>} points Points
  8875. * @returns {FeatureCollection<Point>} points
  8876. */
  8877. function normalize(points$$1) {
  8878. var features = [];
  8879. var type = points$$1.geometry ? points$$1.geometry.type : points$$1.type;
  8880. switch (type) {
  8881. case 'GeometryCollection':
  8882. geomEach(points$$1, function (geom) {
  8883. if (geom.type === 'Point') features.push({type: 'Feature', properties: {}, geometry: geom});
  8884. });
  8885. return {type: 'FeatureCollection', features: features};
  8886. case 'FeatureCollection':
  8887. points$$1.features = points$$1.features.filter(function (feature$$1) {
  8888. return feature$$1.geometry.type === 'Point';
  8889. });
  8890. return points$$1;
  8891. default:
  8892. throw new Error('points must be a Point Collection');
  8893. }
  8894. }
  8895. /**
  8896. * Takes a triangular plane as a {@link Polygon}
  8897. * and a {@link Point} within that triangle and returns the z-value
  8898. * at that point. The Polygon should have properties `a`, `b`, and `c`
  8899. * that define the values at its three corners. Alternatively, the z-values
  8900. * of each triangle point can be provided by their respective 3rd coordinate
  8901. * if their values are not provided as properties.
  8902. *
  8903. * @name planepoint
  8904. * @param {Coord} point the Point for which a z-value will be calculated
  8905. * @param {Feature<Polygon>} triangle a Polygon feature with three vertices
  8906. * @returns {number} the z-value for `interpolatedPoint`
  8907. * @example
  8908. * var point = turf.point([-75.3221, 39.529]);
  8909. * // "a", "b", and "c" values represent the values of the coordinates in order.
  8910. * var triangle = turf.polygon([[
  8911. * [-75.1221, 39.57],
  8912. * [-75.58, 39.18],
  8913. * [-75.97, 39.86],
  8914. * [-75.1221, 39.57]
  8915. * ]], {
  8916. * "a": 11,
  8917. * "b": 122,
  8918. * "c": 44
  8919. * });
  8920. *
  8921. * var zValue = turf.planepoint(point, triangle);
  8922. * point.properties.zValue = zValue;
  8923. *
  8924. * //addToMap
  8925. * var addToMap = [triangle, point];
  8926. */
  8927. function planepoint(point, triangle) {
  8928. // Normalize input
  8929. var coord = getCoord(point);
  8930. var geom = getGeom(triangle);
  8931. var coords = geom.coordinates;
  8932. var outer = coords[0];
  8933. if (outer.length < 4) throw new Error('OuterRing of a Polygon must have 4 or more Positions.');
  8934. var properties = triangle.properties || {};
  8935. var a = properties.a;
  8936. var b = properties.b;
  8937. var c = properties.c;
  8938. // Planepoint
  8939. var x = coord[0];
  8940. var y = coord[1];
  8941. var x1 = outer[0][0];
  8942. var y1 = outer[0][1];
  8943. var z1 = (a !== undefined ? a : outer[0][2]);
  8944. var x2 = outer[1][0];
  8945. var y2 = outer[1][1];
  8946. var z2 = (b !== undefined ? b : outer[1][2]);
  8947. var x3 = outer[2][0];
  8948. var y3 = outer[2][1];
  8949. var z3 = (c !== undefined ? c : outer[2][2]);
  8950. var z = (z3 * (x - x1) * (y - y2) + z1 * (x - x2) * (y - y3) + z2 * (x - x3) * (y - y1) -
  8951. z2 * (x - x1) * (y - y3) - z3 * (x - x2) * (y - y1) - z1 * (x - x3) * (y - y2)) /
  8952. ((x - x1) * (y - y2) + (x - x2) * (y - y3) + (x - x3) * (y - y1) -
  8953. (x - x1) * (y - y3) - (x - x2) * (y - y1) - (x - x3) * (y - y2));
  8954. return z;
  8955. }
  8956. /**
  8957. * Takes a {@link LineString|linestring}, {@link MultiLineString|multi-linestring}, {@link MultiPolygon|multi-polygon}, or {@link Polygon|polygon} and returns {@link Point|points} at all self-intersections.
  8958. *
  8959. * @name kinks
  8960. * @param {Feature<LineString|MultiLineString|MultiPolygon|Polygon>} featureIn input feature
  8961. * @returns {FeatureCollection<Point>} self-intersections
  8962. * @example
  8963. * var poly = turf.polygon([[
  8964. * [-12.034835, 8.901183],
  8965. * [-12.060413, 8.899826],
  8966. * [-12.03638, 8.873199],
  8967. * [-12.059383, 8.871418],
  8968. * [-12.034835, 8.901183]
  8969. * ]]);
  8970. *
  8971. * var kinks = turf.kinks(poly);
  8972. *
  8973. * //addToMap
  8974. * var addToMap = [poly, kinks]
  8975. */
  8976. function kinks(featureIn) {
  8977. var coordinates;
  8978. var feature$$1;
  8979. var results = {
  8980. type: 'FeatureCollection',
  8981. features: []
  8982. };
  8983. if (featureIn.type === 'Feature') {
  8984. feature$$1 = featureIn.geometry;
  8985. } else {
  8986. feature$$1 = featureIn;
  8987. }
  8988. if (feature$$1.type === 'LineString') {
  8989. coordinates = [feature$$1.coordinates];
  8990. } else if (feature$$1.type === 'MultiLineString') {
  8991. coordinates = feature$$1.coordinates;
  8992. } else if (feature$$1.type === 'MultiPolygon') {
  8993. coordinates = [].concat.apply([], feature$$1.coordinates);
  8994. } else if (feature$$1.type === 'Polygon') {
  8995. coordinates = feature$$1.coordinates;
  8996. } else {
  8997. throw new Error('Input must be a LineString, MultiLineString, ' +
  8998. 'Polygon, or MultiPolygon Feature or Geometry');
  8999. }
  9000. coordinates.forEach(function (line1) {
  9001. coordinates.forEach(function (line2) {
  9002. for (var i = 0; i < line1.length - 1; i++) {
  9003. // start iteration at i, intersections for k < i have already been checked in previous outer loop iterations
  9004. for (var k = i; k < line2.length - 1; k++) {
  9005. if (line1 === line2) {
  9006. // segments are adjacent and always share a vertex, not a kink
  9007. if (Math.abs(i - k) === 1) {
  9008. continue;
  9009. }
  9010. // first and last segment in a closed lineString or ring always share a vertex, not a kink
  9011. if (
  9012. // segments are first and last segment of lineString
  9013. i === 0 &&
  9014. k === line1.length - 2 &&
  9015. // lineString is closed
  9016. line1[i][0] === line1[line1.length - 1][0] &&
  9017. line1[i][1] === line1[line1.length - 1][1]
  9018. ) {
  9019. continue;
  9020. }
  9021. }
  9022. var intersection = lineIntersects(line1[i][0], line1[i][1], line1[i + 1][0], line1[i + 1][1],
  9023. line2[k][0], line2[k][1], line2[k + 1][0], line2[k + 1][1]);
  9024. if (intersection) {
  9025. results.features.push(point([intersection[0], intersection[1]]));
  9026. }
  9027. }
  9028. }
  9029. });
  9030. });
  9031. return results;
  9032. }
  9033. // modified from http://jsfiddle.net/justin_c_rounds/Gd2S2/light/
  9034. function lineIntersects(line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY) {
  9035. // if the lines intersect, the result contains the x and y of the intersection (treating the lines as infinite) and booleans for whether line segment 1 or line segment 2 contain the point
  9036. var denominator, a, b, numerator1, numerator2,
  9037. result = {
  9038. x: null,
  9039. y: null,
  9040. onLine1: false,
  9041. onLine2: false
  9042. };
  9043. denominator = ((line2EndY - line2StartY) * (line1EndX - line1StartX)) - ((line2EndX - line2StartX) * (line1EndY - line1StartY));
  9044. if (denominator === 0) {
  9045. if (result.x !== null && result.y !== null) {
  9046. return result;
  9047. } else {
  9048. return false;
  9049. }
  9050. }
  9051. a = line1StartY - line2StartY;
  9052. b = line1StartX - line2StartX;
  9053. numerator1 = ((line2EndX - line2StartX) * a) - ((line2EndY - line2StartY) * b);
  9054. numerator2 = ((line1EndX - line1StartX) * a) - ((line1EndY - line1StartY) * b);
  9055. a = numerator1 / denominator;
  9056. b = numerator2 / denominator;
  9057. // if we cast these lines infinitely in both directions, they intersect here:
  9058. result.x = line1StartX + (a * (line1EndX - line1StartX));
  9059. result.y = line1StartY + (a * (line1EndY - line1StartY));
  9060. // if line1 is a segment and line2 is infinite, they intersect if:
  9061. if (a >= 0 && a <= 1) {
  9062. result.onLine1 = true;
  9063. }
  9064. // if line2 is a segment and line1 is infinite, they intersect if:
  9065. if (b >= 0 && b <= 1) {
  9066. result.onLine2 = true;
  9067. }
  9068. // if line1 and line2 are segments, they intersect if both of the above are true
  9069. if (result.onLine1 && result.onLine2) {
  9070. return [result.x, result.y];
  9071. } else {
  9072. return false;
  9073. }
  9074. }
  9075. /**
  9076. * Takes a Feature or FeatureCollection and returns a {@link Point} guaranteed to be on the surface of the feature.
  9077. *
  9078. * * Given a {@link Polygon}, the point will be in the area of the polygon
  9079. * * Given a {@link LineString}, the point will be along the string
  9080. * * Given a {@link Point}, the point will the same as the input
  9081. *
  9082. * @name pointOnFeature
  9083. * @param {GeoJSON} geojson any Feature or FeatureCollection
  9084. * @returns {Feature<Point>} a point on the surface of `input`
  9085. * @example
  9086. * var polygon = turf.polygon([[
  9087. * [116, -36],
  9088. * [131, -32],
  9089. * [146, -43],
  9090. * [155, -25],
  9091. * [133, -9],
  9092. * [111, -22],
  9093. * [116, -36]
  9094. * ]]);
  9095. *
  9096. * var pointOnPolygon = turf.pointOnFeature(polygon);
  9097. *
  9098. * //addToMap
  9099. * var addToMap = [polygon, pointOnPolygon];
  9100. */
  9101. function pointOnFeature(geojson) {
  9102. // normalize
  9103. var fc = normalize$1(geojson);
  9104. // get centroid
  9105. var cent = center(fc);
  9106. // check to see if centroid is on surface
  9107. var onSurface = false;
  9108. var i = 0;
  9109. while (!onSurface && i < fc.features.length) {
  9110. var geom = fc.features[i].geometry;
  9111. var x, y, x1, y1, x2, y2, k;
  9112. var onLine = false;
  9113. if (geom.type === 'Point') {
  9114. if (cent.geometry.coordinates[0] === geom.coordinates[0] &&
  9115. cent.geometry.coordinates[1] === geom.coordinates[1]) {
  9116. onSurface = true;
  9117. }
  9118. } else if (geom.type === 'MultiPoint') {
  9119. var onMultiPoint = false;
  9120. k = 0;
  9121. while (!onMultiPoint && k < geom.coordinates.length) {
  9122. if (cent.geometry.coordinates[0] === geom.coordinates[k][0] &&
  9123. cent.geometry.coordinates[1] === geom.coordinates[k][1]) {
  9124. onSurface = true;
  9125. onMultiPoint = true;
  9126. }
  9127. k++;
  9128. }
  9129. } else if (geom.type === 'LineString') {
  9130. k = 0;
  9131. while (!onLine && k < geom.coordinates.length - 1) {
  9132. x = cent.geometry.coordinates[0];
  9133. y = cent.geometry.coordinates[1];
  9134. x1 = geom.coordinates[k][0];
  9135. y1 = geom.coordinates[k][1];
  9136. x2 = geom.coordinates[k + 1][0];
  9137. y2 = geom.coordinates[k + 1][1];
  9138. if (pointOnSegment(x, y, x1, y1, x2, y2)) {
  9139. onLine = true;
  9140. onSurface = true;
  9141. }
  9142. k++;
  9143. }
  9144. } else if (geom.type === 'MultiLineString') {
  9145. var j = 0;
  9146. while (j < geom.coordinates.length) {
  9147. onLine = false;
  9148. k = 0;
  9149. var line = geom.coordinates[j];
  9150. while (!onLine && k < line.length - 1) {
  9151. x = cent.geometry.coordinates[0];
  9152. y = cent.geometry.coordinates[1];
  9153. x1 = line[k][0];
  9154. y1 = line[k][1];
  9155. x2 = line[k + 1][0];
  9156. y2 = line[k + 1][1];
  9157. if (pointOnSegment(x, y, x1, y1, x2, y2)) {
  9158. onLine = true;
  9159. onSurface = true;
  9160. }
  9161. k++;
  9162. }
  9163. j++;
  9164. }
  9165. } else if (geom.type === 'Polygon' || geom.type === 'MultiPolygon') {
  9166. if (booleanPointInPolygon(cent, geom)) {
  9167. onSurface = true;
  9168. }
  9169. }
  9170. i++;
  9171. }
  9172. if (onSurface) {
  9173. return cent;
  9174. } else {
  9175. var vertices = featureCollection([]);
  9176. for (i = 0; i < fc.features.length; i++) {
  9177. vertices.features = vertices.features.concat(explode(fc.features[i]).features);
  9178. }
  9179. // Remove distanceToPoint properties from nearestPoint()
  9180. return point(nearestPoint(cent, vertices).geometry.coordinates);
  9181. }
  9182. }
  9183. /**
  9184. * Normalizes any GeoJSON to a FeatureCollection
  9185. *
  9186. * @private
  9187. * @name normalize
  9188. * @param {GeoJSON} geojson Any GeoJSON
  9189. * @returns {FeatureCollection} FeatureCollection
  9190. */
  9191. function normalize$1(geojson) {
  9192. if (geojson.type !== 'FeatureCollection') {
  9193. if (geojson.type !== 'Feature') {
  9194. return featureCollection([feature(geojson)]);
  9195. }
  9196. return featureCollection([geojson]);
  9197. }
  9198. return geojson;
  9199. }
  9200. function pointOnSegment(x, y, x1, y1, x2, y2) {
  9201. var ab = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
  9202. var ap = Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
  9203. var pb = Math.sqrt((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y));
  9204. return ab === ap + pb;
  9205. }
  9206. /**
  9207. * Takes one or more features and returns their area in square meters.
  9208. *
  9209. * @name area
  9210. * @param {GeoJSON} geojson input GeoJSON feature(s)
  9211. * @returns {number} area in square meters
  9212. * @example
  9213. * var polygon = turf.polygon([[[125, -15], [113, -22], [154, -27], [144, -15], [125, -15]]]);
  9214. *
  9215. * var area = turf.area(polygon);
  9216. *
  9217. * //addToMap
  9218. * var addToMap = [polygon]
  9219. * polygon.properties.area = area
  9220. */
  9221. function area$1(geojson) {
  9222. return geomReduce(geojson, function (value, geom) {
  9223. return value + calculateArea(geom);
  9224. }, 0);
  9225. }
  9226. var RADIUS = 6378137;
  9227. // var FLATTENING_DENOM = 298.257223563;
  9228. // var FLATTENING = 1 / FLATTENING_DENOM;
  9229. // var POLAR_RADIUS = RADIUS * (1 - FLATTENING);
  9230. /**
  9231. * Calculate Area
  9232. *
  9233. * @private
  9234. * @param {GeoJSON} geojson GeoJSON
  9235. * @returns {number} area
  9236. */
  9237. function calculateArea(geojson) {
  9238. var area = 0, i;
  9239. switch (geojson.type) {
  9240. case 'Polygon':
  9241. return polygonArea(geojson.coordinates);
  9242. case 'MultiPolygon':
  9243. for (i = 0; i < geojson.coordinates.length; i++) {
  9244. area += polygonArea(geojson.coordinates[i]);
  9245. }
  9246. return area;
  9247. case 'Point':
  9248. case 'MultiPoint':
  9249. case 'LineString':
  9250. case 'MultiLineString':
  9251. return 0;
  9252. case 'GeometryCollection':
  9253. for (i = 0; i < geojson.geometries.length; i++) {
  9254. area += calculateArea(geojson.geometries[i]);
  9255. }
  9256. return area;
  9257. }
  9258. }
  9259. function polygonArea(coords) {
  9260. var area = 0;
  9261. if (coords && coords.length > 0) {
  9262. area += Math.abs(ringArea(coords[0]));
  9263. for (var i = 1; i < coords.length; i++) {
  9264. area -= Math.abs(ringArea(coords[i]));
  9265. }
  9266. }
  9267. return area;
  9268. }
  9269. /**
  9270. * @private
  9271. * Calculate the approximate area of the polygon were it projected onto the earth.
  9272. * Note that this area will be positive if ring is oriented clockwise, otherwise it will be negative.
  9273. *
  9274. * Reference:
  9275. * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
  9276. * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
  9277. *
  9278. * @param {Array<Array<number>>} coords Ring Coordinates
  9279. * @returns {number} The approximate signed geodesic area of the polygon in square meters.
  9280. */
  9281. function ringArea(coords) {
  9282. var p1;
  9283. var p2;
  9284. var p3;
  9285. var lowerIndex;
  9286. var middleIndex;
  9287. var upperIndex;
  9288. var i;
  9289. var area = 0;
  9290. var coordsLength = coords.length;
  9291. if (coordsLength > 2) {
  9292. for (i = 0; i < coordsLength; i++) {
  9293. if (i === coordsLength - 2) { // i = N-2
  9294. lowerIndex = coordsLength - 2;
  9295. middleIndex = coordsLength - 1;
  9296. upperIndex = 0;
  9297. } else if (i === coordsLength - 1) { // i = N-1
  9298. lowerIndex = coordsLength - 1;
  9299. middleIndex = 0;
  9300. upperIndex = 1;
  9301. } else { // i = 0 to N-3
  9302. lowerIndex = i;
  9303. middleIndex = i + 1;
  9304. upperIndex = i + 2;
  9305. }
  9306. p1 = coords[lowerIndex];
  9307. p2 = coords[middleIndex];
  9308. p3 = coords[upperIndex];
  9309. area += (rad(p3[0]) - rad(p1[0])) * Math.sin(rad(p2[1]));
  9310. }
  9311. area = area * RADIUS * RADIUS / 2;
  9312. }
  9313. return area;
  9314. }
  9315. function rad(_) {
  9316. return _ * Math.PI / 180;
  9317. }
  9318. /**
  9319. * Takes a {@link LineString} and returns a {@link Point} at a specified distance along the line.
  9320. *
  9321. * @name along
  9322. * @param {Feature<LineString>} line input line
  9323. * @param {number} distance distance along the line
  9324. * @param {Object} [options] Optional parameters
  9325. * @param {string} [options.units="kilometers"] can be degrees, radians, miles, or kilometers
  9326. * @returns {Feature<Point>} Point `distance` `units` along the line
  9327. * @example
  9328. * var line = turf.lineString([[-83, 30], [-84, 36], [-78, 41]]);
  9329. * var options = {units: 'miles'};
  9330. *
  9331. * var along = turf.along(line, 200, options);
  9332. *
  9333. * //addToMap
  9334. * var addToMap = [along, line]
  9335. */
  9336. function along(line, distance$$1, options) {
  9337. // Optional parameters
  9338. options = options || {};
  9339. if (!isObject(options)) throw new Error('options is invalid');
  9340. // Validation
  9341. var coords;
  9342. if (line.type === 'Feature') coords = line.geometry.coordinates;
  9343. else if (line.type === 'LineString') coords = line.coordinates;
  9344. else throw new Error('input must be a LineString Feature or Geometry');
  9345. if (!isNumber(distance$$1)) throw new Error('distance must be a number');
  9346. var travelled = 0;
  9347. for (var i = 0; i < coords.length; i++) {
  9348. if (distance$$1 >= travelled && i === coords.length - 1) break;
  9349. else if (travelled >= distance$$1) {
  9350. var overshot = distance$$1 - travelled;
  9351. if (!overshot) return point(coords[i]);
  9352. else {
  9353. var direction = bearing(coords[i], coords[i - 1]) - 180;
  9354. var interpolated = destination(coords[i], overshot, direction, options);
  9355. return interpolated;
  9356. }
  9357. } else {
  9358. travelled += distance(coords[i], coords[i + 1], options);
  9359. }
  9360. }
  9361. return point(coords[coords.length - 1]);
  9362. }
  9363. /**
  9364. * Takes a {@link GeoJSON} and measures its length in the specified units, {@link (Multi)Point}'s distance are ignored.
  9365. *
  9366. * @name length
  9367. * @param {GeoJSON} geojson GeoJSON to measure
  9368. * @param {Object} [options={}] Optional parameters
  9369. * @param {string} [options.units=kilometers] can be degrees, radians, miles, or kilometers
  9370. * @returns {number} length of GeoJSON
  9371. * @example
  9372. * var line = turf.lineString([[115, -32], [131, -22], [143, -25], [150, -34]]);
  9373. * var length = turf.length(line, {units: 'miles'});
  9374. *
  9375. * //addToMap
  9376. * var addToMap = [line];
  9377. * line.properties.distance = length;
  9378. */
  9379. function length(geojson, options) {
  9380. // Optional parameters
  9381. options = options || {};
  9382. if (!isObject(options)) throw new Error('options is invalid');
  9383. // Input Validation
  9384. if (!geojson) throw new Error('geojson is required');
  9385. // Calculate distance from 2-vertex line segements
  9386. return segmentReduce(geojson, function (previousValue, segment) {
  9387. var coords = segment.geometry.coordinates;
  9388. return previousValue + distance(coords[0], coords[1], options);
  9389. }, 0);
  9390. }
  9391. /**
  9392. * Takes a {@link LineString|line}, a start {@link Point}, and a stop point
  9393. * and returns a subsection of the line in-between those points.
  9394. * The start & stop points don't need to fall exactly on the line.
  9395. *
  9396. * This can be useful for extracting only the part of a route between waypoints.
  9397. *
  9398. * @name lineSlice
  9399. * @param {Coord} startPt starting point
  9400. * @param {Coord} stopPt stopping point
  9401. * @param {Feature<LineString>|LineString} line line to slice
  9402. * @returns {Feature<LineString>} sliced line
  9403. * @example
  9404. * var line = turf.lineString([
  9405. * [-77.031669, 38.878605],
  9406. * [-77.029609, 38.881946],
  9407. * [-77.020339, 38.884084],
  9408. * [-77.025661, 38.885821],
  9409. * [-77.021884, 38.889563],
  9410. * [-77.019824, 38.892368]
  9411. * ]);
  9412. * var start = turf.point([-77.029609, 38.881946]);
  9413. * var stop = turf.point([-77.021884, 38.889563]);
  9414. *
  9415. * var sliced = turf.lineSlice(start, stop, line);
  9416. *
  9417. * //addToMap
  9418. * var addToMap = [start, stop, line]
  9419. */
  9420. function lineSlice(startPt, stopPt, line) {
  9421. // Validation
  9422. var coords = getCoords(line);
  9423. if (getType(line) !== 'LineString') throw new Error('line must be a LineString');
  9424. var startVertex = nearestPointOnLine(line, startPt);
  9425. var stopVertex = nearestPointOnLine(line, stopPt);
  9426. var ends;
  9427. if (startVertex.properties.index <= stopVertex.properties.index) {
  9428. ends = [startVertex, stopVertex];
  9429. } else {
  9430. ends = [stopVertex, startVertex];
  9431. }
  9432. var clipCoords = [ends[0].geometry.coordinates];
  9433. for (var i = ends[0].properties.index + 1; i < ends[1].properties.index + 1; i++) {
  9434. clipCoords.push(coords[i]);
  9435. }
  9436. clipCoords.push(ends[1].geometry.coordinates);
  9437. return lineString(clipCoords, line.properties);
  9438. }
  9439. /**
  9440. * Takes a {@link LineString|line}, a specified distance along the line to a start {@link Point},
  9441. * and a specified distance along the line to a stop point
  9442. * and returns a subsection of the line in-between those points.
  9443. *
  9444. * This can be useful for extracting only the part of a route between two distances.
  9445. *
  9446. * @name lineSliceAlong
  9447. * @param {Feature<LineString>|LineString} line input line
  9448. * @param {number} startDist distance along the line to starting point
  9449. * @param {number} stopDist distance along the line to ending point
  9450. * @param {Object} [options={}] Optional parameters
  9451. * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers
  9452. * @returns {Feature<LineString>} sliced line
  9453. * @example
  9454. * var line = turf.lineString([[7, 45], [9, 45], [14, 40], [14, 41]]);
  9455. * var start = 12.5;
  9456. * var stop = 25;
  9457. * var sliced = turf.lineSliceAlong(line, start, stop, {units: 'miles'});
  9458. *
  9459. * //addToMap
  9460. * var addToMap = [line, start, stop, sliced]
  9461. */
  9462. function lineSliceAlong(line, startDist, stopDist, options) {
  9463. // Optional parameters
  9464. options = options || {};
  9465. if (!isObject(options)) throw new Error('options is invalid');
  9466. var coords;
  9467. var slice = [];
  9468. // Validation
  9469. if (line.type === 'Feature') coords = line.geometry.coordinates;
  9470. else if (line.type === 'LineString') coords = line.coordinates;
  9471. else throw new Error('input must be a LineString Feature or Geometry');
  9472. var travelled = 0;
  9473. var overshot, direction, interpolated;
  9474. for (var i = 0; i < coords.length; i++) {
  9475. if (startDist >= travelled && i === coords.length - 1) break;
  9476. else if (travelled > startDist && slice.length === 0) {
  9477. overshot = startDist - travelled;
  9478. if (!overshot) {
  9479. slice.push(coords[i]);
  9480. return lineString(slice);
  9481. }
  9482. direction = bearing(coords[i], coords[i - 1]) - 180;
  9483. interpolated = destination(coords[i], overshot, direction, options);
  9484. slice.push(interpolated.geometry.coordinates);
  9485. }
  9486. if (travelled >= stopDist) {
  9487. overshot = stopDist - travelled;
  9488. if (!overshot) {
  9489. slice.push(coords[i]);
  9490. return lineString(slice);
  9491. }
  9492. direction = bearing(coords[i], coords[i - 1]) - 180;
  9493. interpolated = destination(coords[i], overshot, direction, options);
  9494. slice.push(interpolated.geometry.coordinates);
  9495. return lineString(slice);
  9496. }
  9497. if (travelled >= startDist) {
  9498. slice.push(coords[i]);
  9499. }
  9500. if (i === coords.length - 1) {
  9501. return lineString(slice);
  9502. }
  9503. travelled += distance(coords[i], coords[i + 1], options);
  9504. }
  9505. return lineString(coords[coords.length - 1]);
  9506. }
  9507. /**
  9508. * Returns true if a point is on a line. Accepts a optional parameter to ignore the start and end vertices of the linestring.
  9509. *
  9510. * @name booleanPointOnLine
  9511. * @param {Coord} pt GeoJSON Point
  9512. * @param {Feature<LineString>} line GeoJSON LineString
  9513. * @param {Object} [options={}] Optional parameters
  9514. * @param {boolean} [options.ignoreEndVertices=false] whether to ignore the start and end vertices.
  9515. * @returns {boolean} true/false
  9516. * @example
  9517. * var pt = turf.point([0, 0]);
  9518. * var line = turf.lineString([[-1, -1],[1, 1],[1.5, 2.2]]);
  9519. * var isPointOnLine = turf.booleanPointOnLine(pt, line);
  9520. * //=true
  9521. */
  9522. function booleanPointOnLine(pt, line, options) {
  9523. // Optional parameters
  9524. options = options || {};
  9525. var ignoreEndVertices = options.ignoreEndVertices;
  9526. if (!isObject(options)) throw new Error('invalid options');
  9527. // Validate input
  9528. if (!pt) throw new Error('pt is required');
  9529. if (!line) throw new Error('line is required');
  9530. // Normalize inputs
  9531. var ptCoords = getCoord(pt);
  9532. var lineCoords = getCoords(line);
  9533. // Main
  9534. for (var i = 0; i < lineCoords.length - 1; i++) {
  9535. var ignoreBoundary = false;
  9536. if (ignoreEndVertices) {
  9537. if (i === 0) ignoreBoundary = 'start';
  9538. if (i === lineCoords.length - 2) ignoreBoundary = 'end';
  9539. if (i === 0 && i + 1 === lineCoords.length - 1) ignoreBoundary = 'both';
  9540. }
  9541. if (isPointOnLineSegment$1(lineCoords[i], lineCoords[i + 1], ptCoords, ignoreBoundary)) return true;
  9542. }
  9543. return false;
  9544. }
  9545. // See http://stackoverflow.com/a/4833823/1979085
  9546. /**
  9547. * @private
  9548. * @param {Position} lineSegmentStart coord pair of start of line
  9549. * @param {Position} lineSegmentEnd coord pair of end of line
  9550. * @param {Position} pt coord pair of point to check
  9551. * @param {boolean|string} excludeBoundary whether the point is allowed to fall on the line ends. If true which end to ignore.
  9552. * @returns {boolean} true/false
  9553. */
  9554. function isPointOnLineSegment$1(lineSegmentStart, lineSegmentEnd, pt, excludeBoundary) {
  9555. var x = pt[0];
  9556. var y = pt[1];
  9557. var x1 = lineSegmentStart[0];
  9558. var y1 = lineSegmentStart[1];
  9559. var x2 = lineSegmentEnd[0];
  9560. var y2 = lineSegmentEnd[1];
  9561. var dxc = pt[0] - x1;
  9562. var dyc = pt[1] - y1;
  9563. var dxl = x2 - x1;
  9564. var dyl = y2 - y1;
  9565. var cross = dxc * dyl - dyc * dxl;
  9566. if (cross !== 0) {
  9567. return false;
  9568. }
  9569. if (!excludeBoundary) {
  9570. if (Math.abs(dxl) >= Math.abs(dyl)) {
  9571. return dxl > 0 ? x1 <= x && x <= x2 : x2 <= x && x <= x1;
  9572. }
  9573. return dyl > 0 ? y1 <= y && y <= y2 : y2 <= y && y <= y1;
  9574. } else if (excludeBoundary === 'start') {
  9575. if (Math.abs(dxl) >= Math.abs(dyl)) {
  9576. return dxl > 0 ? x1 < x && x <= x2 : x2 <= x && x < x1;
  9577. }
  9578. return dyl > 0 ? y1 < y && y <= y2 : y2 <= y && y < y1;
  9579. } else if (excludeBoundary === 'end') {
  9580. if (Math.abs(dxl) >= Math.abs(dyl)) {
  9581. return dxl > 0 ? x1 <= x && x < x2 : x2 < x && x <= x1;
  9582. }
  9583. return dyl > 0 ? y1 <= y && y < y2 : y2 < y && y <= y1;
  9584. } else if (excludeBoundary === 'both') {
  9585. if (Math.abs(dxl) >= Math.abs(dyl)) {
  9586. return dxl > 0 ? x1 < x && x < x2 : x2 < x && x < x1;
  9587. }
  9588. return dyl > 0 ? y1 < y && y < y2 : y2 < y && y < y1;
  9589. }
  9590. }
  9591. /**
  9592. * Boolean-within returns true if the first geometry is completely within the second geometry.
  9593. * The interiors of both geometries must intersect and, the interior and boundary of the primary (geometry a)
  9594. * must not intersect the exterior of the secondary (geometry b).
  9595. * Boolean-within returns the exact opposite result of the `@turf/boolean-contains`.
  9596. *
  9597. * @name booleanWithin
  9598. * @param {Geometry|Feature<any>} feature1 GeoJSON Feature or Geometry
  9599. * @param {Geometry|Feature<any>} feature2 GeoJSON Feature or Geometry
  9600. * @returns {boolean} true/false
  9601. * @example
  9602. * var line = turf.lineString([[1, 1], [1, 2], [1, 3], [1, 4]]);
  9603. * var point = turf.point([1, 2]);
  9604. *
  9605. * turf.booleanWithin(point, line);
  9606. * //=true
  9607. */
  9608. function booleanWithin(feature1, feature2) {
  9609. var type1 = getType(feature1);
  9610. var type2 = getType(feature2);
  9611. var geom1 = getGeom(feature1);
  9612. var geom2 = getGeom(feature2);
  9613. switch (type1) {
  9614. case 'Point':
  9615. switch (type2) {
  9616. case 'MultiPoint':
  9617. return isPointInMultiPoint(geom1, geom2);
  9618. case 'LineString':
  9619. return booleanPointOnLine(geom1, geom2, {ignoreEndVertices: true});
  9620. case 'Polygon':
  9621. return booleanPointInPolygon(geom1, geom2, {ignoreBoundary: true});
  9622. default:
  9623. throw new Error('feature2 ' + type2 + ' geometry not supported');
  9624. }
  9625. case 'MultiPoint':
  9626. switch (type2) {
  9627. case 'MultiPoint':
  9628. return isMultiPointInMultiPoint(geom1, geom2);
  9629. case 'LineString':
  9630. return isMultiPointOnLine(geom1, geom2);
  9631. case 'Polygon':
  9632. return isMultiPointInPoly(geom1, geom2);
  9633. default:
  9634. throw new Error('feature2 ' + type2 + ' geometry not supported');
  9635. }
  9636. case 'LineString':
  9637. switch (type2) {
  9638. case 'LineString':
  9639. return isLineOnLine(geom1, geom2);
  9640. case 'Polygon':
  9641. return isLineInPoly(geom1, geom2);
  9642. default:
  9643. throw new Error('feature2 ' + type2 + ' geometry not supported');
  9644. }
  9645. case 'Polygon':
  9646. switch (type2) {
  9647. case 'Polygon':
  9648. return isPolyInPoly(geom1, geom2);
  9649. default:
  9650. throw new Error('feature2 ' + type2 + ' geometry not supported');
  9651. }
  9652. default:
  9653. throw new Error('feature1 ' + type1 + ' geometry not supported');
  9654. }
  9655. }
  9656. function isPointInMultiPoint(point, multiPoint) {
  9657. var i;
  9658. var output = false;
  9659. for (i = 0; i < multiPoint.coordinates.length; i++) {
  9660. if (compareCoords(multiPoint.coordinates[i], point.coordinates)) {
  9661. output = true;
  9662. break;
  9663. }
  9664. }
  9665. return output;
  9666. }
  9667. function isMultiPointInMultiPoint(multiPoint1, multiPoint2) {
  9668. for (var i = 0; i < multiPoint1.coordinates.length; i++) {
  9669. var anyMatch = false;
  9670. for (var i2 = 0; i2 < multiPoint2.coordinates.length; i2++) {
  9671. if (compareCoords(multiPoint1.coordinates[i], multiPoint2.coordinates[i2])) {
  9672. anyMatch = true;
  9673. }
  9674. }
  9675. if (!anyMatch) {
  9676. return false;
  9677. }
  9678. }
  9679. return true;
  9680. }
  9681. function isMultiPointOnLine(multiPoint, lineString) {
  9682. var foundInsidePoint = false;
  9683. for (var i = 0; i < multiPoint.coordinates.length; i++) {
  9684. if (!booleanPointOnLine(multiPoint.coordinates[i], lineString)) {
  9685. return false;
  9686. }
  9687. if (!foundInsidePoint) {
  9688. foundInsidePoint = booleanPointOnLine(multiPoint.coordinates[i], lineString, {ignoreEndVertices: true});
  9689. }
  9690. }
  9691. return foundInsidePoint;
  9692. }
  9693. function isMultiPointInPoly(multiPoint, polygon) {
  9694. var output = true;
  9695. var oneInside = false;
  9696. for (var i = 0; i < multiPoint.coordinates.length; i++) {
  9697. var isInside = booleanPointInPolygon(multiPoint.coordinates[1], polygon);
  9698. if (!isInside) {
  9699. output = false;
  9700. break;
  9701. }
  9702. if (!oneInside) {
  9703. isInside = booleanPointInPolygon(multiPoint.coordinates[1], polygon, {ignoreBoundary: true});
  9704. }
  9705. }
  9706. return output && isInside;
  9707. }
  9708. function isLineOnLine(lineString1, lineString2) {
  9709. for (var i = 0; i < lineString1.coordinates.length; i++) {
  9710. if (!booleanPointOnLine(lineString1.coordinates[i], lineString2)) {
  9711. return false;
  9712. }
  9713. }
  9714. return true;
  9715. }
  9716. function isLineInPoly(linestring, polygon) {
  9717. var polyBbox = bbox(polygon);
  9718. var lineBbox = bbox(linestring);
  9719. if (!doBBoxOverlap(polyBbox, lineBbox)) {
  9720. return false;
  9721. }
  9722. var foundInsidePoint = false;
  9723. for (var i = 0; i < linestring.coordinates.length - 1; i++) {
  9724. if (!booleanPointInPolygon(linestring.coordinates[i], polygon)) {
  9725. return false;
  9726. }
  9727. if (!foundInsidePoint) {
  9728. foundInsidePoint = booleanPointInPolygon(linestring.coordinates[i], polygon, {ignoreBoundary: true});
  9729. }
  9730. if (!foundInsidePoint) {
  9731. var midpoint = getMidpoint(linestring.coordinates[i], linestring.coordinates[i + 1]);
  9732. foundInsidePoint = booleanPointInPolygon(midpoint, polygon, {ignoreBoundary: true});
  9733. }
  9734. }
  9735. return foundInsidePoint;
  9736. }
  9737. /**
  9738. * Is Polygon2 in Polygon1
  9739. * Only takes into account outer rings
  9740. *
  9741. * @private
  9742. * @param {Geometry|Feature<Polygon>} feature1 Polygon1
  9743. * @param {Geometry|Feature<Polygon>} feature2 Polygon2
  9744. * @returns {boolean} true/false
  9745. */
  9746. function isPolyInPoly(feature1, feature2) {
  9747. var poly1Bbox = bbox(feature1);
  9748. var poly2Bbox = bbox(feature2);
  9749. if (!doBBoxOverlap(poly2Bbox, poly1Bbox)) {
  9750. return false;
  9751. }
  9752. for (var i = 0; i < feature1.coordinates[0].length; i++) {
  9753. if (!booleanPointInPolygon(feature1.coordinates[0][i], feature2)) {
  9754. return false;
  9755. }
  9756. }
  9757. return true;
  9758. }
  9759. function doBBoxOverlap(bbox1, bbox2) {
  9760. if (bbox1[0] > bbox2[0]) return false;
  9761. if (bbox1[2] < bbox2[2]) return false;
  9762. if (bbox1[1] > bbox2[1]) return false;
  9763. if (bbox1[3] < bbox2[3]) return false;
  9764. return true;
  9765. }
  9766. /**
  9767. * compareCoords
  9768. *
  9769. * @private
  9770. * @param {Position} pair1 point [x,y]
  9771. * @param {Position} pair2 point [x,y]
  9772. * @returns {boolean} true/false if coord pairs match
  9773. */
  9774. function compareCoords(pair1, pair2) {
  9775. return pair1[0] === pair2[0] && pair1[1] === pair2[1];
  9776. }
  9777. /**
  9778. * getMidpoint
  9779. *
  9780. * @private
  9781. * @param {Position} pair1 point [x,y]
  9782. * @param {Position} pair2 point [x,y]
  9783. * @returns {Position} midpoint of pair1 and pair2
  9784. */
  9785. function getMidpoint(pair1, pair2) {
  9786. return [(pair1[0] + pair2[0]) / 2, (pair1[1] + pair2[1]) / 2];
  9787. }
  9788. /**
  9789. * Creates a {@link Point} grid from a bounding box, {@link FeatureCollection} or {@link Feature}.
  9790. *
  9791. * @name pointGrid
  9792. * @param {Array<number>} bbox extent in [minX, minY, maxX, maxY] order
  9793. * @param {number} cellSide the distance between points, in units
  9794. * @param {Object} [options={}] Optional parameters
  9795. * @param {string} [options.units='kilometers'] used in calculating cellSide, can be degrees, radians, miles, or kilometers
  9796. * @param {Feature<Polygon|MultiPolygon>} [options.mask] if passed a Polygon or MultiPolygon, the grid Points will be created only inside it
  9797. * @param {Object} [options.properties={}] passed to each point of the grid
  9798. * @returns {FeatureCollection<Point>} grid of points
  9799. * @example
  9800. * var extent = [-70.823364, -33.553984, -70.473175, -33.302986];
  9801. * var cellSide = 3;
  9802. * var options = {units: 'miles'};
  9803. *
  9804. * var grid = turf.pointGrid(extent, cellSide, options);
  9805. *
  9806. * //addToMap
  9807. * var addToMap = [grid];
  9808. */
  9809. function pointGrid(bbox, cellSide, options) {
  9810. // Optional parameters
  9811. options = options || {};
  9812. if (!isObject(options)) throw new Error('options is invalid');
  9813. // var units = options.units;
  9814. var mask = options.mask;
  9815. var properties = options.properties;
  9816. // Containers
  9817. var results = [];
  9818. // Input Validation
  9819. if (cellSide === null || cellSide === undefined) throw new Error('cellSide is required');
  9820. if (!isNumber(cellSide)) throw new Error('cellSide is invalid');
  9821. if (!bbox) throw new Error('bbox is required');
  9822. if (!Array.isArray(bbox)) throw new Error('bbox must be array');
  9823. if (bbox.length !== 4) throw new Error('bbox must contain 4 numbers');
  9824. if (mask && ['Polygon', 'MultiPolygon'].indexOf(getType(mask)) === -1) throw new Error('options.mask must be a (Multi)Polygon');
  9825. var west = bbox[0];
  9826. var south = bbox[1];
  9827. var east = bbox[2];
  9828. var north = bbox[3];
  9829. var xFraction = cellSide / (distance([west, south], [east, south], options));
  9830. var cellWidth = xFraction * (east - west);
  9831. var yFraction = cellSide / (distance([west, south], [west, north], options));
  9832. var cellHeight = yFraction * (north - south);
  9833. var bboxWidth = (east - west);
  9834. var bboxHeight = (north - south);
  9835. var columns = Math.floor(bboxWidth / cellWidth);
  9836. var rows = Math.floor(bboxHeight / cellHeight);
  9837. // adjust origin of the grid
  9838. var deltaX = (bboxWidth - columns * cellWidth) / 2;
  9839. var deltaY = (bboxHeight - rows * cellHeight) / 2;
  9840. var currentX = west + deltaX;
  9841. while (currentX <= east) {
  9842. var currentY = south + deltaY;
  9843. while (currentY <= north) {
  9844. var cellPt = point([currentX, currentY], properties);
  9845. if (mask) {
  9846. if (booleanWithin(cellPt, mask)) results.push(cellPt);
  9847. } else {
  9848. results.push(cellPt);
  9849. }
  9850. currentY += cellHeight;
  9851. }
  9852. currentX += cellWidth;
  9853. }
  9854. return featureCollection(results);
  9855. }
  9856. /**
  9857. * Takes a GeoJSON Feature or FeatureCollection and truncates the precision of the geometry.
  9858. *
  9859. * @name truncate
  9860. * @param {GeoJSON} geojson any GeoJSON Feature, FeatureCollection, Geometry or GeometryCollection.
  9861. * @param {Object} [options={}] Optional parameters
  9862. * @param {number} [options.precision=6] coordinate decimal precision
  9863. * @param {number} [options.coordinates=3] maximum number of coordinates (primarly used to remove z coordinates)
  9864. * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
  9865. * @returns {GeoJSON} layer with truncated geometry
  9866. * @example
  9867. * var point = turf.point([
  9868. * 70.46923055566859,
  9869. * 58.11088890802906,
  9870. * 1508
  9871. * ]);
  9872. * var options = {precision: 3, coordinates: 2};
  9873. * var truncated = turf.truncate(point, options);
  9874. * //=truncated.geometry.coordinates => [70.469, 58.111]
  9875. *
  9876. * //addToMap
  9877. * var addToMap = [truncated];
  9878. */
  9879. function truncate(geojson, options) {
  9880. // Optional parameters
  9881. options = options || {};
  9882. if (!isObject(options)) throw new Error('options is invalid');
  9883. var precision = options.precision;
  9884. var coordinates = options.coordinates;
  9885. var mutate = options.mutate;
  9886. // default params
  9887. precision = (precision === undefined || precision === null || isNaN(precision)) ? 6 : precision;
  9888. coordinates = (coordinates === undefined || coordinates === null || isNaN(coordinates)) ? 3 : coordinates;
  9889. // validation
  9890. if (!geojson) throw new Error('<geojson> is required');
  9891. if (typeof precision !== 'number') throw new Error('<precision> must be a number');
  9892. if (typeof coordinates !== 'number') throw new Error('<coordinates> must be a number');
  9893. // prevent input mutation
  9894. if (mutate === false || mutate === undefined) geojson = JSON.parse(JSON.stringify(geojson));
  9895. var factor = Math.pow(10, precision);
  9896. // Truncate Coordinates
  9897. coordEach(geojson, function (coords) {
  9898. truncateCoords(coords, factor, coordinates);
  9899. });
  9900. return geojson;
  9901. }
  9902. /**
  9903. * Truncate Coordinates - Mutates coordinates in place
  9904. *
  9905. * @private
  9906. * @param {Array<any>} coords Geometry Coordinates
  9907. * @param {number} factor rounding factor for coordinate decimal precision
  9908. * @param {number} coordinates maximum number of coordinates (primarly used to remove z coordinates)
  9909. * @returns {Array<any>} mutated coordinates
  9910. */
  9911. function truncateCoords(coords, factor, coordinates) {
  9912. // Remove extra coordinates (usually elevation coordinates and more)
  9913. if (coords.length > coordinates) coords.splice(coordinates, coords.length);
  9914. // Truncate coordinate decimals
  9915. for (var i = 0; i < coords.length; i++) {
  9916. coords[i] = Math.round(coords[i] * factor) / factor;
  9917. }
  9918. return coords;
  9919. }
  9920. /**
  9921. * Flattens any {@link GeoJSON} to a {@link FeatureCollection} inspired by [geojson-flatten](https://github.com/tmcw/geojson-flatten).
  9922. *
  9923. * @name flatten
  9924. * @param {GeoJSON} geojson any valid GeoJSON Object
  9925. * @returns {FeatureCollection<any>} all Multi-Geometries are flattened into single Features
  9926. * @example
  9927. * var multiGeometry = turf.multiPolygon([
  9928. * [[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]]],
  9929. * [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]],
  9930. * [[100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2]]]
  9931. * ]);
  9932. *
  9933. * var flatten = turf.flatten(multiGeometry);
  9934. *
  9935. * //addToMap
  9936. * var addToMap = [flatten]
  9937. */
  9938. function flatten(geojson) {
  9939. if (!geojson) throw new Error('geojson is required');
  9940. var results = [];
  9941. flattenEach(geojson, function (feature$$1) {
  9942. results.push(feature$$1);
  9943. });
  9944. return featureCollection(results);
  9945. }
  9946. /**
  9947. * Divides a {@link LineString} into chunks of a specified length.
  9948. * If the line is shorter than the segment length then the original line is returned.
  9949. *
  9950. * @name lineChunk
  9951. * @param {FeatureCollection|Geometry|Feature<LineString|MultiLineString>} geojson the lines to split
  9952. * @param {number} segmentLength how long to make each segment
  9953. * @param {Object} [options={}] Optional parameters
  9954. * @param {string} [options.units='kilometers'] units can be degrees, radians, miles, or kilometers
  9955. * @param {boolean} [options.reverse=false] reverses coordinates to start the first chunked segment at the end
  9956. * @returns {FeatureCollection<LineString>} collection of line segments
  9957. * @example
  9958. * var line = turf.lineString([[-95, 40], [-93, 45], [-85, 50]]);
  9959. *
  9960. * var chunk = turf.lineChunk(line, 15, {units: 'miles'});
  9961. *
  9962. * //addToMap
  9963. * var addToMap = [chunk];
  9964. */
  9965. function lineChunk(geojson, segmentLength, options) {
  9966. // Optional parameters
  9967. options = options || {};
  9968. if (!isObject(options)) throw new Error('options is invalid');
  9969. var units = options.units;
  9970. var reverse = options.reverse;
  9971. // Validation
  9972. if (!geojson) throw new Error('geojson is required');
  9973. if (segmentLength <= 0) throw new Error('segmentLength must be greater than 0');
  9974. // Container
  9975. var results = [];
  9976. // Flatten each feature to simple LineString
  9977. flattenEach(geojson, function (feature$$1) {
  9978. // reverses coordinates to start the first chunked segment at the end
  9979. if (reverse) feature$$1.geometry.coordinates = feature$$1.geometry.coordinates.reverse();
  9980. sliceLineSegments(feature$$1, segmentLength, units, function (segment) {
  9981. results.push(segment);
  9982. });
  9983. });
  9984. return featureCollection(results);
  9985. }
  9986. /**
  9987. * Slice Line Segments
  9988. *
  9989. * @private
  9990. * @param {Feature<LineString>} line GeoJSON LineString
  9991. * @param {number} segmentLength how long to make each segment
  9992. * @param {string}[units='kilometers'] units can be degrees, radians, miles, or kilometers
  9993. * @param {Function} callback iterate over sliced line segments
  9994. * @returns {void}
  9995. */
  9996. function sliceLineSegments(line, segmentLength, units, callback) {
  9997. var lineLength = length(line, {units: units});
  9998. // If the line is shorter than the segment length then the orginal line is returned.
  9999. if (lineLength <= segmentLength) return callback(line);
  10000. var numberOfSegments = lineLength / segmentLength;
  10001. // If numberOfSegments is integer, no need to plus 1
  10002. if (!Number.isInteger(numberOfSegments)) {
  10003. numberOfSegments = Math.floor(numberOfSegments) + 1;
  10004. }
  10005. for (var i = 0; i < numberOfSegments; i++) {
  10006. var outline = lineSliceAlong(line, segmentLength * i, segmentLength * (i + 1), {units: units});
  10007. callback(outline, i);
  10008. }
  10009. }
  10010. // Find self-intersections in geojson polygon (possibly with interior rings)
  10011. var isects = function (feature$$1, filterFn, useSpatialIndex) {
  10012. if (feature$$1.geometry.type !== 'Polygon') throw new Error('The input feature must be a Polygon');
  10013. if (useSpatialIndex === undefined) useSpatialIndex = 1;
  10014. var coord = feature$$1.geometry.coordinates;
  10015. var output = [];
  10016. var seen = {};
  10017. if (useSpatialIndex) {
  10018. var allEdgesAsRbushTreeItems = [];
  10019. for (var ring0 = 0; ring0 < coord.length; ring0++) {
  10020. for (var edge0 = 0; edge0 < coord[ring0].length - 1; edge0++) {
  10021. allEdgesAsRbushTreeItems.push(rbushTreeItem(ring0, edge0));
  10022. }
  10023. }
  10024. var tree = rbush_1();
  10025. tree.load(allEdgesAsRbushTreeItems);
  10026. }
  10027. for (var ringA = 0; ringA < coord.length; ringA++) {
  10028. for (var edgeA = 0; edgeA < coord[ringA].length - 1; edgeA++) {
  10029. if (useSpatialIndex) {
  10030. var bboxOverlaps = tree.search(rbushTreeItem(ringA, edgeA));
  10031. bboxOverlaps.forEach(function (bboxIsect) {
  10032. var ring1 = bboxIsect.ring;
  10033. var edge1 = bboxIsect.edge;
  10034. ifIsectAddToOutput(ringA, edgeA, ring1, edge1);
  10035. });
  10036. } else {
  10037. for (var ring1 = 0; ring1 < coord.length; ring1++) {
  10038. for (var edge1 = 0; edge1 < coord[ring1].length - 1; edge1++) {
  10039. // TODO: speedup possible if only interested in unique: start last two loops at ringA and edgeA+1
  10040. ifIsectAddToOutput(ringA, edgeA, ring1, edge1);
  10041. }
  10042. }
  10043. }
  10044. }
  10045. }
  10046. if (!filterFn) output = {type: 'Feature', geometry: {type: 'MultiPoint', coordinates: output}};
  10047. return output;
  10048. // Function to check if two edges intersect and add the intersection to the output
  10049. function ifIsectAddToOutput(ring0, edge0, ring1, edge1) {
  10050. var start0 = coord[ring0][edge0];
  10051. var end0 = coord[ring0][edge0 + 1];
  10052. var start1 = coord[ring1][edge1];
  10053. var end1 = coord[ring1][edge1 + 1];
  10054. var isect = intersect(start0, end0, start1, end1);
  10055. if (isect === null) return; // discard parallels and coincidence
  10056. var frac0;
  10057. var frac1;
  10058. if (end0[0] !== start0[0]) {
  10059. frac0 = (isect[0] - start0[0]) / (end0[0] - start0[0]);
  10060. } else {
  10061. frac0 = (isect[1] - start0[1]) / (end0[1] - start0[1]);
  10062. }
  10063. if (end1[0] !== start1[0]) {
  10064. frac1 = (isect[0] - start1[0]) / (end1[0] - start1[0]);
  10065. } else {
  10066. frac1 = (isect[1] - start1[1]) / (end1[1] - start1[1]);
  10067. }
  10068. if (frac0 >= 1 || frac0 <= 0 || frac1 >= 1 || frac1 <= 0) return; // require segment intersection
  10069. var key = isect;
  10070. var unique = !seen[key];
  10071. if (unique) {
  10072. seen[key] = true;
  10073. }
  10074. if (filterFn) {
  10075. output.push(filterFn(isect, ring0, edge0, start0, end0, frac0, ring1, edge1, start1, end1, frac1, unique));
  10076. } else {
  10077. output.push(isect);
  10078. }
  10079. }
  10080. // Function to return a rbush tree item given an ring and edge number
  10081. function rbushTreeItem(ring, edge) {
  10082. var start = coord[ring][edge];
  10083. var end = coord[ring][edge + 1];
  10084. var minX;
  10085. var maxX;
  10086. var minY;
  10087. var maxY;
  10088. if (start[0] < end[0]) {
  10089. minX = start[0];
  10090. maxX = end[0];
  10091. } else {
  10092. minX = end[0];
  10093. maxX = start[0];
  10094. }
  10095. if (start[1] < end[1]) {
  10096. minY = start[1];
  10097. maxY = end[1];
  10098. } else {
  10099. minY = end[1];
  10100. maxY = start[1];
  10101. }
  10102. return {minX: minX, minY: minY, maxX: maxX, maxY: maxY, ring: ring, edge: edge};
  10103. }
  10104. };
  10105. // Function to compute where two lines (not segments) intersect. From https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
  10106. function intersect(start0, end0, start1, end1) {
  10107. if (equalArrays$1(start0, start1) || equalArrays$1(start0, end1) || equalArrays$1(end0, start1) || equalArrays$1(end1, start1)) return null;
  10108. var x0 = start0[0],
  10109. y0 = start0[1],
  10110. x1 = end0[0],
  10111. y1 = end0[1],
  10112. x2 = start1[0],
  10113. y2 = start1[1],
  10114. x3 = end1[0],
  10115. y3 = end1[1];
  10116. var denom = (x0 - x1) * (y2 - y3) - (y0 - y1) * (x2 - x3);
  10117. if (denom === 0) return null;
  10118. var x4 = ((x0 * y1 - y0 * x1) * (x2 - x3) - (x0 - x1) * (x2 * y3 - y2 * x3)) / denom;
  10119. var y4 = ((x0 * y1 - y0 * x1) * (y2 - y3) - (y0 - y1) * (x2 * y3 - y2 * x3)) / denom;
  10120. return [x4, y4];
  10121. }
  10122. // Function to compare Arrays of numbers. From http://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript
  10123. function equalArrays$1(array1, array2) {
  10124. // if the other array is a falsy value, return
  10125. if (!array1 || !array2)
  10126. return false;
  10127. // compare lengths - can save a lot of time
  10128. if (array1.length !== array2.length)
  10129. return false;
  10130. for (var i = 0, l = array1.length; i < l; i++) {
  10131. // Check if we have nested arrays
  10132. if (array1[i] instanceof Array && array2[i] instanceof Array) {
  10133. // recurse into the nested arrays
  10134. if (!equalArrays$1(array1[i], array2[i]))
  10135. return false;
  10136. } else if (array1[i] !== array2[i]) {
  10137. // Warning - two different object instances will never be equal: {x:20} !== {x:20}
  10138. return false;
  10139. }
  10140. }
  10141. return true;
  10142. }
  10143. /**
  10144. * Takes a complex (i.e. self-intersecting) geojson polygon, and breaks it down into its composite simple, non-self-intersecting one-ring polygons.
  10145. *
  10146. * @module simplepolygon
  10147. * @param {Feature} feature Input polygon. This polygon may be unconform the {@link https://en.wikipedia.org/wiki/Simple_Features|Simple Features standard} in the sense that it's inner and outer rings may cross-intersect or self-intersect, that the outer ring must not contain the optional inner rings and that the winding number must not be positive for the outer and negative for the inner rings.
  10148. * @return {FeatureCollection} Feature collection containing the simple, non-self-intersecting one-ring polygon features that the complex polygon is composed of. These simple polygons have properties such as their parent polygon, winding number and net winding number.
  10149. *
  10150. * @example
  10151. * var poly = {
  10152. * "type": "Feature",
  10153. * "geometry": {
  10154. * "type": "Polygon",
  10155. * "coordinates": [[[0,0],[2,0],[0,2],[2,2],[0,0]]]
  10156. * }
  10157. * };
  10158. *
  10159. * var result = simplepolygon(poly);
  10160. *
  10161. * // =result
  10162. * // which will be a featureCollection of two polygons, one with coordinates [[[0,0],[2,0],[1,1],[0,0]]], parent -1, winding 1 and net winding 1, and one with coordinates [[[1,1],[0,2],[2,2],[1,1]]], parent -1, winding -1 and net winding -1
  10163. */
  10164. var simplepolygon = function (feature$$1) {
  10165. // Check input
  10166. if (feature$$1.type != 'Feature') throw new Error('The input must a geojson object of type Feature');
  10167. if ((feature$$1.geometry === undefined) || (feature$$1.geometry == null)) throw new Error('The input must a geojson object with a non-empty geometry');
  10168. if (feature$$1.geometry.type != 'Polygon') throw new Error('The input must be a geojson Polygon');
  10169. // Process input
  10170. var numRings = feature$$1.geometry.coordinates.length;
  10171. var vertices = [];
  10172. for (var i = 0; i < numRings; i++) {
  10173. var ring = feature$$1.geometry.coordinates[i];
  10174. if (!equalArrays(ring[0], ring[ring.length - 1])) {
  10175. ring.push(ring[0]); // Close input ring if it is not
  10176. }
  10177. vertices.push.apply(vertices, ring.slice(0, ring.length - 1));
  10178. }
  10179. if (!isUnique(vertices)) throw new Error('The input polygon may not have duplicate vertices (except for the first and last vertex of each ring)');
  10180. var numvertices = vertices.length; // number of input ring vertices, with the last closing vertices not counted
  10181. // Compute self-intersections
  10182. var selfIsectsData = isects(feature$$1, function filterFn(isect, ring0, edge0, start0, end0, frac0, ring1, edge1, start1, end1, frac1, unique) {
  10183. return [isect, ring0, edge0, start0, end0, frac0, ring1, edge1, start1, end1, frac1, unique];
  10184. });
  10185. var numSelfIsect = selfIsectsData.length;
  10186. // If no self-intersections are found, the input rings are the output rings. Hence, we must only compute their winding numbers, net winding numbers and (since ohers rings could lie outside the first ring) parents.
  10187. if (numSelfIsect == 0) {
  10188. var outputFeatureArray = [];
  10189. for (var i = 0; i < numRings; i++) {
  10190. outputFeatureArray.push(polygon([feature$$1.geometry.coordinates[i]], {parent: -1, winding: windingOfRing(feature$$1.geometry.coordinates[i])}));
  10191. }
  10192. var output = featureCollection(outputFeatureArray);
  10193. determineParents();
  10194. setNetWinding();
  10195. return output;
  10196. }
  10197. // If self-intersections are found, we will compute the output rings with the help of two intermediate variables
  10198. // First, we build the pseudo vertex list and intersection list
  10199. // The Pseudo vertex list is an array with for each ring an array with for each edge an array containing the pseudo-vertices (as made by their constructor) that have this ring and edge as ringAndEdgeIn, sorted for each edge by their fractional distance on this edge. It's length hence equals numRings.
  10200. var pseudoVtxListByRingAndEdge = [];
  10201. // The intersection list is an array containing intersections (as made by their constructor). First all numvertices ring-vertex-intersections, then all self-intersections (intra- and inter-ring). The order of the latter is not important but is permanent once given.
  10202. var isectList = [];
  10203. // Adding ring-pseudo-vertices to pseudoVtxListByRingAndEdge and ring-vertex-intersections to isectList
  10204. for (var i = 0; i < numRings; i++) {
  10205. pseudoVtxListByRingAndEdge.push([]);
  10206. for (var j = 0; j < feature$$1.geometry.coordinates[i].length - 1; j++) {
  10207. // Each edge will feature one ring-pseudo-vertex in its array, on the last position. i.e. edge j features the ring-pseudo-vertex of the ring vertex j+1, which has ringAndEdgeIn = [i,j], on the last position.
  10208. pseudoVtxListByRingAndEdge[i].push([new PseudoVtx(feature$$1.geometry.coordinates[i][(j + 1).modulo(feature$$1.geometry.coordinates[i].length - 1)], 1, [i, j], [i, (j + 1).modulo(feature$$1.geometry.coordinates[i].length - 1)], undefined)]);
  10209. // The first numvertices elements in isectList correspond to the ring-vertex-intersections
  10210. isectList.push(new Isect(feature$$1.geometry.coordinates[i][j], [i, (j - 1).modulo(feature$$1.geometry.coordinates[i].length - 1)], [i, j], undefined, undefined, false, true));
  10211. }
  10212. }
  10213. // Adding intersection-pseudo-vertices to pseudoVtxListByRingAndEdge and self-intersections to isectList
  10214. for (var i = 0; i < numSelfIsect; i++) {
  10215. // Adding intersection-pseudo-vertices made using selfIsectsData to pseudoVtxListByRingAndEdge's array corresponding to the incomming ring and edge
  10216. pseudoVtxListByRingAndEdge[selfIsectsData[i][1]][selfIsectsData[i][2]].push(new PseudoVtx(selfIsectsData[i][0], selfIsectsData[i][5], [selfIsectsData[i][1], selfIsectsData[i][2]], [selfIsectsData[i][6], selfIsectsData[i][7]], undefined));
  10217. // selfIsectsData contains double mentions of each intersection, but we only want to add them once to isectList
  10218. if (selfIsectsData[i][11]) isectList.push(new Isect(selfIsectsData[i][0], [selfIsectsData[i][1], selfIsectsData[i][2]], [selfIsectsData[i][6], selfIsectsData[i][7]], undefined, undefined, true, true));
  10219. }
  10220. var numIsect = isectList.length;
  10221. // Sort edge arrays of pseudoVtxListByRingAndEdge by the fractional distance 'param'
  10222. for (var i = 0; i < pseudoVtxListByRingAndEdge.length; i++) {
  10223. for (var j = 0; j < pseudoVtxListByRingAndEdge[i].length; j++) {
  10224. pseudoVtxListByRingAndEdge[i][j].sort(function (a, b) { return (a.param < b.param) ? -1 : 1; });
  10225. }
  10226. }
  10227. // Make a spatial index of intersections, in preperation for the following two steps
  10228. var allIsectsAsIsectRbushTreeItem = [];
  10229. for (var i = 0; i < numIsect; i++) {
  10230. allIsectsAsIsectRbushTreeItem.push({minX: isectList[i].coord[0], minY: isectList[i].coord[1], maxX: isectList[i].coord[0], maxY: isectList[i].coord[1], index: i}); // could pass isect: isectList[i], but not necessary
  10231. }
  10232. var isectRbushTree = rbush_1();
  10233. isectRbushTree.load(allIsectsAsIsectRbushTreeItem);
  10234. // Now we will teach each intersection in isectList which is the next intersection along both it's [ring, edge]'s, in two steps.
  10235. // First, we find the next intersection for each pseudo-vertex in pseudoVtxListByRingAndEdge:
  10236. // For each pseudovertex in pseudoVtxListByRingAndEdge (3 loops) look at the next pseudovertex on that edge and find the corresponding intersection by comparing coordinates
  10237. for (var i = 0; i < pseudoVtxListByRingAndEdge.length; i++) {
  10238. for (var j = 0; j < pseudoVtxListByRingAndEdge[i].length; j++) {
  10239. for (var k = 0; k < pseudoVtxListByRingAndEdge[i][j].length; k++) {
  10240. var coordToFind;
  10241. if (k == pseudoVtxListByRingAndEdge[i][j].length - 1) { // If it's the last pseudoVertex on that edge, then the next pseudoVertex is the first one on the next edge of that ring.
  10242. coordToFind = pseudoVtxListByRingAndEdge[i][(j + 1).modulo(feature$$1.geometry.coordinates[i].length - 1)][0].coord;
  10243. } else {
  10244. coordToFind = pseudoVtxListByRingAndEdge[i][j][k + 1].coord;
  10245. }
  10246. var IsectRbushTreeItemFound = isectRbushTree.search({minX: coordToFind[0], minY: coordToFind[1], maxX: coordToFind[0], maxY: coordToFind[1]})[0]; // We can take [0] of the result, because there is only one isect correponding to a pseudo-vertex
  10247. pseudoVtxListByRingAndEdge[i][j][k].nxtIsectAlongEdgeIn = IsectRbushTreeItemFound.index;
  10248. }
  10249. }
  10250. }
  10251. // Second, we port this knowledge of the next intersection over to the intersections in isectList, by finding the intersection corresponding to each pseudo-vertex and copying the pseudo-vertex' knownledge of the next-intersection over to the intersection
  10252. for (var i = 0; i < pseudoVtxListByRingAndEdge.length; i++) {
  10253. for (var j = 0; j < pseudoVtxListByRingAndEdge[i].length; j++) {
  10254. for (var k = 0; k < pseudoVtxListByRingAndEdge[i][j].length; k++) {
  10255. var coordToFind = pseudoVtxListByRingAndEdge[i][j][k].coord;
  10256. var IsectRbushTreeItemFound = isectRbushTree.search({minX: coordToFind[0], minY: coordToFind[1], maxX: coordToFind[0], maxY: coordToFind[1]})[0]; // We can take [0] of the result, because there is only one isect correponding to a pseudo-vertex
  10257. var l = IsectRbushTreeItemFound.index;
  10258. if (l < numvertices) { // Special treatment at ring-vertices: we correct the misnaming that happened in the previous block, since ringAndEdgeOut = ringAndEdge2 for ring vertices.
  10259. isectList[l].nxtIsectAlongRingAndEdge2 = pseudoVtxListByRingAndEdge[i][j][k].nxtIsectAlongEdgeIn;
  10260. } else { // Port the knowledge of the next intersection from the pseudo-vertices to the intersections, depending on how the edges are labeled in the pseudo-vertex and intersection.
  10261. if (equalArrays(isectList[l].ringAndEdge1, pseudoVtxListByRingAndEdge[i][j][k].ringAndEdgeIn)) {
  10262. isectList[l].nxtIsectAlongRingAndEdge1 = pseudoVtxListByRingAndEdge[i][j][k].nxtIsectAlongEdgeIn;
  10263. } else {
  10264. isectList[l].nxtIsectAlongRingAndEdge2 = pseudoVtxListByRingAndEdge[i][j][k].nxtIsectAlongEdgeIn;
  10265. }
  10266. }
  10267. }
  10268. }
  10269. }
  10270. // This explains why, eventhough when we will walk away from an intersection, we will walk way from the corresponding pseudo-vertex along edgeOut, pseudo-vertices have the property 'nxtIsectAlongEdgeIn' in stead of some propery 'nxtPseudoVtxAlongEdgeOut'. This is because this property (which is easy to find out) is used in the above for nxtIsectAlongRingAndEdge1 and nxtIsectAlongRingAndEdge2!
  10271. // Before we start walking over the intersections to build the output rings, we prepare a queue that stores information on intersections we still have to deal with, and put at least one intersection in it.
  10272. // This queue will contain information on intersections where we can start walking from once the current walk is finished, and its parent output ring (the smallest output ring it lies within, -1 if no parent or parent unknown yet) and its winding number (which we can already determine).
  10273. var queue = [];
  10274. // For each output ring, add the ring-vertex-intersection with the smalles x-value (i.e. the left-most) as a start intersection. By choosing such an extremal intersections, we are sure to start at an intersection that is a convex vertex of its output ring. By adding them all to the queue, we are sure that no rings will be forgotten. If due to ring-intersections such an intersection will be encountered while walking, it will be removed from the queue.
  10275. var i = 0;
  10276. for (var j = 0; j < numRings; j++) {
  10277. var leftIsect = i;
  10278. for (var k = 0; k < feature$$1.geometry.coordinates[j].length - 1; k++) {
  10279. if (isectList[i].coord[0] < isectList[leftIsect].coord[0]) {
  10280. leftIsect = i;
  10281. }
  10282. i++;
  10283. }
  10284. // Compute winding at this left-most ring-vertex-intersection. We thus this by using our knowledge that this extremal vertex must be a convex vertex.
  10285. // We first find the intersection before and after it, and then use them to determine the winding number of the corresponding output ring, since we know that an extremal vertex of a simple, non-self-intersecting ring is always convex, so the only reason it would not be is because the winding number we use to compute it is wrong
  10286. var isectAfterLeftIsect = isectList[leftIsect].nxtIsectAlongRingAndEdge2;
  10287. for (var k = 0; k < isectList.length; k++) {
  10288. if ((isectList[k].nxtIsectAlongRingAndEdge1 == leftIsect) || (isectList[k].nxtIsectAlongRingAndEdge2 == leftIsect)) {
  10289. var isectBeforeLeftIsect = k;
  10290. break;
  10291. }
  10292. }
  10293. var windingAtIsect = isConvex([isectList[isectBeforeLeftIsect].coord, isectList[leftIsect].coord, isectList[isectAfterLeftIsect].coord], true) ? 1 : -1;
  10294. queue.push({isect: leftIsect, parent: -1, winding: windingAtIsect});
  10295. }
  10296. // Sort the queue by the same criterion used to find the leftIsect: the left-most leftIsect must be last in the queue, such that it will be popped first, such that we will work from out to in regarding input rings. This assumtion is used when predicting the winding number and parent of a new queue member.
  10297. queue.sort(function (a, b) { return (isectList[a.isect].coord > isectList[b.isect].coord) ? -1 : 1; });
  10298. // Initialise output
  10299. var outputFeatureArray = [];
  10300. // While the queue is not empty, take the last object (i.e. its intersection) out and start making an output ring by walking in the direction that has not been walked away over yet.
  10301. while (queue.length > 0) {
  10302. // Get the last object out of the queue
  10303. var popped = queue.pop();
  10304. var startIsect = popped.isect;
  10305. var currentOutputRingParent = popped.parent;
  10306. var currentOutputRingWinding = popped.winding;
  10307. // Make new output ring and add vertex from starting intersection
  10308. var currentOutputRing = outputFeatureArray.length;
  10309. var currentOutputRingCoords = [isectList[startIsect].coord];
  10310. // Set up the variables used while walking over intersections: 'currentIsect', 'nxtIsect' and 'walkingRingAndEdge'
  10311. var currentIsect = startIsect;
  10312. if (isectList[startIsect].ringAndEdge1Walkable) {
  10313. var walkingRingAndEdge = isectList[startIsect].ringAndEdge1;
  10314. var nxtIsect = isectList[startIsect].nxtIsectAlongRingAndEdge1;
  10315. } else {
  10316. var walkingRingAndEdge = isectList[startIsect].ringAndEdge2;
  10317. var nxtIsect = isectList[startIsect].nxtIsectAlongRingAndEdge2;
  10318. }
  10319. // While we have not arrived back at the same intersection, keep walking
  10320. while (!equalArrays(isectList[startIsect].coord, isectList[nxtIsect].coord)) {
  10321. currentOutputRingCoords.push(isectList[nxtIsect].coord);
  10322. // If the next intersection is queued, we can remove it, because we will go there now.
  10323. var nxtIsectInQueue = undefined;
  10324. for (var i = 0; i < queue.length; i++) { if (queue[i].isect == nxtIsect) { nxtIsectInQueue = i; break; } }
  10325. if (nxtIsectInQueue != undefined) {
  10326. queue.splice(nxtIsectInQueue, 1);
  10327. }
  10328. // Arriving at this new intersection, we know which will be our next walking ring and edge (if we came from 1 we will walk away from 2 and vice versa),
  10329. // So we can set it as our new walking ring and intersection and remember that we (will) have walked over it
  10330. // If we have never walked away from this new intersection along the other ring and edge then we will soon do, add the intersection (and the parent wand winding number) to the queue
  10331. // (We can predict the winding number and parent as follows: if the edge is convex, the other output ring started from there will have the alternate winding and lie outside of the current one, and thus have the same parent ring as the current ring. Otherwise, it will have the same winding number and lie inside of the current ring. We are, however, only sure of this of an output ring started from there does not enclose the current ring. This is why the initial queue's intersections must be sorted such that outer ones come out first.)
  10332. // We then update the other two walking variables.
  10333. if (equalArrays(walkingRingAndEdge, isectList[nxtIsect].ringAndEdge1)) {
  10334. walkingRingAndEdge = isectList[nxtIsect].ringAndEdge2;
  10335. isectList[nxtIsect].ringAndEdge2Walkable = false;
  10336. if (isectList[nxtIsect].ringAndEdge1Walkable) {
  10337. var pushing = {isect: nxtIsect};
  10338. if (isConvex([isectList[currentIsect].coord, isectList[nxtIsect].coord, isectList[isectList[nxtIsect].nxtIsectAlongRingAndEdge2].coord], currentOutputRingWinding == 1)) {
  10339. pushing.parent = currentOutputRingParent;
  10340. pushing.winding = -currentOutputRingWinding;
  10341. } else {
  10342. pushing.parent = currentOutputRing;
  10343. pushing.winding = currentOutputRingWinding;
  10344. }
  10345. queue.push(pushing);
  10346. }
  10347. currentIsect = nxtIsect;
  10348. nxtIsect = isectList[nxtIsect].nxtIsectAlongRingAndEdge2;
  10349. } else {
  10350. walkingRingAndEdge = isectList[nxtIsect].ringAndEdge1;
  10351. isectList[nxtIsect].ringAndEdge1Walkable = false;
  10352. if (isectList[nxtIsect].ringAndEdge2Walkable) {
  10353. var pushing = {isect: nxtIsect};
  10354. if (isConvex([isectList[currentIsect].coord, isectList[nxtIsect].coord, isectList[isectList[nxtIsect].nxtIsectAlongRingAndEdge1].coord], currentOutputRingWinding == 1)) {
  10355. pushing.parent = currentOutputRingParent;
  10356. pushing.winding = -currentOutputRingWinding;
  10357. } else {
  10358. pushing.parent = currentOutputRing;
  10359. pushing.winding = currentOutputRingWinding;
  10360. }
  10361. queue.push(pushing);
  10362. }
  10363. currentIsect = nxtIsect;
  10364. nxtIsect = isectList[nxtIsect].nxtIsectAlongRingAndEdge1;
  10365. }
  10366. }
  10367. // Close output ring
  10368. currentOutputRingCoords.push(isectList[nxtIsect].coord);
  10369. // Push output ring to output
  10370. outputFeatureArray.push(polygon([currentOutputRingCoords], {index: currentOutputRing, parent: currentOutputRingParent, winding: currentOutputRingWinding, netWinding: undefined}));
  10371. }
  10372. var output = featureCollection(outputFeatureArray);
  10373. determineParents();
  10374. setNetWinding();
  10375. // These functions are also used if no intersections are found
  10376. function determineParents() {
  10377. var featuresWithoutParent = [];
  10378. for (var i = 0; i < output.features.length; i++) {
  10379. if (output.features[i].properties.parent == -1) featuresWithoutParent.push(i);
  10380. }
  10381. if (featuresWithoutParent.length > 1) {
  10382. for (var i = 0; i < featuresWithoutParent.length; i++) {
  10383. var parent = -1;
  10384. var parentArea = Infinity;
  10385. for (var j = 0; j < output.features.length; j++) {
  10386. if (featuresWithoutParent[i] == j) continue;
  10387. if (booleanPointInPolygon(output.features[featuresWithoutParent[i]].geometry.coordinates[0][0], output.features[j], {ignoreBoundary: true})) {
  10388. if (area$1(output.features[j]) < parentArea) {
  10389. parent = j;
  10390. }
  10391. }
  10392. }
  10393. output.features[featuresWithoutParent[i]].properties.parent = parent;
  10394. }
  10395. }
  10396. }
  10397. function setNetWinding() {
  10398. for (var i = 0; i < output.features.length; i++) {
  10399. if (output.features[i].properties.parent == -1) {
  10400. var netWinding = output.features[i].properties.winding;
  10401. output.features[i].properties.netWinding = netWinding;
  10402. setNetWindingOfChildren(i, netWinding);
  10403. }
  10404. }
  10405. }
  10406. function setNetWindingOfChildren(parent, ParentNetWinding) {
  10407. for (var i = 0; i < output.features.length; i++) {
  10408. if (output.features[i].properties.parent == parent) {
  10409. var netWinding = ParentNetWinding + output.features[i].properties.winding;
  10410. output.features[i].properties.netWinding = netWinding;
  10411. setNetWindingOfChildren(i, netWinding);
  10412. }
  10413. }
  10414. }
  10415. return output;
  10416. };
  10417. // Constructor for (ring- or intersection-) pseudo-vertices.
  10418. var PseudoVtx = function (coord, param, ringAndEdgeIn, ringAndEdgeOut, nxtIsectAlongEdgeIn) {
  10419. this.coord = coord; // [x,y] of this pseudo-vertex
  10420. this.param = param; // fractional distance of this intersection on incomming edge
  10421. this.ringAndEdgeIn = ringAndEdgeIn; // [ring index, edge index] of incomming edge
  10422. this.ringAndEdgeOut = ringAndEdgeOut; // [ring index, edge index] of outgoing edge
  10423. this.nxtIsectAlongEdgeIn = nxtIsectAlongEdgeIn; // The next intersection when following the incomming edge (so not when following ringAndEdgeOut!)
  10424. };
  10425. // Constructor for an intersection. There are two intersection-pseudo-vertices per self-intersection and one ring-pseudo-vertex per ring-vertex-intersection. Their labels 1 and 2 are not assigned a particular meaning but are permanent once given.
  10426. var Isect = function (coord, ringAndEdge1, ringAndEdge2, nxtIsectAlongRingAndEdge1, nxtIsectAlongRingAndEdge2, ringAndEdge1Walkable, ringAndEdge2Walkable) {
  10427. this.coord = coord; // [x,y] of this intersection
  10428. this.ringAndEdge1 = ringAndEdge1; // first edge of this intersection
  10429. this.ringAndEdge2 = ringAndEdge2; // second edge of this intersection
  10430. this.nxtIsectAlongRingAndEdge1 = nxtIsectAlongRingAndEdge1; // the next intersection when following ringAndEdge1
  10431. this.nxtIsectAlongRingAndEdge2 = nxtIsectAlongRingAndEdge2; // the next intersection when following ringAndEdge2
  10432. this.ringAndEdge1Walkable = ringAndEdge1Walkable; // May we (still) walk away from this intersection over ringAndEdge1?
  10433. this.ringAndEdge2Walkable = ringAndEdge2Walkable; // May we (still) walk away from this intersection over ringAndEdge2?
  10434. };
  10435. // Function to determine if three consecutive points of a simple, non-self-intersecting ring make up a convex vertex, assuming the ring is right- or lefthanded
  10436. function isConvex(pts, righthanded) {
  10437. // 'pts' is an [x,y] pair
  10438. // 'righthanded' is a boolean
  10439. if (typeof (righthanded) === 'undefined') righthanded = true;
  10440. if (pts.length != 3) throw new Error('This function requires an array of three points [x,y]');
  10441. var d = (pts[1][0] - pts[0][0]) * (pts[2][1] - pts[0][1]) - (pts[1][1] - pts[0][1]) * (pts[2][0] - pts[0][0]);
  10442. return (d >= 0) == righthanded;
  10443. }
  10444. // Function to compute winding of simple, non-self-intersecting ring
  10445. function windingOfRing(ring) {
  10446. // 'ring' is an array of [x,y] pairs with the last equal to the first
  10447. // Compute the winding number based on the vertex with the smallest x-value, it precessor and successor. An extremal vertex of a simple, non-self-intersecting ring is always convex, so the only reason it is not is because the winding number we use to compute it is wrong
  10448. var leftVtx = 0;
  10449. for (var i = 0; i < ring.length - 1; i++) { if (ring[i][0] < ring[leftVtx][0]) leftVtx = i; }
  10450. if (isConvex([ring[(leftVtx - 1).modulo(ring.length - 1)], ring[leftVtx], ring[(leftVtx + 1).modulo(ring.length - 1)]], true)) {
  10451. var winding = 1;
  10452. } else {
  10453. var winding = -1;
  10454. }
  10455. return winding;
  10456. }
  10457. // Function to compare Arrays of numbers. From http://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript
  10458. function equalArrays(array1, array2) {
  10459. // if the other array is a falsy value, return
  10460. if (!array1 || !array2)
  10461. return false;
  10462. // compare lengths - can save a lot of time
  10463. if (array1.length != array2.length)
  10464. return false;
  10465. for (var i = 0, l = array1.length; i < l; i++) {
  10466. // Check if we have nested arrays
  10467. if (array1[i] instanceof Array && array2[i] instanceof Array) {
  10468. // recurse into the nested arrays
  10469. if (!equalArrays(array1[i], array2[i]))
  10470. return false;
  10471. } else if (array1[i] != array2[i]) {
  10472. // Warning - two different object instances will never be equal: {x:20} != {x:20}
  10473. return false;
  10474. }
  10475. }
  10476. return true;
  10477. }
  10478. // Fix Javascript modulo for negative number. From http://stackoverflow.com/questions/4467539/javascript-modulo-not-behaving
  10479. Number.prototype.modulo = function (n) {
  10480. return ((this % n) + n) % n;
  10481. };
  10482. // Function to check if array is unique (i.e. all unique elements, i.e. no duplicate elements)
  10483. function isUnique(array) {
  10484. var u = {};
  10485. var isUnique = 1;
  10486. for (var i = 0, l = array.length; i < l; ++i) {
  10487. if (u.hasOwnProperty(array[i])) {
  10488. isUnique = 0;
  10489. break;
  10490. }
  10491. u[array[i]] = 1;
  10492. }
  10493. return isUnique;
  10494. }
  10495. /**
  10496. * Takes a kinked polygon and returns a feature collection of polygons that have no kinks.
  10497. * Uses [simplepolygon](https://github.com/mclaeysb/simplepolygon) internally.
  10498. *
  10499. * @name unkinkPolygon
  10500. * @param {FeatureCollection|Feature<Polygon|MultiPolygon>} geojson GeoJSON Polygon or MultiPolygon
  10501. * @returns {FeatureCollection<Polygon>} Unkinked polygons
  10502. * @example
  10503. * var poly = turf.polygon([[[0, 0], [2, 0], [0, 2], [2, 2], [0, 0]]]);
  10504. *
  10505. * var result = turf.unkinkPolygon(poly);
  10506. *
  10507. * //addToMap
  10508. * var addToMap = [poly, result]
  10509. */
  10510. function unkinkPolygon(geojson) {
  10511. var features = [];
  10512. flattenEach(geojson, function (feature$$1) {
  10513. if (feature$$1.geometry.type !== 'Polygon') return;
  10514. featureEach(simplepolygon(feature$$1), function (poly) {
  10515. features.push(polygon(poly.geometry.coordinates, feature$$1.properties));
  10516. });
  10517. });
  10518. return featureCollection(features);
  10519. }
  10520. var D2R = Math.PI / 180;
  10521. var R2D = 180 / Math.PI;
  10522. var Coord = function (lon, lat) {
  10523. this.lon = lon;
  10524. this.lat = lat;
  10525. this.x = D2R * lon;
  10526. this.y = D2R * lat;
  10527. };
  10528. Coord.prototype.view = function () {
  10529. return String(this.lon).slice(0, 4) + ',' + String(this.lat).slice(0, 4);
  10530. };
  10531. Coord.prototype.antipode = function () {
  10532. var anti_lat = -1 * this.lat;
  10533. var anti_lon = (this.lon < 0) ? 180 + this.lon : (180 - this.lon) * -1;
  10534. return new Coord(anti_lon, anti_lat);
  10535. };
  10536. var LineString = function () {
  10537. this.coords = [];
  10538. this.length = 0;
  10539. };
  10540. LineString.prototype.move_to = function (coord) {
  10541. this.length++;
  10542. this.coords.push(coord);
  10543. };
  10544. var Arc = function (properties) {
  10545. this.properties = properties || {};
  10546. this.geometries = [];
  10547. };
  10548. Arc.prototype.json = function () {
  10549. if (this.geometries.length <= 0) {
  10550. return {'geometry': { 'type': 'LineString', 'coordinates': null },
  10551. 'type': 'Feature', 'properties': this.properties
  10552. };
  10553. } else if (this.geometries.length === 1) {
  10554. return {'geometry': { 'type': 'LineString', 'coordinates': this.geometries[0].coords },
  10555. 'type': 'Feature', 'properties': this.properties
  10556. };
  10557. } else {
  10558. var multiline = [];
  10559. for (var i = 0; i < this.geometries.length; i++) {
  10560. multiline.push(this.geometries[i].coords);
  10561. }
  10562. return {'geometry': { 'type': 'MultiLineString', 'coordinates': multiline },
  10563. 'type': 'Feature', 'properties': this.properties
  10564. };
  10565. }
  10566. };
  10567. // TODO - output proper multilinestring
  10568. Arc.prototype.wkt = function () {
  10569. var wkt_string = '';
  10570. var wkt = 'LINESTRING(';
  10571. var collect = function (c) { wkt += c[0] + ' ' + c[1] + ','; };
  10572. for (var i = 0; i < this.geometries.length; i++) {
  10573. if (this.geometries[i].coords.length === 0) {
  10574. return 'LINESTRING(empty)';
  10575. } else {
  10576. var coords = this.geometries[i].coords;
  10577. coords.forEach(collect);
  10578. wkt_string += wkt.substring(0, wkt.length - 1) + ')';
  10579. }
  10580. }
  10581. return wkt_string;
  10582. };
  10583. /*
  10584. * http://en.wikipedia.org/wiki/Great-circle_distance
  10585. *
  10586. */
  10587. var GreatCircle = function (start, end, properties) {
  10588. if (!start || start.x === undefined || start.y === undefined) {
  10589. throw new Error('GreatCircle constructor expects two args: start and end objects with x and y properties');
  10590. }
  10591. if (!end || end.x === undefined || end.y === undefined) {
  10592. throw new Error('GreatCircle constructor expects two args: start and end objects with x and y properties');
  10593. }
  10594. this.start = new Coord(start.x, start.y);
  10595. this.end = new Coord(end.x, end.y);
  10596. this.properties = properties || {};
  10597. var w = this.start.x - this.end.x;
  10598. var h = this.start.y - this.end.y;
  10599. var z = Math.pow(Math.sin(h / 2.0), 2) +
  10600. Math.cos(this.start.y) *
  10601. Math.cos(this.end.y) *
  10602. Math.pow(Math.sin(w / 2.0), 2);
  10603. this.g = 2.0 * Math.asin(Math.sqrt(z));
  10604. if (this.g === Math.PI) {
  10605. throw new Error('it appears ' + start.view() + ' and ' + end.view() + ' are \'antipodal\', e.g diametrically opposite, thus there is no single route but rather infinite');
  10606. } else if (isNaN(this.g)) {
  10607. throw new Error('could not calculate great circle between ' + start + ' and ' + end);
  10608. }
  10609. };
  10610. /*
  10611. * http://williams.best.vwh.net/avform.htm#Intermediate
  10612. */
  10613. GreatCircle.prototype.interpolate = function (f) {
  10614. var A = Math.sin((1 - f) * this.g) / Math.sin(this.g);
  10615. var B = Math.sin(f * this.g) / Math.sin(this.g);
  10616. var x = A * Math.cos(this.start.y) * Math.cos(this.start.x) + B * Math.cos(this.end.y) * Math.cos(this.end.x);
  10617. var y = A * Math.cos(this.start.y) * Math.sin(this.start.x) + B * Math.cos(this.end.y) * Math.sin(this.end.x);
  10618. var z = A * Math.sin(this.start.y) + B * Math.sin(this.end.y);
  10619. var lat = R2D * Math.atan2(z, Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
  10620. var lon = R2D * Math.atan2(y, x);
  10621. return [lon, lat];
  10622. };
  10623. /*
  10624. * Generate points along the great circle
  10625. */
  10626. GreatCircle.prototype.Arc = function (npoints, options) {
  10627. var first_pass = [];
  10628. if (!npoints || npoints <= 2) {
  10629. first_pass.push([this.start.lon, this.start.lat]);
  10630. first_pass.push([this.end.lon, this.end.lat]);
  10631. } else {
  10632. var delta = 1.0 / (npoints - 1);
  10633. for (var i = 0; i < npoints; ++i) {
  10634. var step = delta * i;
  10635. var pair = this.interpolate(step);
  10636. first_pass.push(pair);
  10637. }
  10638. }
  10639. /* partial port of dateline handling from:
  10640. gdal/ogr/ogrgeometryfactory.cpp
  10641. TODO - does not handle all wrapping scenarios yet
  10642. */
  10643. var bHasBigDiff = false;
  10644. var dfMaxSmallDiffLong = 0;
  10645. // from http://www.gdal.org/ogr2ogr.html
  10646. // -datelineoffset:
  10647. // (starting with GDAL 1.10) offset from dateline in degrees (default long. = +/- 10deg, geometries within 170deg to -170deg will be splited)
  10648. var dfDateLineOffset = options && options.offset ? options.offset : 10;
  10649. var dfLeftBorderX = 180 - dfDateLineOffset;
  10650. var dfRightBorderX = -180 + dfDateLineOffset;
  10651. var dfDiffSpace = 360 - dfDateLineOffset;
  10652. // https://github.com/OSGeo/gdal/blob/7bfb9c452a59aac958bff0c8386b891edf8154ca/gdal/ogr/ogrgeometryfactory.cpp#L2342
  10653. for (var j = 1; j < first_pass.length; ++j) {
  10654. var dfPrevX = first_pass[j - 1][0];
  10655. var dfX = first_pass[j][0];
  10656. var dfDiffLong = Math.abs(dfX - dfPrevX);
  10657. if (dfDiffLong > dfDiffSpace &&
  10658. ((dfX > dfLeftBorderX && dfPrevX < dfRightBorderX) || (dfPrevX > dfLeftBorderX && dfX < dfRightBorderX))) {
  10659. bHasBigDiff = true;
  10660. } else if (dfDiffLong > dfMaxSmallDiffLong) {
  10661. dfMaxSmallDiffLong = dfDiffLong;
  10662. }
  10663. }
  10664. var poMulti = [];
  10665. if (bHasBigDiff && dfMaxSmallDiffLong < dfDateLineOffset) {
  10666. var poNewLS = [];
  10667. poMulti.push(poNewLS);
  10668. for (var k = 0; k < first_pass.length; ++k) {
  10669. var dfX0 = parseFloat(first_pass[k][0]);
  10670. if (k > 0 && Math.abs(dfX0 - first_pass[k - 1][0]) > dfDiffSpace) {
  10671. var dfX1 = parseFloat(first_pass[k - 1][0]);
  10672. var dfY1 = parseFloat(first_pass[k - 1][1]);
  10673. var dfX2 = parseFloat(first_pass[k][0]);
  10674. var dfY2 = parseFloat(first_pass[k][1]);
  10675. if (dfX1 > -180 && dfX1 < dfRightBorderX && dfX2 === 180 &&
  10676. k + 1 < first_pass.length &&
  10677. first_pass[k - 1][0] > -180 && first_pass[k - 1][0] < dfRightBorderX) {
  10678. poNewLS.push([-180, first_pass[k][1]]);
  10679. k++;
  10680. poNewLS.push([first_pass[k][0], first_pass[k][1]]);
  10681. continue;
  10682. } else if (dfX1 > dfLeftBorderX && dfX1 < 180 && dfX2 === -180 &&
  10683. k + 1 < first_pass.length &&
  10684. first_pass[k - 1][0] > dfLeftBorderX && first_pass[k - 1][0] < 180) {
  10685. poNewLS.push([180, first_pass[k][1]]);
  10686. k++;
  10687. poNewLS.push([first_pass[k][0], first_pass[k][1]]);
  10688. continue;
  10689. }
  10690. if (dfX1 < dfRightBorderX && dfX2 > dfLeftBorderX) {
  10691. // swap dfX1, dfX2
  10692. var tmpX = dfX1;
  10693. dfX1 = dfX2;
  10694. dfX2 = tmpX;
  10695. // swap dfY1, dfY2
  10696. var tmpY = dfY1;
  10697. dfY1 = dfY2;
  10698. dfY2 = tmpY;
  10699. }
  10700. if (dfX1 > dfLeftBorderX && dfX2 < dfRightBorderX) {
  10701. dfX2 += 360;
  10702. }
  10703. if (dfX1 <= 180 && dfX2 >= 180 && dfX1 < dfX2) {
  10704. var dfRatio = (180 - dfX1) / (dfX2 - dfX1);
  10705. var dfY = dfRatio * dfY2 + (1 - dfRatio) * dfY1;
  10706. poNewLS.push([first_pass[k - 1][0] > dfLeftBorderX ? 180 : -180, dfY]);
  10707. poNewLS = [];
  10708. poNewLS.push([first_pass[k - 1][0] > dfLeftBorderX ? -180 : 180, dfY]);
  10709. poMulti.push(poNewLS);
  10710. } else {
  10711. poNewLS = [];
  10712. poMulti.push(poNewLS);
  10713. }
  10714. poNewLS.push([dfX0, first_pass[k][1]]);
  10715. } else {
  10716. poNewLS.push([first_pass[k][0], first_pass[k][1]]);
  10717. }
  10718. }
  10719. } else {
  10720. // add normally
  10721. var poNewLS0 = [];
  10722. poMulti.push(poNewLS0);
  10723. for (var l = 0; l < first_pass.length; ++l) {
  10724. poNewLS0.push([first_pass[l][0], first_pass[l][1]]);
  10725. }
  10726. }
  10727. var arc = new Arc(this.properties);
  10728. for (var m = 0; m < poMulti.length; ++m) {
  10729. var line = new LineString();
  10730. arc.geometries.push(line);
  10731. var points = poMulti[m];
  10732. for (var j0 = 0; j0 < points.length; ++j0) {
  10733. line.move_to(points[j0]);
  10734. }
  10735. }
  10736. return arc;
  10737. };
  10738. /**
  10739. * Calculate great circles routes as {@link LineString}
  10740. *
  10741. * @name greatCircle
  10742. * @param {Coord} start source point feature
  10743. * @param {Coord} end destination point feature
  10744. * @param {Object} [options={}] Optional parameters
  10745. * @param {Object} [options.properties={}] line feature properties
  10746. * @param {number} [options.npoints=100] number of points
  10747. * @param {number} [options.offset=10] offset controls the likelyhood that lines will
  10748. * be split which cross the dateline. The higher the number the more likely.
  10749. * @returns {Feature<LineString>} great circle line feature
  10750. * @example
  10751. * var start = turf.point([-122, 48]);
  10752. * var end = turf.point([-77, 39]);
  10753. *
  10754. * var greatCircle = turf.greatCircle(start, end, {'name': 'Seattle to DC'});
  10755. *
  10756. * //addToMap
  10757. * var addToMap = [start, end, greatCircle]
  10758. */
  10759. function greatCircle(start, end, options) {
  10760. // Optional parameters
  10761. options = options || {};
  10762. if (typeof options !== 'object') throw new Error('options is invalid');
  10763. var properties = options.properties;
  10764. var npoints = options.npoints;
  10765. var offset = options.offset;
  10766. start = getCoord(start);
  10767. end = getCoord(end);
  10768. properties = properties || {};
  10769. npoints = npoints || 100;
  10770. offset = offset || 10;
  10771. var generator = new GreatCircle({x: start[0], y: start[1]}, {x: end[0], y: end[1]}, properties);
  10772. /* eslint-disable */
  10773. var line = generator.Arc(npoints, {offset: offset});
  10774. /* eslint-enable */
  10775. return line.json();
  10776. }
  10777. /**
  10778. * Split a LineString by another GeoJSON Feature.
  10779. *
  10780. * @name lineSplit
  10781. * @param {Feature<LineString>} line LineString Feature to split
  10782. * @param {Feature<any>} splitter Feature used to split line
  10783. * @returns {FeatureCollection<LineString>} Split LineStrings
  10784. * @example
  10785. * var line = turf.lineString([[120, -25], [145, -25]]);
  10786. * var splitter = turf.lineString([[130, -15], [130, -35]]);
  10787. *
  10788. * var split = turf.lineSplit(line, splitter);
  10789. *
  10790. * //addToMap
  10791. * var addToMap = [line, splitter]
  10792. */
  10793. function lineSplit(line, splitter) {
  10794. if (!line) throw new Error('line is required');
  10795. if (!splitter) throw new Error('splitter is required');
  10796. var lineType = getType(line);
  10797. var splitterType = getType(splitter);
  10798. if (lineType !== 'LineString') throw new Error('line must be LineString');
  10799. if (splitterType === 'FeatureCollection') throw new Error('splitter cannot be a FeatureCollection');
  10800. if (splitterType === 'GeometryCollection') throw new Error('splitter cannot be a GeometryCollection');
  10801. // remove excessive decimals from splitter
  10802. // to avoid possible approximation issues in rbush
  10803. var truncatedSplitter = truncate(splitter, {precision: 7});
  10804. switch (splitterType) {
  10805. case 'Point':
  10806. return splitLineWithPoint(line, truncatedSplitter);
  10807. case 'MultiPoint':
  10808. return splitLineWithPoints(line, truncatedSplitter);
  10809. case 'LineString':
  10810. case 'MultiLineString':
  10811. case 'Polygon':
  10812. case 'MultiPolygon':
  10813. return splitLineWithPoints(line, lineIntersect(line, truncatedSplitter));
  10814. }
  10815. }
  10816. /**
  10817. * Split LineString with MultiPoint
  10818. *
  10819. * @private
  10820. * @param {Feature<LineString>} line LineString
  10821. * @param {FeatureCollection<Point>} splitter Point
  10822. * @returns {FeatureCollection<LineString>} split LineStrings
  10823. */
  10824. function splitLineWithPoints(line, splitter) {
  10825. var results = [];
  10826. var tree = geojsonRbush();
  10827. flattenEach(splitter, function (point$$1) {
  10828. // Add index/id to features (needed for filter)
  10829. results.forEach(function (feature$$1, index) {
  10830. feature$$1.id = index;
  10831. });
  10832. // First Point - doesn't need to handle any previous line results
  10833. if (!results.length) {
  10834. results = splitLineWithPoint(line, point$$1).features;
  10835. // Add Square BBox to each feature for GeoJSON-RBush
  10836. results.forEach(function (feature$$1) {
  10837. if (!feature$$1.bbox) feature$$1.bbox = square(bbox(feature$$1));
  10838. });
  10839. tree.load(featureCollection(results));
  10840. // Split with remaining points - lines might needed to be split multiple times
  10841. } else {
  10842. // Find all lines that are within the splitter's bbox
  10843. var search = tree.search(point$$1);
  10844. if (search.features.length) {
  10845. // RBush might return multiple lines - only process the closest line to splitter
  10846. var closestLine = findClosestFeature(point$$1, search);
  10847. // Remove closest line from results since this will be split into two lines
  10848. // This removes any duplicates inside the results & index
  10849. results = results.filter(function (feature$$1) { return feature$$1.id !== closestLine.id; });
  10850. tree.remove(closestLine);
  10851. // Append the two newly split lines into the results
  10852. featureEach(splitLineWithPoint(closestLine, point$$1), function (line) {
  10853. results.push(line);
  10854. tree.insert(line);
  10855. });
  10856. }
  10857. }
  10858. });
  10859. return featureCollection(results);
  10860. }
  10861. /**
  10862. * Split LineString with Point
  10863. *
  10864. * @private
  10865. * @param {Feature<LineString>} line LineString
  10866. * @param {Feature<Point>} splitter Point
  10867. * @returns {FeatureCollection<LineString>} split LineStrings
  10868. */
  10869. function splitLineWithPoint(line, splitter) {
  10870. var results = [];
  10871. // handle endpoints
  10872. var startPoint = getCoords(line)[0];
  10873. var endPoint = getCoords(line)[line.geometry.coordinates.length - 1];
  10874. if (pointsEquals(startPoint, getCoord(splitter)) ||
  10875. pointsEquals(endPoint, getCoord(splitter))) return featureCollection([line]);
  10876. // Create spatial index
  10877. var tree = geojsonRbush();
  10878. var segments = lineSegment(line);
  10879. tree.load(segments);
  10880. // Find all segments that are within bbox of splitter
  10881. var search = tree.search(splitter);
  10882. // Return itself if point is not within spatial index
  10883. if (!search.features.length) return featureCollection([line]);
  10884. // RBush might return multiple lines - only process the closest line to splitter
  10885. var closestSegment = findClosestFeature(splitter, search);
  10886. // Initial value is the first point of the first segments (beginning of line)
  10887. var initialValue = [startPoint];
  10888. var lastCoords = featureReduce(segments, function (previous, current, index) {
  10889. var currentCoords = getCoords(current)[1];
  10890. var splitterCoords = getCoord(splitter);
  10891. // Location where segment intersects with line
  10892. if (index === closestSegment.id) {
  10893. previous.push(splitterCoords);
  10894. results.push(lineString(previous));
  10895. // Don't duplicate splitter coordinate (Issue #688)
  10896. if (pointsEquals(splitterCoords, currentCoords)) return [splitterCoords];
  10897. return [splitterCoords, currentCoords];
  10898. // Keep iterating over coords until finished or intersection is found
  10899. } else {
  10900. previous.push(currentCoords);
  10901. return previous;
  10902. }
  10903. }, initialValue);
  10904. // Append last line to final split results
  10905. if (lastCoords.length > 1) {
  10906. results.push(lineString(lastCoords));
  10907. }
  10908. return featureCollection(results);
  10909. }
  10910. /**
  10911. * Find Closest Feature
  10912. *
  10913. * @private
  10914. * @param {Feature<Point>} point Feature must be closest to this point
  10915. * @param {FeatureCollection<LineString>} lines Collection of Features
  10916. * @returns {Feature<LineString>} closest LineString
  10917. */
  10918. function findClosestFeature(point$$1, lines) {
  10919. if (!lines.features.length) throw new Error('lines must contain features');
  10920. // Filter to one segment that is the closest to the line
  10921. if (lines.features.length === 1) return lines.features[0];
  10922. var closestFeature;
  10923. var closestDistance = Infinity;
  10924. featureEach(lines, function (segment) {
  10925. var pt = nearestPointOnLine(segment, point$$1);
  10926. var dist = pt.properties.dist;
  10927. if (dist < closestDistance) {
  10928. closestFeature = segment;
  10929. closestDistance = dist;
  10930. }
  10931. });
  10932. return closestFeature;
  10933. }
  10934. /**
  10935. * Compares two points and returns if they are equals
  10936. *
  10937. * @private
  10938. * @param {Array<number>} pt1 point
  10939. * @param {Array<number>} pt2 point
  10940. * @returns {boolean} true if they are equals
  10941. */
  10942. function pointsEquals(pt1, pt2) {
  10943. return pt1[0] === pt2[0] && pt1[1] === pt2[1];
  10944. }
  10945. /**
  10946. * Creates a circular arc, of a circle of the given radius and center point, between bearing1 and bearing2;
  10947. * 0 bearing is North of center point, positive clockwise.
  10948. *
  10949. * @name lineArc
  10950. * @param {Coord} center center point
  10951. * @param {number} radius radius of the circle
  10952. * @param {number} bearing1 angle, in decimal degrees, of the first radius of the arc
  10953. * @param {number} bearing2 angle, in decimal degrees, of the second radius of the arc
  10954. * @param {Object} [options={}] Optional parameters
  10955. * @param {number} [options.steps=64] number of steps
  10956. * @param {string} [options.units='kilometers'] miles, kilometers, degrees, or radians
  10957. * @returns {Feature<LineString>} line arc
  10958. * @example
  10959. * var center = turf.point([-75, 40]);
  10960. * var radius = 5;
  10961. * var bearing1 = 25;
  10962. * var bearing2 = 47;
  10963. *
  10964. * var arc = turf.lineArc(center, radius, bearing1, bearing2);
  10965. *
  10966. * //addToMap
  10967. * var addToMap = [center, arc]
  10968. */
  10969. function lineArc(center, radius, bearing1, bearing2, options) {
  10970. // Optional parameters
  10971. options = options || {};
  10972. if (!isObject(options)) throw new Error('options is invalid');
  10973. var steps = options.steps;
  10974. var units = options.units;
  10975. // validation
  10976. if (!center) throw new Error('center is required');
  10977. if (!radius) throw new Error('radius is required');
  10978. if (bearing1 === undefined || bearing1 === null) throw new Error('bearing1 is required');
  10979. if (bearing2 === undefined || bearing2 === null) throw new Error('bearing2 is required');
  10980. if (typeof options !== 'object') throw new Error('options must be an object');
  10981. // default params
  10982. steps = steps || 64;
  10983. var angle1 = convertAngleTo360(bearing1);
  10984. var angle2 = convertAngleTo360(bearing2);
  10985. var properties = center.properties;
  10986. // handle angle parameters
  10987. if (angle1 === angle2) {
  10988. return lineString(circle(center, radius, options).geometry.coordinates[0], properties);
  10989. }
  10990. var arcStartDegree = angle1;
  10991. var arcEndDegree = (angle1 < angle2) ? angle2 : angle2 + 360;
  10992. var alfa = arcStartDegree;
  10993. var coordinates = [];
  10994. var i = 0;
  10995. while (alfa < arcEndDegree) {
  10996. coordinates.push(destination(center, radius, alfa, units).geometry.coordinates);
  10997. i++;
  10998. alfa = arcStartDegree + i * 360 / steps;
  10999. }
  11000. if (alfa > arcEndDegree) {
  11001. coordinates.push(destination(center, radius, arcEndDegree, units).geometry.coordinates);
  11002. }
  11003. return lineString(coordinates, properties);
  11004. }
  11005. /**
  11006. * Takes any angle in degrees
  11007. * and returns a valid angle between 0-360 degrees
  11008. *
  11009. * @private
  11010. * @param {number} alfa angle between -180-180 degrees
  11011. * @returns {number} angle between 0-360 degrees
  11012. */
  11013. function convertAngleTo360(alfa) {
  11014. var beta = alfa % 360;
  11015. if (beta < 0) {
  11016. beta += 360;
  11017. }
  11018. return beta;
  11019. }
  11020. /**
  11021. * Converts a {@link Polygon} to {@link LineString|(Multi)LineString} or {@link MultiPolygon} to a {@link FeatureCollection} of {@link LineString|(Multi)LineString}.
  11022. *
  11023. * @name polygonToLine
  11024. * @param {Feature<Polygon|MultiPolygon>} polygon Feature to convert
  11025. * @param {Object} [options={}] Optional parameters
  11026. * @param {Object} [options.properties={}] translates GeoJSON properties to Feature
  11027. * @returns {FeatureCollection|Feature<LineString|MultiLinestring>} converted (Multi)Polygon to (Multi)LineString
  11028. * @example
  11029. * var poly = turf.polygon([[[125, -30], [145, -30], [145, -20], [125, -20], [125, -30]]]);
  11030. *
  11031. * var line = turf.polygonToLine(poly);
  11032. *
  11033. * //addToMap
  11034. * var addToMap = [line];
  11035. */
  11036. function polygonToLine(polygon$$1, options) {
  11037. // Optional parameters
  11038. options = options || {};
  11039. if (!isObject(options)) throw new Error('options is invalid');
  11040. var properties = options.properties;
  11041. // Variables
  11042. var geom = getType(polygon$$1);
  11043. var coords = getCoords(polygon$$1);
  11044. properties = properties || polygon$$1.properties || {};
  11045. if (!coords.length) throw new Error('polygon must contain coordinates');
  11046. switch (geom) {
  11047. case 'Polygon':
  11048. return coordsToLine(coords, properties);
  11049. case 'MultiPolygon':
  11050. var lines = [];
  11051. coords.forEach(function (coord) {
  11052. lines.push(coordsToLine(coord, properties));
  11053. });
  11054. return featureCollection(lines);
  11055. default:
  11056. throw new Error('geom ' + geom + ' not supported');
  11057. }
  11058. }
  11059. function coordsToLine(coords, properties) {
  11060. if (coords.length > 1) return multiLineString(coords, properties);
  11061. return lineString(coords[0], properties);
  11062. }
  11063. /**
  11064. * Converts (Multi)LineString(s) to Polygon(s).
  11065. *
  11066. * @name lineToPolygon
  11067. * @param {FeatureCollection|Feature<LineString|MultiLineString>} lines Features to convert
  11068. * @param {Object} [options={}] Optional parameters
  11069. * @param {Object} [options.properties={}] translates GeoJSON properties to Feature
  11070. * @param {boolean} [options.autoComplete=true] auto complete linestrings (matches first & last coordinates)
  11071. * @param {boolean} [options.orderCoords=true] sorts linestrings to place outer ring at the first position of the coordinates
  11072. * @returns {Feature<Polygon|MultiPolygon>} converted to Polygons
  11073. * @example
  11074. * var line = turf.lineString([[125, -30], [145, -30], [145, -20], [125, -20], [125, -30]]);
  11075. *
  11076. * var polygon = turf.lineToPolygon(line);
  11077. *
  11078. * //addToMap
  11079. * var addToMap = [polygon];
  11080. */
  11081. function lineToPolygon(lines, options) {
  11082. // Optional parameters
  11083. options = options || {};
  11084. if (!isObject(options)) throw new Error('options is invalid');
  11085. var properties = options.properties;
  11086. var autoComplete = options.autoComplete;
  11087. var orderCoords = options.orderCoords;
  11088. // validation
  11089. if (!lines) throw new Error('lines is required');
  11090. // default params
  11091. autoComplete = (autoComplete !== undefined) ? autoComplete : true;
  11092. orderCoords = (orderCoords !== undefined) ? orderCoords : true;
  11093. var type = getType(lines);
  11094. switch (type) {
  11095. case 'FeatureCollection':
  11096. case 'GeometryCollection':
  11097. var coords = [];
  11098. var features = (lines.features) ? lines.features : lines.geometries;
  11099. features.forEach(function (line) {
  11100. coords.push(getCoords(lineStringToPolygon(line, {}, autoComplete, orderCoords)));
  11101. });
  11102. return multiPolygon(coords, properties);
  11103. }
  11104. return lineStringToPolygon(lines, properties, autoComplete, orderCoords);
  11105. }
  11106. /**
  11107. * LineString to Polygon
  11108. *
  11109. * @private
  11110. * @param {Feature<LineString|MultiLineString>} line line
  11111. * @param {Object} [properties] translates GeoJSON properties to Feature
  11112. * @param {boolean} [autoComplete=true] auto complete linestrings
  11113. * @param {boolean} [orderCoords=true] sorts linestrings to place outer ring at the first position of the coordinates
  11114. * @returns {Feature<Polygon>} line converted to Polygon
  11115. */
  11116. function lineStringToPolygon(line, properties, autoComplete, orderCoords) {
  11117. properties = properties || line.properties || {};
  11118. var coords = getCoords(line);
  11119. var type = getType(line);
  11120. if (!coords.length) throw new Error('line must contain coordinates');
  11121. switch (type) {
  11122. case 'LineString':
  11123. if (autoComplete) coords = autoCompleteCoords(coords);
  11124. return polygon([coords], properties);
  11125. case 'MultiLineString':
  11126. var multiCoords = [];
  11127. var largestArea = 0;
  11128. coords.forEach(function (coord) {
  11129. if (autoComplete) coord = autoCompleteCoords(coord);
  11130. // Largest LineString to be placed in the first position of the coordinates array
  11131. if (orderCoords) {
  11132. var area = calculateArea$1(bbox(lineString(coord)));
  11133. if (area > largestArea) {
  11134. multiCoords.unshift(coord);
  11135. largestArea = area;
  11136. } else multiCoords.push(coord);
  11137. } else {
  11138. multiCoords.push(coord);
  11139. }
  11140. });
  11141. return polygon(multiCoords, properties);
  11142. default:
  11143. throw new Error('geometry type ' + type + ' is not supported');
  11144. }
  11145. }
  11146. /**
  11147. * Auto Complete Coords - matches first & last coordinates
  11148. *
  11149. * @private
  11150. * @param {Array<Array<number>>} coords Coordinates
  11151. * @returns {Array<Array<number>>} auto completed coordinates
  11152. */
  11153. function autoCompleteCoords(coords) {
  11154. var first = coords[0];
  11155. var x1 = first[0];
  11156. var y1 = first[1];
  11157. var last = coords[coords.length - 1];
  11158. var x2 = last[0];
  11159. var y2 = last[1];
  11160. if (x1 !== x2 || y1 !== y2) {
  11161. coords.push(first);
  11162. }
  11163. return coords;
  11164. }
  11165. /**
  11166. * area - quick approximate area calculation (used to sort)
  11167. *
  11168. * @private
  11169. * @param {Array<number>} bbox BBox [west, south, east, north]
  11170. * @returns {number} very quick area calculation
  11171. */
  11172. function calculateArea$1(bbox$$1) {
  11173. var west = bbox$$1[0];
  11174. var south = bbox$$1[1];
  11175. var east = bbox$$1[2];
  11176. var north = bbox$$1[3];
  11177. return Math.abs(west - east) * Math.abs(south - north);
  11178. }
  11179. var lineclip_1 = lineclip;
  11180. lineclip.polyline = lineclip;
  11181. lineclip.polygon = polygonclip;
  11182. // Cohen-Sutherland line clippign algorithm, adapted to efficiently
  11183. // handle polylines rather than just segments
  11184. function lineclip(points, bbox, result) {
  11185. var len = points.length,
  11186. codeA = bitCode(points[0], bbox),
  11187. part = [],
  11188. i, a, b, codeB, lastCode;
  11189. if (!result) result = [];
  11190. for (i = 1; i < len; i++) {
  11191. a = points[i - 1];
  11192. b = points[i];
  11193. codeB = lastCode = bitCode(b, bbox);
  11194. while (true) {
  11195. if (!(codeA | codeB)) { // accept
  11196. part.push(a);
  11197. if (codeB !== lastCode) { // segment went outside
  11198. part.push(b);
  11199. if (i < len - 1) { // start a new line
  11200. result.push(part);
  11201. part = [];
  11202. }
  11203. } else if (i === len - 1) {
  11204. part.push(b);
  11205. }
  11206. break;
  11207. } else if (codeA & codeB) { // trivial reject
  11208. break;
  11209. } else if (codeA) { // a outside, intersect with clip edge
  11210. a = intersect$1(a, b, codeA, bbox);
  11211. codeA = bitCode(a, bbox);
  11212. } else { // b outside
  11213. b = intersect$1(a, b, codeB, bbox);
  11214. codeB = bitCode(b, bbox);
  11215. }
  11216. }
  11217. codeA = lastCode;
  11218. }
  11219. if (part.length) result.push(part);
  11220. return result;
  11221. }
  11222. // Sutherland-Hodgeman polygon clipping algorithm
  11223. function polygonclip(points, bbox) {
  11224. var result, edge, prev, prevInside, i, p, inside;
  11225. // clip against each side of the clip rectangle
  11226. for (edge = 1; edge <= 8; edge *= 2) {
  11227. result = [];
  11228. prev = points[points.length - 1];
  11229. prevInside = !(bitCode(prev, bbox) & edge);
  11230. for (i = 0; i < points.length; i++) {
  11231. p = points[i];
  11232. inside = !(bitCode(p, bbox) & edge);
  11233. // if segment goes through the clip window, add an intersection
  11234. if (inside !== prevInside) result.push(intersect$1(prev, p, edge, bbox));
  11235. if (inside) result.push(p); // add a point if it's inside
  11236. prev = p;
  11237. prevInside = inside;
  11238. }
  11239. points = result;
  11240. if (!points.length) break;
  11241. }
  11242. return result;
  11243. }
  11244. // intersect a segment against one of the 4 lines that make up the bbox
  11245. function intersect$1(a, b, edge, bbox) {
  11246. return edge & 8 ? [a[0] + (b[0] - a[0]) * (bbox[3] - a[1]) / (b[1] - a[1]), bbox[3]] : // top
  11247. edge & 4 ? [a[0] + (b[0] - a[0]) * (bbox[1] - a[1]) / (b[1] - a[1]), bbox[1]] : // bottom
  11248. edge & 2 ? [bbox[2], a[1] + (b[1] - a[1]) * (bbox[2] - a[0]) / (b[0] - a[0])] : // right
  11249. edge & 1 ? [bbox[0], a[1] + (b[1] - a[1]) * (bbox[0] - a[0]) / (b[0] - a[0])] : // left
  11250. null;
  11251. }
  11252. // bit code reflects the point position relative to the bbox:
  11253. // left mid right
  11254. // top 1001 1000 1010
  11255. // mid 0001 0000 0010
  11256. // bottom 0101 0100 0110
  11257. function bitCode(p, bbox) {
  11258. var code = 0;
  11259. if (p[0] < bbox[0]) code |= 1; // left
  11260. else if (p[0] > bbox[2]) code |= 2; // right
  11261. if (p[1] < bbox[1]) code |= 4; // bottom
  11262. else if (p[1] > bbox[3]) code |= 8; // top
  11263. return code;
  11264. }
  11265. /**
  11266. * Takes a {@link Feature} and a bbox and clips the feature to the bbox using [lineclip](https://github.com/mapbox/lineclip).
  11267. * May result in degenerate edges when clipping Polygons.
  11268. *
  11269. * @name bboxClip
  11270. * @param {Feature<LineString|MultiLineString|Polygon|MultiPolygon>} feature feature to clip to the bbox
  11271. * @param {BBox} bbox extent in [minX, minY, maxX, maxY] order
  11272. * @returns {Feature<LineString|MultiLineString|Polygon|MultiPolygon>} clipped Feature
  11273. * @example
  11274. * var bbox = [0, 0, 10, 10];
  11275. * var poly = turf.polygon([[[2, 2], [8, 4], [12, 8], [3, 7], [2, 2]]]);
  11276. *
  11277. * var clipped = turf.bboxClip(poly, bbox);
  11278. *
  11279. * //addToMap
  11280. * var addToMap = [bbox, poly, clipped]
  11281. */
  11282. function bboxClip(feature$$1, bbox) {
  11283. var geom = getGeom$1(feature$$1);
  11284. var coords = getCoords(feature$$1);
  11285. var properties = feature$$1.properties;
  11286. switch (geom) {
  11287. case 'LineString':
  11288. case 'MultiLineString':
  11289. var lines = [];
  11290. if (geom === 'LineString') coords = [coords];
  11291. coords.forEach(function (line) {
  11292. lineclip_1(line, bbox, lines);
  11293. });
  11294. if (lines.length === 1) return lineString(lines[0], properties);
  11295. return multiLineString(lines, properties);
  11296. case 'Polygon':
  11297. return polygon(clipPolygon(coords, bbox), properties);
  11298. case 'MultiPolygon':
  11299. return multiPolygon(coords.map(function (polygon$$1) {
  11300. return clipPolygon(polygon$$1, bbox);
  11301. }), properties);
  11302. default:
  11303. throw new Error('geometry ' + geom + ' not supported');
  11304. }
  11305. }
  11306. function clipPolygon(rings, bbox) {
  11307. var outRings = [];
  11308. for (var i = 0; i < rings.length; i++) {
  11309. var clipped = lineclip_1.polygon(rings[i], bbox);
  11310. if (clipped.length > 0) {
  11311. if (clipped[0][0] !== clipped[clipped.length - 1][0] || clipped[0][1] !== clipped[clipped.length - 1][1]) {
  11312. clipped.push(clipped[0]);
  11313. }
  11314. if (clipped.length >= 4) {
  11315. outRings.push(clipped);
  11316. }
  11317. }
  11318. }
  11319. return outRings;
  11320. }
  11321. function getGeom$1(feature$$1) {
  11322. return (feature$$1.geometry) ? feature$$1.geometry.type : feature$$1.type;
  11323. }
  11324. var pSlice = Array.prototype.slice;
  11325. function isArguments(object) {
  11326. return Object.prototype.toString.call(object) === '[object Arguments]';
  11327. }
  11328. function deepEqual(actual, expected, opts) {
  11329. if (!opts) opts = {};
  11330. // 7.1. All identical values are equivalent, as determined by ===.
  11331. if (actual === expected) {
  11332. return true;
  11333. } else if (actual instanceof Date && expected instanceof Date) {
  11334. return actual.getTime() === expected.getTime();
  11335. // 7.3. Other pairs that do not both pass typeof value == 'object',
  11336. // equivalence is determined by ==.
  11337. } else if (!actual || !expected || typeof actual != 'object' && typeof expected != 'object') {
  11338. return opts.strict ? actual === expected : actual === expected;
  11339. // 7.4. For all other Object pairs, including Array objects, equivalence is
  11340. // determined by having the same number of owned properties (as verified
  11341. // with Object.prototype.hasOwnProperty.call), the same set of keys
  11342. // (although not necessarily the same order), equivalent values for every
  11343. // corresponding key, and an identical 'prototype' property. Note: this
  11344. // accounts for both named and indexed properties on Arrays.
  11345. } else {
  11346. return objEquiv(actual, expected, opts);
  11347. }
  11348. }
  11349. function isUndefinedOrNull(value) {
  11350. return value === null || value === undefined;
  11351. }
  11352. function isBuffer(x) {
  11353. if (!x || typeof x !== 'object' || typeof x.length !== 'number') return false;
  11354. if (typeof x.copy !== 'function' || typeof x.slice !== 'function') {
  11355. return false;
  11356. }
  11357. if (x.length > 0 && typeof x[0] !== 'number') return false;
  11358. return true;
  11359. }
  11360. function objEquiv(a, b, opts) {
  11361. var i, key;
  11362. if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
  11363. return false;
  11364. // an identical 'prototype' property.
  11365. if (a.prototype !== b.prototype) return false;
  11366. //~~~I've managed to break Object.keys through screwy arguments passing.
  11367. // Converting to array solves the problem.
  11368. if (isArguments(a)) {
  11369. if (!isArguments(b)) {
  11370. return false;
  11371. }
  11372. a = pSlice.call(a);
  11373. b = pSlice.call(b);
  11374. return deepEqual(a, b, opts);
  11375. }
  11376. if (isBuffer(a)) {
  11377. if (!isBuffer(b)) {
  11378. return false;
  11379. }
  11380. if (a.length !== b.length) return false;
  11381. for (i = 0; i < a.length; i++) {
  11382. if (a[i] !== b[i]) return false;
  11383. }
  11384. return true;
  11385. }
  11386. try {
  11387. var ka = Object.keys(a),
  11388. kb = Object.keys(b);
  11389. } catch (e) { //happens when one is a string literal and the other isn't
  11390. return false;
  11391. }
  11392. // having the same number of owned properties (keys incorporates
  11393. // hasOwnProperty)
  11394. if (ka.length !== kb.length)
  11395. return false;
  11396. //the same set of keys (although not necessarily the same order),
  11397. ka.sort();
  11398. kb.sort();
  11399. //~~~cheap key test
  11400. for (i = ka.length - 1; i >= 0; i--) {
  11401. if (ka[i] !== kb[i])
  11402. return false;
  11403. }
  11404. //equivalent values for every corresponding key, and
  11405. //~~~possibly expensive deep test
  11406. for (i = ka.length - 1; i >= 0; i--) {
  11407. key = ka[i];
  11408. if (!deepEqual(a[key], b[key], opts)) return false;
  11409. }
  11410. return typeof a === typeof b;
  11411. }
  11412. /**
  11413. * Takes any LineString or Polygon and returns the overlapping lines between both features.
  11414. *
  11415. * @name lineOverlap
  11416. * @param {Geometry|Feature<LineString|MultiLineString|Polygon|MultiPolygon>} line1 any LineString or Polygon
  11417. * @param {Geometry|Feature<LineString|MultiLineString|Polygon|MultiPolygon>} line2 any LineString or Polygon
  11418. * @param {Object} [options={}] Optional parameters
  11419. * @param {number} [options.tolerance=0] Tolerance distance to match overlapping line segments (in kilometers)
  11420. * @returns {FeatureCollection<LineString>} lines(s) that are overlapping between both features
  11421. * @example
  11422. * var line1 = turf.lineString([[115, -35], [125, -30], [135, -30], [145, -35]]);
  11423. * var line2 = turf.lineString([[115, -25], [125, -30], [135, -30], [145, -25]]);
  11424. *
  11425. * var overlapping = turf.lineOverlap(line1, line2);
  11426. *
  11427. * //addToMap
  11428. * var addToMap = [line1, line2, overlapping]
  11429. */
  11430. function lineOverlap(line1, line2, options) {
  11431. // Optional parameters
  11432. options = options || {};
  11433. if (!isObject(options)) throw new Error('options is invalid');
  11434. var tolerance = options.tolerance || 0;
  11435. // Containers
  11436. var features = [];
  11437. // Create Spatial Index
  11438. var tree = geojsonRbush();
  11439. tree.load(lineSegment(line1));
  11440. var overlapSegment;
  11441. // Line Intersection
  11442. // Iterate over line segments
  11443. segmentEach(line2, function (segment) {
  11444. var doesOverlaps = false;
  11445. // Iterate over each segments which falls within the same bounds
  11446. featureEach(tree.search(segment), function (match) {
  11447. if (doesOverlaps === false) {
  11448. var coordsSegment = getCoords(segment).sort();
  11449. var coordsMatch = getCoords(match).sort();
  11450. // Segment overlaps feature
  11451. if (deepEqual(coordsSegment, coordsMatch)) {
  11452. doesOverlaps = true;
  11453. // Overlaps already exists - only append last coordinate of segment
  11454. if (overlapSegment) overlapSegment = concatSegment(overlapSegment, segment);
  11455. else overlapSegment = segment;
  11456. // Match segments which don't share nodes (Issue #901)
  11457. } else if (
  11458. (tolerance === 0) ?
  11459. booleanPointOnLine(coordsSegment[0], match) && booleanPointOnLine(coordsSegment[1], match) :
  11460. nearestPointOnLine(match, coordsSegment[0]).properties.dist <= tolerance &&
  11461. nearestPointOnLine(match, coordsSegment[1]).properties.dist <= tolerance) {
  11462. doesOverlaps = true;
  11463. if (overlapSegment) overlapSegment = concatSegment(overlapSegment, segment);
  11464. else overlapSegment = segment;
  11465. } else if (
  11466. (tolerance === 0) ?
  11467. booleanPointOnLine(coordsMatch[0], segment) && booleanPointOnLine(coordsMatch[1], segment) :
  11468. nearestPointOnLine(segment, coordsMatch[0]).properties.dist <= tolerance &&
  11469. nearestPointOnLine(segment, coordsMatch[1]).properties.dist <= tolerance) {
  11470. // Do not define (doesOverlap = true) since more matches can occur within the same segment
  11471. // doesOverlaps = true;
  11472. if (overlapSegment) overlapSegment = concatSegment(overlapSegment, match);
  11473. else overlapSegment = match;
  11474. }
  11475. }
  11476. });
  11477. // Segment doesn't overlap - add overlaps to results & reset
  11478. if (doesOverlaps === false && overlapSegment) {
  11479. features.push(overlapSegment);
  11480. overlapSegment = undefined;
  11481. }
  11482. });
  11483. // Add last segment if exists
  11484. if (overlapSegment) features.push(overlapSegment);
  11485. return featureCollection(features);
  11486. }
  11487. /**
  11488. * Concat Segment
  11489. *
  11490. * @private
  11491. * @param {Feature<LineString>} line LineString
  11492. * @param {Feature<LineString>} segment 2-vertex LineString
  11493. * @returns {Feature<LineString>} concat linestring
  11494. */
  11495. function concatSegment(line, segment) {
  11496. var coords = getCoords(segment);
  11497. var lineCoords = getCoords(line);
  11498. var start = lineCoords[0];
  11499. var end = lineCoords[lineCoords.length - 1];
  11500. var geom = line.geometry.coordinates;
  11501. if (deepEqual(coords[0], start)) geom.unshift(coords[1]);
  11502. else if (deepEqual(coords[0], end)) geom.push(coords[1]);
  11503. else if (deepEqual(coords[1], start)) geom.unshift(coords[0]);
  11504. else if (deepEqual(coords[1], end)) geom.push(coords[0]);
  11505. return line;
  11506. }
  11507. /**
  11508. * Creates a circular sector of a circle of given radius and center {@link Point},
  11509. * between (clockwise) bearing1 and bearing2; 0 bearing is North of center point, positive clockwise.
  11510. *
  11511. * @name sector
  11512. * @param {Coord} center center point
  11513. * @param {number} radius radius of the circle
  11514. * @param {number} bearing1 angle, in decimal degrees, of the first radius of the sector
  11515. * @param {number} bearing2 angle, in decimal degrees, of the second radius of the sector
  11516. * @param {Object} [options={}] Optional parameters
  11517. * @param {string} [options.units='kilometers'] miles, kilometers, degrees, or radians
  11518. * @param {number} [options.steps=64] number of steps
  11519. * @returns {Feature<Polygon>} sector polygon
  11520. * @example
  11521. * var center = turf.point([-75, 40]);
  11522. * var radius = 5;
  11523. * var bearing1 = 25;
  11524. * var bearing2 = 45;
  11525. *
  11526. * var sector = turf.sector(center, radius, bearing1, bearing2);
  11527. *
  11528. * //addToMap
  11529. * var addToMap = [center, sector];
  11530. */
  11531. function sector(center, radius, bearing1, bearing2, options) {
  11532. // Optional parameters
  11533. options = options || {};
  11534. if (!isObject(options)) throw new Error('options is invalid');
  11535. // validation
  11536. if (!center) throw new Error('center is required');
  11537. if (bearing1 === undefined || bearing1 === null) throw new Error('bearing1 is required');
  11538. if (bearing2 === undefined || bearing2 === null) throw new Error('bearing2 is required');
  11539. if (!radius) throw new Error('radius is required');
  11540. if (typeof options !== 'object') throw new Error('options must be an object');
  11541. if (convertAngleTo360$1(bearing1) === convertAngleTo360$1(bearing2)) {
  11542. return circle(center, radius, options);
  11543. }
  11544. var coords = getCoords(center);
  11545. var arc = lineArc(center, radius, bearing1, bearing2, options);
  11546. var sliceCoords = [[coords]];
  11547. coordEach(arc, function (currentCoords) {
  11548. sliceCoords[0].push(currentCoords);
  11549. });
  11550. sliceCoords[0].push(coords);
  11551. return polygon(sliceCoords);
  11552. }
  11553. /**
  11554. * Takes any angle in degrees
  11555. * and returns a valid angle between 0-360 degrees
  11556. *
  11557. * @private
  11558. * @param {number} alfa angle between -180-180 degrees
  11559. * @returns {number} angle between 0-360 degrees
  11560. */
  11561. function convertAngleTo360$1(alfa) {
  11562. var beta = alfa % 360;
  11563. if (beta < 0) beta += 360;
  11564. return beta;
  11565. }
  11566. // https://en.wikipedia.org/wiki/Rhumb_line
  11567. /**
  11568. * Returns the destination {@link Point} having travelled the given distance along a Rhumb line from the
  11569. * origin Point with the (varant) given bearing.
  11570. *
  11571. * @name rhumbDestination
  11572. * @param {Coord} origin starting point
  11573. * @param {number} distance distance from the starting point
  11574. * @param {number} bearing varant bearing angle ranging from -180 to 180 degrees from north
  11575. * @param {Object} [options={}] Optional parameters
  11576. * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers
  11577. * @param {Object} [options.properties={}] translate properties to destination point
  11578. * @returns {Feature<Point>} Destination point.
  11579. * @example
  11580. * var pt = turf.point([-75.343, 39.984], {"marker-color": "F00"});
  11581. * var distance = 50;
  11582. * var bearing = 90;
  11583. * var options = {units: 'miles'};
  11584. *
  11585. * var destination = turf.rhumbDestination(pt, distance, bearing, options);
  11586. *
  11587. * //addToMap
  11588. * var addToMap = [pt, destination]
  11589. * destination.properties['marker-color'] = '#00F';
  11590. */
  11591. function rhumbDestination(origin, distance, bearing, options) {
  11592. // Optional parameters
  11593. options = options || {};
  11594. if (!isObject(options)) throw new Error('options is invalid');
  11595. var units = options.units;
  11596. var properties = options.properties;
  11597. // validation
  11598. if (!origin) throw new Error('origin is required');
  11599. if (distance === undefined || distance === null) throw new Error('distance is required');
  11600. if (bearing === undefined || bearing === null) throw new Error('bearing is required');
  11601. if (!(distance >= 0)) throw new Error('distance must be greater than 0');
  11602. var distanceInMeters = convertLength(distance, units, 'meters');
  11603. var coords = getCoord(origin);
  11604. var destination = calculateRhumbDestination(coords, distanceInMeters, bearing);
  11605. // compensate the crossing of the 180th meridian (https://macwright.org/2016/09/26/the-180th-meridian.html)
  11606. // solution from https://github.com/mapbox/mapbox-gl-js/issues/3250#issuecomment-294887678
  11607. destination[0] += (destination[0] - coords[0] > 180) ? -360 : (coords[0] - destination[0] > 180) ? 360 : 0;
  11608. return point(destination, properties);
  11609. }
  11610. /**
  11611. * Returns the destination point having travelled along a rhumb line from origin point the given
  11612. * distance on the given bearing.
  11613. * Adapted from Geodesy: http://www.movable-type.co.uk/scripts/latlong.html#rhumblines
  11614. *
  11615. * @private
  11616. * @param {Array<number>} origin - point
  11617. * @param {number} distance - Distance travelled, in same units as earth radius (default: metres).
  11618. * @param {number} bearing - Bearing in degrees from north.
  11619. * @param {number} [radius=6371e3] - (Mean) radius of earth (defaults to radius in metres).
  11620. * @returns {Array<number>} Destination point.
  11621. */
  11622. function calculateRhumbDestination(origin, distance, bearing, radius) {
  11623. // φ => phi
  11624. // λ => lambda
  11625. // ψ => psi
  11626. // Δ => Delta
  11627. // δ => delta
  11628. // θ => theta
  11629. radius = (radius === undefined) ? earthRadius : Number(radius);
  11630. var delta = distance / radius; // angular distance in radians
  11631. var lambda1 = origin[0] * Math.PI / 180; // to radians, but without normalize to 𝜋
  11632. var phi1 = degreesToRadians(origin[1]);
  11633. var theta = degreesToRadians(bearing);
  11634. var DeltaPhi = delta * Math.cos(theta);
  11635. var phi2 = phi1 + DeltaPhi;
  11636. // check for some daft bugger going past the pole, normalise latitude if so
  11637. if (Math.abs(phi2) > Math.PI / 2) phi2 = phi2 > 0 ? Math.PI - phi2 : -Math.PI - phi2;
  11638. var DeltaPsi = Math.log(Math.tan(phi2 / 2 + Math.PI / 4) / Math.tan(phi1 / 2 + Math.PI / 4));
  11639. var q = Math.abs(DeltaPsi) > 10e-12 ? DeltaPhi / DeltaPsi : Math.cos(phi1); // E-W course becomes ill-conditioned with 0/0
  11640. var DeltaLambda = delta * Math.sin(theta) / q;
  11641. var lambda2 = lambda1 + DeltaLambda;
  11642. return [((lambda2 * 180 / Math.PI) + 540) % 360 - 180, phi2 * 180 / Math.PI]; // normalise to −180..+180°
  11643. }
  11644. /**
  11645. * Finds the tangents of a {@link Polygon|(Multi)Polygon} from a {@link Point}.
  11646. *
  11647. * @name polygonTangents
  11648. * @param {Coord} pt to calculate the tangent points from
  11649. * @param {Feature<Polygon|MultiPolygon>} polygon to get tangents from
  11650. * @returns {FeatureCollection<Point>} Feature Collection containing the two tangent points
  11651. * @example
  11652. * var polygon = turf.polygon([[[11, 0], [22, 4], [31, 0], [31, 11], [21, 15], [11, 11], [11, 0]]]);
  11653. * var point = turf.point([61, 5]);
  11654. *
  11655. * var tangents = turf.polygonTangents(point, polygon)
  11656. *
  11657. * //addToMap
  11658. * var addToMap = [tangents, point, polygon];
  11659. */
  11660. function polygonTangents(pt, polygon$$1) {
  11661. var pointCoords = getCoords(pt);
  11662. var polyCoords = getCoords(polygon$$1);
  11663. var rtan;
  11664. var ltan;
  11665. var enext;
  11666. var eprev;
  11667. var type = getType(polygon$$1);
  11668. switch (type) {
  11669. case 'Polygon':
  11670. rtan = polyCoords[0][0];
  11671. ltan = polyCoords[0][0];
  11672. eprev = isLeft(polyCoords[0][0], polyCoords[0][polyCoords[0].length - 1], pointCoords);
  11673. var out = processPolygon$1(polyCoords[0], pointCoords, eprev, enext, rtan, ltan);
  11674. rtan = out[0];
  11675. ltan = out[1];
  11676. break;
  11677. case 'MultiPolygon':
  11678. rtan = polyCoords[0][0][0];
  11679. ltan = polyCoords[0][0][0];
  11680. eprev = isLeft(polyCoords[0][0][0], polyCoords[0][0][polyCoords[0][0].length - 1], pointCoords);
  11681. polyCoords.forEach(function (ring) {
  11682. var out = processPolygon$1(ring[0], pointCoords, eprev, enext, rtan, ltan);
  11683. rtan = out[0];
  11684. ltan = out[1];
  11685. });
  11686. break;
  11687. }
  11688. return featureCollection([point(rtan), point(ltan)]);
  11689. }
  11690. function processPolygon$1(polygonCoords, ptCoords, eprev, enext, rtan, ltan) {
  11691. for (var i = 0; i < polygonCoords.length; i++) {
  11692. var currentCoords = polygonCoords[i];
  11693. var nextCoordPair = polygonCoords[i + 1];
  11694. if (i === polygonCoords.length - 1) {
  11695. nextCoordPair = polygonCoords[0];
  11696. }
  11697. enext = isLeft(currentCoords, nextCoordPair, ptCoords);
  11698. if (eprev <= 0 && enext > 0) {
  11699. if (!isBelow(ptCoords, currentCoords, rtan)) {
  11700. rtan = currentCoords;
  11701. }
  11702. } else if (eprev > 0 && enext <= 0) {
  11703. if (!isAbove(ptCoords, currentCoords, ltan)) {
  11704. ltan = currentCoords;
  11705. }
  11706. }
  11707. eprev = enext;
  11708. }
  11709. return [rtan, ltan];
  11710. }
  11711. function isAbove(point1, point2, point3) {
  11712. return isLeft(point1, point2, point3) > 0;
  11713. }
  11714. function isBelow(point1, point2, point3) {
  11715. return isLeft(point1, point2, point3) < 0;
  11716. }
  11717. function isLeft(point1, point2, point3) {
  11718. return (point2[0] - point1[0]) * (point3[1] - point1[1]) - (point3[0] - point1[0]) * (point2[1] - point1[1]);
  11719. }
  11720. /**
  11721. * Takes a ring and return true or false whether or not the ring is clockwise or counter-clockwise.
  11722. *
  11723. * @name booleanClockwise
  11724. * @param {Feature<LineString>} line to be evaluated
  11725. * @returns {boolean} true/false
  11726. * @example
  11727. * var clockwiseRing = turf.lineString([[0,0],[1,1],[1,0],[0,0]]);
  11728. * var counterClockwiseRing = turf.lineString([[0,0],[1,0],[1,1],[0,0]]);
  11729. *
  11730. * turf.booleanClockwise(clockwiseRing)
  11731. * //=true
  11732. * turf.booleanClockwise(counterClockwiseRing)
  11733. * //=false
  11734. */
  11735. function booleanClockwise(line) {
  11736. // validation
  11737. if (!line) throw new Error('line is required');
  11738. var type = (line.geometry) ? line.geometry.type : line.type;
  11739. if (!Array.isArray(line) && type !== 'LineString') throw new Error('geometry must be a LineString');
  11740. var ring = getCoords(line);
  11741. var sum = 0;
  11742. var i = 1;
  11743. var prev, cur;
  11744. while (i < ring.length) {
  11745. prev = cur || ring[0];
  11746. cur = ring[i];
  11747. sum += ((cur[0] - prev[0]) * (cur[1] + prev[1]));
  11748. i++;
  11749. }
  11750. return sum > 0;
  11751. }
  11752. /**
  11753. * Rewind {@link LineString|(Multi)LineString} or {@link Polygon|(Multi)Polygon} outer ring counterclockwise and inner rings clockwise (Uses {@link http://en.wikipedia.org/wiki/Shoelace_formula|Shoelace Formula}).
  11754. *
  11755. * @name rewind
  11756. * @param {GeoJSON} geojson input GeoJSON Polygon
  11757. * @param {Object} [options={}] Optional parameters
  11758. * @param {boolean} [options.reverse=false] enable reverse winding
  11759. * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
  11760. * @returns {GeoJSON} rewind Polygon
  11761. * @example
  11762. * var polygon = turf.polygon([[[121, -29], [138, -29], [138, -18], [121, -18], [121, -29]]]);
  11763. *
  11764. * var rewind = turf.rewind(polygon);
  11765. *
  11766. * //addToMap
  11767. * var addToMap = [rewind];
  11768. */
  11769. function rewind(geojson, options) {
  11770. // Optional parameters
  11771. options = options || {};
  11772. if (!isObject(options)) throw new Error('options is invalid');
  11773. var reverse = options.reverse || false;
  11774. var mutate = options.mutate || false;
  11775. // validation
  11776. if (!geojson) throw new Error('<geojson> is required');
  11777. if (typeof reverse !== 'boolean') throw new Error('<reverse> must be a boolean');
  11778. if (typeof mutate !== 'boolean') throw new Error('<mutate> must be a boolean');
  11779. // prevent input mutation
  11780. if (mutate === false) geojson = clone(geojson);
  11781. // Support Feature Collection or Geometry Collection
  11782. var results = [];
  11783. switch (geojson.type) {
  11784. case 'GeometryCollection':
  11785. geomEach(geojson, function (geometry$$1) {
  11786. rewindFeature(geometry$$1, reverse);
  11787. });
  11788. return geojson;
  11789. case 'FeatureCollection':
  11790. featureEach(geojson, function (feature$$1) {
  11791. featureEach(rewindFeature(feature$$1, reverse), function (result) {
  11792. results.push(result);
  11793. });
  11794. });
  11795. return featureCollection(results);
  11796. }
  11797. // Support Feature or Geometry Objects
  11798. return rewindFeature(geojson, reverse);
  11799. }
  11800. /**
  11801. * Rewind
  11802. *
  11803. * @private
  11804. * @param {Geometry|Feature<any>} geojson Geometry or Feature
  11805. * @param {Boolean} [reverse=false] enable reverse winding
  11806. * @returns {Geometry|Feature<any>} rewind Geometry or Feature
  11807. */
  11808. function rewindFeature(geojson, reverse) {
  11809. var type = (geojson.type === 'Feature') ? geojson.geometry.type : geojson.type;
  11810. // Support all GeoJSON Geometry Objects
  11811. switch (type) {
  11812. case 'GeometryCollection':
  11813. geomEach(geojson, function (geometry$$1) {
  11814. rewindFeature(geometry$$1, reverse);
  11815. });
  11816. return geojson;
  11817. case 'LineString':
  11818. rewindLineString(getCoords(geojson), reverse);
  11819. return geojson;
  11820. case 'Polygon':
  11821. rewindPolygon(getCoords(geojson), reverse);
  11822. return geojson;
  11823. case 'MultiLineString':
  11824. getCoords(geojson).forEach(function (lineCoords) {
  11825. rewindLineString(lineCoords, reverse);
  11826. });
  11827. return geojson;
  11828. case 'MultiPolygon':
  11829. getCoords(geojson).forEach(function (lineCoords) {
  11830. rewindPolygon(lineCoords, reverse);
  11831. });
  11832. return geojson;
  11833. case 'Point':
  11834. case 'MultiPoint':
  11835. return geojson;
  11836. }
  11837. }
  11838. /**
  11839. * Rewind LineString - outer ring clockwise
  11840. *
  11841. * @private
  11842. * @param {Array<Array<number>>} coords GeoJSON LineString geometry coordinates
  11843. * @param {Boolean} [reverse=false] enable reverse winding
  11844. * @returns {void} mutates coordinates
  11845. */
  11846. function rewindLineString(coords, reverse) {
  11847. if (booleanClockwise(coords) === reverse) coords.reverse();
  11848. }
  11849. /**
  11850. * Rewind Polygon - outer ring counterclockwise and inner rings clockwise.
  11851. *
  11852. * @private
  11853. * @param {Array<Array<Array<number>>>} coords GeoJSON Polygon geometry coordinates
  11854. * @param {Boolean} [reverse=false] enable reverse winding
  11855. * @returns {void} mutates coordinates
  11856. */
  11857. function rewindPolygon(coords, reverse) {
  11858. // outer ring
  11859. if (booleanClockwise(coords[0]) !== reverse) {
  11860. coords[0].reverse();
  11861. }
  11862. // inner rings
  11863. for (var i = 1; i < coords.length; i++) {
  11864. if (booleanClockwise(coords[i]) === reverse) {
  11865. coords[i].reverse();
  11866. }
  11867. }
  11868. }
  11869. /**
  11870. * Takes a {@link Point} grid and returns a correspondent matrix {Array<Array<number>>}
  11871. * of the 'property' values
  11872. *
  11873. * @name gridToMatrix
  11874. * @param {FeatureCollection<Point>} grid of points
  11875. * @param {Object} [options={}] Optional parameters
  11876. * @param {string} [options.zProperty='elevation'] the property name in `points` from which z-values will be pulled
  11877. * @param {boolean} [options.flip=false] returns the matrix upside-down
  11878. * @param {boolean} [options.flags=false] flags, adding a `matrixPosition` array field ([row, column]) to its properties,
  11879. * the grid points with coordinates on the matrix
  11880. * @returns {Array<Array<number>>} matrix of property values
  11881. * @example
  11882. * var extent = [-70.823364, -33.553984, -70.473175, -33.302986];
  11883. * var cellSize = 3;
  11884. * var grid = turf.pointGrid(extent, cellSize);
  11885. * // add a random property to each point between 0 and 60
  11886. * for (var i = 0; i < grid.features.length; i++) {
  11887. * grid.features[i].properties.elevation = (Math.random() * 60);
  11888. * }
  11889. * gridToMatrix(grid);
  11890. * //= [
  11891. * [ 1, 13, 10, 9, 10, 13, 18],
  11892. * [34, 8, 5, 4, 5, 8, 13],
  11893. * [10, 5, 2, 1, 2, 5, 4],
  11894. * [ 0, 4, 56, 19, 1, 4, 9],
  11895. * [10, 5, 2, 1, 2, 5, 10],
  11896. * [57, 8, 5, 4, 5, 0, 57],
  11897. * [ 3, 13, 10, 9, 5, 13, 18],
  11898. * [18, 13, 10, 9, 78, 13, 18]
  11899. * ]
  11900. */
  11901. function gridToMatrix$1(grid, options) {
  11902. // Optional parameters
  11903. options = options || {};
  11904. if (!isObject(options)) throw new Error('options is invalid');
  11905. var zProperty = options.zProperty || 'elevation';
  11906. var flip = options.flip;
  11907. var flags = options.flags;
  11908. // validation
  11909. collectionOf(grid, 'Point', 'input must contain Points');
  11910. var pointsMatrix = sortPointsByLatLng$1(grid, flip);
  11911. var matrix = [];
  11912. // create property matrix from sorted points
  11913. // looping order matters here
  11914. for (var r = 0; r < pointsMatrix.length; r++) {
  11915. var pointRow = pointsMatrix[r];
  11916. var row = [];
  11917. for (var c = 0; c < pointRow.length; c++) {
  11918. var point$$1 = pointRow[c];
  11919. // Check if zProperty exist
  11920. if (point$$1.properties[zProperty]) row.push(point$$1.properties[zProperty]);
  11921. else row.push(0);
  11922. // add flags
  11923. if (flags === true) point$$1.properties.matrixPosition = [r, c];
  11924. }
  11925. matrix.push(row);
  11926. }
  11927. return matrix;
  11928. }
  11929. /**
  11930. * Sorts points by latitude and longitude, creating a 2-dimensional array of points
  11931. *
  11932. * @private
  11933. * @param {FeatureCollection<Point>} points GeoJSON Point features
  11934. * @param {boolean} [flip=false] returns the matrix upside-down
  11935. * @returns {Array<Array<Point>>} points ordered by latitude and longitude
  11936. */
  11937. function sortPointsByLatLng$1(points$$1, flip) {
  11938. var pointsByLatitude = {};
  11939. // divide points by rows with the same latitude
  11940. featureEach(points$$1, function (point$$1) {
  11941. var lat = getCoords(point$$1)[1];
  11942. if (!pointsByLatitude[lat]) pointsByLatitude[lat] = [];
  11943. pointsByLatitude[lat].push(point$$1);
  11944. });
  11945. // sort points (with the same latitude) by longitude
  11946. var orderedRowsByLatitude = Object.keys(pointsByLatitude).map(function (lat) {
  11947. var row = pointsByLatitude[lat];
  11948. var rowOrderedByLongitude = row.sort(function (a, b) {
  11949. return getCoords(a)[0] - getCoords(b)[0];
  11950. });
  11951. return rowOrderedByLongitude;
  11952. });
  11953. // sort rows (of points with the same latitude) by latitude
  11954. var pointMatrix = orderedRowsByLatitude.sort(function (a, b) {
  11955. if (flip) return getCoords(a[0])[1] - getCoords(b[0])[1];
  11956. else return getCoords(b[0])[1] - getCoords(a[0])[1];
  11957. });
  11958. return pointMatrix;
  11959. }
  11960. /*!
  11961. * @license GNU Affero General Public License.
  11962. * Copyright (c) 2015, 2015 Ronny Lorenz <ronny@tbi.univie.ac.at>
  11963. * v. 1.2.0
  11964. * https://github.com/RaumZeit/MarchingSquares.js
  11965. */
  11966. var defaultSettings$1 = {
  11967. successCallback: null,
  11968. verbose: false,
  11969. polygons: false
  11970. };
  11971. var settings$1 = {};
  11972. /*
  11973. Compute isobands(s) of a scalar 2D field given a certain
  11974. threshold and a bandwidth by applying the Marching Squares
  11975. Algorithm. The function returns a list of path coordinates
  11976. either for individual polygons within each grid cell, or the
  11977. outline of connected polygons.
  11978. */
  11979. function isoBands(data, minV, bandwidth, options) {
  11980. /* process options */
  11981. options = options ? options : {};
  11982. var optionKeys = Object.keys(defaultSettings$1);
  11983. for (var i = 0; i < optionKeys.length; i++) {
  11984. var key = optionKeys[i];
  11985. var val = options[key];
  11986. val = ((typeof val !== 'undefined') && (val !== null)) ? val : defaultSettings$1[key];
  11987. settings$1[key] = val;
  11988. }
  11989. if (settings$1.verbose)
  11990. console.log('MarchingSquaresJS-isoBands: computing isobands for [' + minV + ':' + (minV + bandwidth) + ']');
  11991. var grid = computeBandGrid(data, minV, bandwidth);
  11992. var ret;
  11993. if (settings$1.polygons) {
  11994. if (settings$1.verbose)
  11995. console.log('MarchingSquaresJS-isoBands: returning single polygons for each grid cell');
  11996. ret = BandGrid2Areas(grid);
  11997. } else {
  11998. if (settings$1.verbose)
  11999. console.log('MarchingSquaresJS-isoBands: returning polygon paths for entire data grid');
  12000. ret = BandGrid2AreaPaths(grid);
  12001. }
  12002. if (typeof settings$1.successCallback === 'function')
  12003. settings$1.successCallback(ret);
  12004. return ret;
  12005. }
  12006. /*
  12007. Thats all for the public interface, below follows the actual
  12008. implementation
  12009. */
  12010. /* Some private variables */
  12011. var Node0 = 64;
  12012. var Node1 = 16;
  12013. var Node2 = 4;
  12014. var Node3 = 1;
  12015. /*
  12016. The look-up tables for tracing back the contour path
  12017. of isoBands
  12018. */
  12019. var isoBandNextXTL = [];
  12020. var isoBandNextYTL = [];
  12021. var isoBandNextOTL = [];
  12022. var isoBandNextXTR = [];
  12023. var isoBandNextYTR = [];
  12024. var isoBandNextOTR = [];
  12025. var isoBandNextXRT = [];
  12026. var isoBandNextYRT = [];
  12027. var isoBandNextORT = [];
  12028. var isoBandNextXRB = [];
  12029. var isoBandNextYRB = [];
  12030. var isoBandNextORB = [];
  12031. var isoBandNextXBL = [];
  12032. var isoBandNextYBL = [];
  12033. var isoBandNextOBL = [];
  12034. var isoBandNextXBR = [];
  12035. var isoBandNextYBR = [];
  12036. var isoBandNextOBR = [];
  12037. var isoBandNextXLT = [];
  12038. var isoBandNextYLT = [];
  12039. var isoBandNextOLT = [];
  12040. var isoBandNextXLB = [];
  12041. var isoBandNextYLB = [];
  12042. var isoBandNextOLB = [];
  12043. isoBandNextXRT[85] = isoBandNextXRB[85] = -1;
  12044. isoBandNextYRT[85] = isoBandNextYRB[85] = 0;
  12045. isoBandNextORT[85] = isoBandNextORB[85] = 1;
  12046. isoBandNextXLT[85] = isoBandNextXLB[85] = 1;
  12047. isoBandNextYLT[85] = isoBandNextYLB[85] = 0;
  12048. isoBandNextOLT[85] = isoBandNextOLB[85] = 1;
  12049. isoBandNextXTL[85] = isoBandNextXTR[85] = 0;
  12050. isoBandNextYTL[85] = isoBandNextYTR[85] = -1;
  12051. isoBandNextOTL[85] = isoBandNextOBL[85] = 0;
  12052. isoBandNextXBR[85] = isoBandNextXBL[85] = 0;
  12053. isoBandNextYBR[85] = isoBandNextYBL[85] = 1;
  12054. isoBandNextOTR[85] = isoBandNextOBR[85] = 1;
  12055. /* triangle cases */
  12056. isoBandNextXLB[1] = isoBandNextXLB[169] = 0;
  12057. isoBandNextYLB[1] = isoBandNextYLB[169] = -1;
  12058. isoBandNextOLB[1] = isoBandNextOLB[169] = 0;
  12059. isoBandNextXBL[1] = isoBandNextXBL[169] = -1;
  12060. isoBandNextYBL[1] = isoBandNextYBL[169] = 0;
  12061. isoBandNextOBL[1] = isoBandNextOBL[169] = 0;
  12062. isoBandNextXRB[4] = isoBandNextXRB[166] = 0;
  12063. isoBandNextYRB[4] = isoBandNextYRB[166] = -1;
  12064. isoBandNextORB[4] = isoBandNextORB[166] = 1;
  12065. isoBandNextXBR[4] = isoBandNextXBR[166] = 1;
  12066. isoBandNextYBR[4] = isoBandNextYBR[166] = 0;
  12067. isoBandNextOBR[4] = isoBandNextOBR[166] = 0;
  12068. isoBandNextXRT[16] = isoBandNextXRT[154] = 0;
  12069. isoBandNextYRT[16] = isoBandNextYRT[154] = 1;
  12070. isoBandNextORT[16] = isoBandNextORT[154] = 1;
  12071. isoBandNextXTR[16] = isoBandNextXTR[154] = 1;
  12072. isoBandNextYTR[16] = isoBandNextYTR[154] = 0;
  12073. isoBandNextOTR[16] = isoBandNextOTR[154] = 1;
  12074. isoBandNextXLT[64] = isoBandNextXLT[106] = 0;
  12075. isoBandNextYLT[64] = isoBandNextYLT[106] = 1;
  12076. isoBandNextOLT[64] = isoBandNextOLT[106] = 0;
  12077. isoBandNextXTL[64] = isoBandNextXTL[106] = -1;
  12078. isoBandNextYTL[64] = isoBandNextYTL[106] = 0;
  12079. isoBandNextOTL[64] = isoBandNextOTL[106] = 1;
  12080. /* single trapezoid cases */
  12081. isoBandNextXLT[2] = isoBandNextXLT[168] = 0;
  12082. isoBandNextYLT[2] = isoBandNextYLT[168] = -1;
  12083. isoBandNextOLT[2] = isoBandNextOLT[168] = 1;
  12084. isoBandNextXLB[2] = isoBandNextXLB[168] = 0;
  12085. isoBandNextYLB[2] = isoBandNextYLB[168] = -1;
  12086. isoBandNextOLB[2] = isoBandNextOLB[168] = 0;
  12087. isoBandNextXBL[2] = isoBandNextXBL[168] = -1;
  12088. isoBandNextYBL[2] = isoBandNextYBL[168] = 0;
  12089. isoBandNextOBL[2] = isoBandNextOBL[168] = 0;
  12090. isoBandNextXBR[2] = isoBandNextXBR[168] = -1;
  12091. isoBandNextYBR[2] = isoBandNextYBR[168] = 0;
  12092. isoBandNextOBR[2] = isoBandNextOBR[168] = 1;
  12093. isoBandNextXRT[8] = isoBandNextXRT[162] = 0;
  12094. isoBandNextYRT[8] = isoBandNextYRT[162] = -1;
  12095. isoBandNextORT[8] = isoBandNextORT[162] = 0;
  12096. isoBandNextXRB[8] = isoBandNextXRB[162] = 0;
  12097. isoBandNextYRB[8] = isoBandNextYRB[162] = -1;
  12098. isoBandNextORB[8] = isoBandNextORB[162] = 1;
  12099. isoBandNextXBL[8] = isoBandNextXBL[162] = 1;
  12100. isoBandNextYBL[8] = isoBandNextYBL[162] = 0;
  12101. isoBandNextOBL[8] = isoBandNextOBL[162] = 1;
  12102. isoBandNextXBR[8] = isoBandNextXBR[162] = 1;
  12103. isoBandNextYBR[8] = isoBandNextYBR[162] = 0;
  12104. isoBandNextOBR[8] = isoBandNextOBR[162] = 0;
  12105. isoBandNextXRT[32] = isoBandNextXRT[138] = 0;
  12106. isoBandNextYRT[32] = isoBandNextYRT[138] = 1;
  12107. isoBandNextORT[32] = isoBandNextORT[138] = 1;
  12108. isoBandNextXRB[32] = isoBandNextXRB[138] = 0;
  12109. isoBandNextYRB[32] = isoBandNextYRB[138] = 1;
  12110. isoBandNextORB[32] = isoBandNextORB[138] = 0;
  12111. isoBandNextXTL[32] = isoBandNextXTL[138] = 1;
  12112. isoBandNextYTL[32] = isoBandNextYTL[138] = 0;
  12113. isoBandNextOTL[32] = isoBandNextOTL[138] = 0;
  12114. isoBandNextXTR[32] = isoBandNextXTR[138] = 1;
  12115. isoBandNextYTR[32] = isoBandNextYTR[138] = 0;
  12116. isoBandNextOTR[32] = isoBandNextOTR[138] = 1;
  12117. isoBandNextXLB[128] = isoBandNextXLB[42] = 0;
  12118. isoBandNextYLB[128] = isoBandNextYLB[42] = 1;
  12119. isoBandNextOLB[128] = isoBandNextOLB[42] = 1;
  12120. isoBandNextXLT[128] = isoBandNextXLT[42] = 0;
  12121. isoBandNextYLT[128] = isoBandNextYLT[42] = 1;
  12122. isoBandNextOLT[128] = isoBandNextOLT[42] = 0;
  12123. isoBandNextXTL[128] = isoBandNextXTL[42] = -1;
  12124. isoBandNextYTL[128] = isoBandNextYTL[42] = 0;
  12125. isoBandNextOTL[128] = isoBandNextOTL[42] = 1;
  12126. isoBandNextXTR[128] = isoBandNextXTR[42] = -1;
  12127. isoBandNextYTR[128] = isoBandNextYTR[42] = 0;
  12128. isoBandNextOTR[128] = isoBandNextOTR[42] = 0;
  12129. /* single rectangle cases */
  12130. isoBandNextXRB[5] = isoBandNextXRB[165] = -1;
  12131. isoBandNextYRB[5] = isoBandNextYRB[165] = 0;
  12132. isoBandNextORB[5] = isoBandNextORB[165] = 0;
  12133. isoBandNextXLB[5] = isoBandNextXLB[165] = 1;
  12134. isoBandNextYLB[5] = isoBandNextYLB[165] = 0;
  12135. isoBandNextOLB[5] = isoBandNextOLB[165] = 0;
  12136. isoBandNextXBR[20] = isoBandNextXBR[150] = 0;
  12137. isoBandNextYBR[20] = isoBandNextYBR[150] = 1;
  12138. isoBandNextOBR[20] = isoBandNextOBR[150] = 1;
  12139. isoBandNextXTR[20] = isoBandNextXTR[150] = 0;
  12140. isoBandNextYTR[20] = isoBandNextYTR[150] = -1;
  12141. isoBandNextOTR[20] = isoBandNextOTR[150] = 1;
  12142. isoBandNextXRT[80] = isoBandNextXRT[90] = -1;
  12143. isoBandNextYRT[80] = isoBandNextYRT[90] = 0;
  12144. isoBandNextORT[80] = isoBandNextORT[90] = 1;
  12145. isoBandNextXLT[80] = isoBandNextXLT[90] = 1;
  12146. isoBandNextYLT[80] = isoBandNextYLT[90] = 0;
  12147. isoBandNextOLT[80] = isoBandNextOLT[90] = 1;
  12148. isoBandNextXBL[65] = isoBandNextXBL[105] = 0;
  12149. isoBandNextYBL[65] = isoBandNextYBL[105] = 1;
  12150. isoBandNextOBL[65] = isoBandNextOBL[105] = 0;
  12151. isoBandNextXTL[65] = isoBandNextXTL[105] = 0;
  12152. isoBandNextYTL[65] = isoBandNextYTL[105] = -1;
  12153. isoBandNextOTL[65] = isoBandNextOTL[105] = 0;
  12154. isoBandNextXRT[160] = isoBandNextXRT[10] = -1;
  12155. isoBandNextYRT[160] = isoBandNextYRT[10] = 0;
  12156. isoBandNextORT[160] = isoBandNextORT[10] = 1;
  12157. isoBandNextXRB[160] = isoBandNextXRB[10] = -1;
  12158. isoBandNextYRB[160] = isoBandNextYRB[10] = 0;
  12159. isoBandNextORB[160] = isoBandNextORB[10] = 0;
  12160. isoBandNextXLB[160] = isoBandNextXLB[10] = 1;
  12161. isoBandNextYLB[160] = isoBandNextYLB[10] = 0;
  12162. isoBandNextOLB[160] = isoBandNextOLB[10] = 0;
  12163. isoBandNextXLT[160] = isoBandNextXLT[10] = 1;
  12164. isoBandNextYLT[160] = isoBandNextYLT[10] = 0;
  12165. isoBandNextOLT[160] = isoBandNextOLT[10] = 1;
  12166. isoBandNextXBR[130] = isoBandNextXBR[40] = 0;
  12167. isoBandNextYBR[130] = isoBandNextYBR[40] = 1;
  12168. isoBandNextOBR[130] = isoBandNextOBR[40] = 1;
  12169. isoBandNextXBL[130] = isoBandNextXBL[40] = 0;
  12170. isoBandNextYBL[130] = isoBandNextYBL[40] = 1;
  12171. isoBandNextOBL[130] = isoBandNextOBL[40] = 0;
  12172. isoBandNextXTL[130] = isoBandNextXTL[40] = 0;
  12173. isoBandNextYTL[130] = isoBandNextYTL[40] = -1;
  12174. isoBandNextOTL[130] = isoBandNextOTL[40] = 0;
  12175. isoBandNextXTR[130] = isoBandNextXTR[40] = 0;
  12176. isoBandNextYTR[130] = isoBandNextYTR[40] = -1;
  12177. isoBandNextOTR[130] = isoBandNextOTR[40] = 1;
  12178. /* single hexagon cases */
  12179. isoBandNextXRB[37] = isoBandNextXRB[133] = 0;
  12180. isoBandNextYRB[37] = isoBandNextYRB[133] = 1;
  12181. isoBandNextORB[37] = isoBandNextORB[133] = 1;
  12182. isoBandNextXLB[37] = isoBandNextXLB[133] = 0;
  12183. isoBandNextYLB[37] = isoBandNextYLB[133] = 1;
  12184. isoBandNextOLB[37] = isoBandNextOLB[133] = 0;
  12185. isoBandNextXTL[37] = isoBandNextXTL[133] = -1;
  12186. isoBandNextYTL[37] = isoBandNextYTL[133] = 0;
  12187. isoBandNextOTL[37] = isoBandNextOTL[133] = 0;
  12188. isoBandNextXTR[37] = isoBandNextXTR[133] = 1;
  12189. isoBandNextYTR[37] = isoBandNextYTR[133] = 0;
  12190. isoBandNextOTR[37] = isoBandNextOTR[133] = 0;
  12191. isoBandNextXBR[148] = isoBandNextXBR[22] = -1;
  12192. isoBandNextYBR[148] = isoBandNextYBR[22] = 0;
  12193. isoBandNextOBR[148] = isoBandNextOBR[22] = 0;
  12194. isoBandNextXLB[148] = isoBandNextXLB[22] = 0;
  12195. isoBandNextYLB[148] = isoBandNextYLB[22] = -1;
  12196. isoBandNextOLB[148] = isoBandNextOLB[22] = 1;
  12197. isoBandNextXLT[148] = isoBandNextXLT[22] = 0;
  12198. isoBandNextYLT[148] = isoBandNextYLT[22] = 1;
  12199. isoBandNextOLT[148] = isoBandNextOLT[22] = 1;
  12200. isoBandNextXTR[148] = isoBandNextXTR[22] = -1;
  12201. isoBandNextYTR[148] = isoBandNextYTR[22] = 0;
  12202. isoBandNextOTR[148] = isoBandNextOTR[22] = 1;
  12203. isoBandNextXRT[82] = isoBandNextXRT[88] = 0;
  12204. isoBandNextYRT[82] = isoBandNextYRT[88] = -1;
  12205. isoBandNextORT[82] = isoBandNextORT[88] = 1;
  12206. isoBandNextXBR[82] = isoBandNextXBR[88] = 1;
  12207. isoBandNextYBR[82] = isoBandNextYBR[88] = 0;
  12208. isoBandNextOBR[82] = isoBandNextOBR[88] = 1;
  12209. isoBandNextXBL[82] = isoBandNextXBL[88] = -1;
  12210. isoBandNextYBL[82] = isoBandNextYBL[88] = 0;
  12211. isoBandNextOBL[82] = isoBandNextOBL[88] = 1;
  12212. isoBandNextXLT[82] = isoBandNextXLT[88] = 0;
  12213. isoBandNextYLT[82] = isoBandNextYLT[88] = -1;
  12214. isoBandNextOLT[82] = isoBandNextOLT[88] = 0;
  12215. isoBandNextXRT[73] = isoBandNextXRT[97] = 0;
  12216. isoBandNextYRT[73] = isoBandNextYRT[97] = 1;
  12217. isoBandNextORT[73] = isoBandNextORT[97] = 0;
  12218. isoBandNextXRB[73] = isoBandNextXRB[97] = 0;
  12219. isoBandNextYRB[73] = isoBandNextYRB[97] = -1;
  12220. isoBandNextORB[73] = isoBandNextORB[97] = 0;
  12221. isoBandNextXBL[73] = isoBandNextXBL[97] = 1;
  12222. isoBandNextYBL[73] = isoBandNextYBL[97] = 0;
  12223. isoBandNextOBL[73] = isoBandNextOBL[97] = 0;
  12224. isoBandNextXTL[73] = isoBandNextXTL[97] = 1;
  12225. isoBandNextYTL[73] = isoBandNextYTL[97] = 0;
  12226. isoBandNextOTL[73] = isoBandNextOTL[97] = 1;
  12227. isoBandNextXRT[145] = isoBandNextXRT[25] = 0;
  12228. isoBandNextYRT[145] = isoBandNextYRT[25] = -1;
  12229. isoBandNextORT[145] = isoBandNextORT[25] = 0;
  12230. isoBandNextXBL[145] = isoBandNextXBL[25] = 1;
  12231. isoBandNextYBL[145] = isoBandNextYBL[25] = 0;
  12232. isoBandNextOBL[145] = isoBandNextOBL[25] = 1;
  12233. isoBandNextXLB[145] = isoBandNextXLB[25] = 0;
  12234. isoBandNextYLB[145] = isoBandNextYLB[25] = 1;
  12235. isoBandNextOLB[145] = isoBandNextOLB[25] = 1;
  12236. isoBandNextXTR[145] = isoBandNextXTR[25] = -1;
  12237. isoBandNextYTR[145] = isoBandNextYTR[25] = 0;
  12238. isoBandNextOTR[145] = isoBandNextOTR[25] = 0;
  12239. isoBandNextXRB[70] = isoBandNextXRB[100] = 0;
  12240. isoBandNextYRB[70] = isoBandNextYRB[100] = 1;
  12241. isoBandNextORB[70] = isoBandNextORB[100] = 0;
  12242. isoBandNextXBR[70] = isoBandNextXBR[100] = -1;
  12243. isoBandNextYBR[70] = isoBandNextYBR[100] = 0;
  12244. isoBandNextOBR[70] = isoBandNextOBR[100] = 1;
  12245. isoBandNextXLT[70] = isoBandNextXLT[100] = 0;
  12246. isoBandNextYLT[70] = isoBandNextYLT[100] = -1;
  12247. isoBandNextOLT[70] = isoBandNextOLT[100] = 1;
  12248. isoBandNextXTL[70] = isoBandNextXTL[100] = 1;
  12249. isoBandNextYTL[70] = isoBandNextYTL[100] = 0;
  12250. isoBandNextOTL[70] = isoBandNextOTL[100] = 0;
  12251. /* single pentagon cases */
  12252. isoBandNextXRB[101] = isoBandNextXRB[69] = 0;
  12253. isoBandNextYRB[101] = isoBandNextYRB[69] = 1;
  12254. isoBandNextORB[101] = isoBandNextORB[69] = 0;
  12255. isoBandNextXTL[101] = isoBandNextXTL[69] = 1;
  12256. isoBandNextYTL[101] = isoBandNextYTL[69] = 0;
  12257. isoBandNextOTL[101] = isoBandNextOTL[69] = 0;
  12258. isoBandNextXLB[149] = isoBandNextXLB[21] = 0;
  12259. isoBandNextYLB[149] = isoBandNextYLB[21] = 1;
  12260. isoBandNextOLB[149] = isoBandNextOLB[21] = 1;
  12261. isoBandNextXTR[149] = isoBandNextXTR[21] = -1;
  12262. isoBandNextYTR[149] = isoBandNextYTR[21] = 0;
  12263. isoBandNextOTR[149] = isoBandNextOTR[21] = 0;
  12264. isoBandNextXBR[86] = isoBandNextXBR[84] = -1;
  12265. isoBandNextYBR[86] = isoBandNextYBR[84] = 0;
  12266. isoBandNextOBR[86] = isoBandNextOBR[84] = 1;
  12267. isoBandNextXLT[86] = isoBandNextXLT[84] = 0;
  12268. isoBandNextYLT[86] = isoBandNextYLT[84] = -1;
  12269. isoBandNextOLT[86] = isoBandNextOLT[84] = 1;
  12270. isoBandNextXRT[89] = isoBandNextXRT[81] = 0;
  12271. isoBandNextYRT[89] = isoBandNextYRT[81] = -1;
  12272. isoBandNextORT[89] = isoBandNextORT[81] = 0;
  12273. isoBandNextXBL[89] = isoBandNextXBL[81] = 1;
  12274. isoBandNextYBL[89] = isoBandNextYBL[81] = 0;
  12275. isoBandNextOBL[89] = isoBandNextOBL[81] = 1;
  12276. isoBandNextXRT[96] = isoBandNextXRT[74] = 0;
  12277. isoBandNextYRT[96] = isoBandNextYRT[74] = 1;
  12278. isoBandNextORT[96] = isoBandNextORT[74] = 0;
  12279. isoBandNextXRB[96] = isoBandNextXRB[74] = -1;
  12280. isoBandNextYRB[96] = isoBandNextYRB[74] = 0;
  12281. isoBandNextORB[96] = isoBandNextORB[74] = 1;
  12282. isoBandNextXLT[96] = isoBandNextXLT[74] = 1;
  12283. isoBandNextYLT[96] = isoBandNextYLT[74] = 0;
  12284. isoBandNextOLT[96] = isoBandNextOLT[74] = 0;
  12285. isoBandNextXTL[96] = isoBandNextXTL[74] = 1;
  12286. isoBandNextYTL[96] = isoBandNextYTL[74] = 0;
  12287. isoBandNextOTL[96] = isoBandNextOTL[74] = 1;
  12288. isoBandNextXRT[24] = isoBandNextXRT[146] = 0;
  12289. isoBandNextYRT[24] = isoBandNextYRT[146] = -1;
  12290. isoBandNextORT[24] = isoBandNextORT[146] = 1;
  12291. isoBandNextXBR[24] = isoBandNextXBR[146] = 1;
  12292. isoBandNextYBR[24] = isoBandNextYBR[146] = 0;
  12293. isoBandNextOBR[24] = isoBandNextOBR[146] = 1;
  12294. isoBandNextXBL[24] = isoBandNextXBL[146] = 0;
  12295. isoBandNextYBL[24] = isoBandNextYBL[146] = 1;
  12296. isoBandNextOBL[24] = isoBandNextOBL[146] = 1;
  12297. isoBandNextXTR[24] = isoBandNextXTR[146] = 0;
  12298. isoBandNextYTR[24] = isoBandNextYTR[146] = -1;
  12299. isoBandNextOTR[24] = isoBandNextOTR[146] = 0;
  12300. isoBandNextXRB[6] = isoBandNextXRB[164] = -1;
  12301. isoBandNextYRB[6] = isoBandNextYRB[164] = 0;
  12302. isoBandNextORB[6] = isoBandNextORB[164] = 1;
  12303. isoBandNextXBR[6] = isoBandNextXBR[164] = -1;
  12304. isoBandNextYBR[6] = isoBandNextYBR[164] = 0;
  12305. isoBandNextOBR[6] = isoBandNextOBR[164] = 0;
  12306. isoBandNextXLB[6] = isoBandNextXLB[164] = 0;
  12307. isoBandNextYLB[6] = isoBandNextYLB[164] = -1;
  12308. isoBandNextOLB[6] = isoBandNextOLB[164] = 1;
  12309. isoBandNextXLT[6] = isoBandNextXLT[164] = 1;
  12310. isoBandNextYLT[6] = isoBandNextYLT[164] = 0;
  12311. isoBandNextOLT[6] = isoBandNextOLT[164] = 0;
  12312. isoBandNextXBL[129] = isoBandNextXBL[41] = 0;
  12313. isoBandNextYBL[129] = isoBandNextYBL[41] = 1;
  12314. isoBandNextOBL[129] = isoBandNextOBL[41] = 1;
  12315. isoBandNextXLB[129] = isoBandNextXLB[41] = 0;
  12316. isoBandNextYLB[129] = isoBandNextYLB[41] = 1;
  12317. isoBandNextOLB[129] = isoBandNextOLB[41] = 0;
  12318. isoBandNextXTL[129] = isoBandNextXTL[41] = -1;
  12319. isoBandNextYTL[129] = isoBandNextYTL[41] = 0;
  12320. isoBandNextOTL[129] = isoBandNextOTL[41] = 0;
  12321. isoBandNextXTR[129] = isoBandNextXTR[41] = 0;
  12322. isoBandNextYTR[129] = isoBandNextYTR[41] = -1;
  12323. isoBandNextOTR[129] = isoBandNextOTR[41] = 0;
  12324. isoBandNextXBR[66] = isoBandNextXBR[104] = 0;
  12325. isoBandNextYBR[66] = isoBandNextYBR[104] = 1;
  12326. isoBandNextOBR[66] = isoBandNextOBR[104] = 0;
  12327. isoBandNextXBL[66] = isoBandNextXBL[104] = -1;
  12328. isoBandNextYBL[66] = isoBandNextYBL[104] = 0;
  12329. isoBandNextOBL[66] = isoBandNextOBL[104] = 1;
  12330. isoBandNextXLT[66] = isoBandNextXLT[104] = 0;
  12331. isoBandNextYLT[66] = isoBandNextYLT[104] = -1;
  12332. isoBandNextOLT[66] = isoBandNextOLT[104] = 0;
  12333. isoBandNextXTL[66] = isoBandNextXTL[104] = 0;
  12334. isoBandNextYTL[66] = isoBandNextYTL[104] = -1;
  12335. isoBandNextOTL[66] = isoBandNextOTL[104] = 1;
  12336. isoBandNextXRT[144] = isoBandNextXRT[26] = -1;
  12337. isoBandNextYRT[144] = isoBandNextYRT[26] = 0;
  12338. isoBandNextORT[144] = isoBandNextORT[26] = 0;
  12339. isoBandNextXLB[144] = isoBandNextXLB[26] = 1;
  12340. isoBandNextYLB[144] = isoBandNextYLB[26] = 0;
  12341. isoBandNextOLB[144] = isoBandNextOLB[26] = 1;
  12342. isoBandNextXLT[144] = isoBandNextXLT[26] = 0;
  12343. isoBandNextYLT[144] = isoBandNextYLT[26] = 1;
  12344. isoBandNextOLT[144] = isoBandNextOLT[26] = 1;
  12345. isoBandNextXTR[144] = isoBandNextXTR[26] = -1;
  12346. isoBandNextYTR[144] = isoBandNextYTR[26] = 0;
  12347. isoBandNextOTR[144] = isoBandNextOTR[26] = 1;
  12348. isoBandNextXRB[36] = isoBandNextXRB[134] = 0;
  12349. isoBandNextYRB[36] = isoBandNextYRB[134] = 1;
  12350. isoBandNextORB[36] = isoBandNextORB[134] = 1;
  12351. isoBandNextXBR[36] = isoBandNextXBR[134] = 0;
  12352. isoBandNextYBR[36] = isoBandNextYBR[134] = 1;
  12353. isoBandNextOBR[36] = isoBandNextOBR[134] = 0;
  12354. isoBandNextXTL[36] = isoBandNextXTL[134] = 0;
  12355. isoBandNextYTL[36] = isoBandNextYTL[134] = -1;
  12356. isoBandNextOTL[36] = isoBandNextOTL[134] = 1;
  12357. isoBandNextXTR[36] = isoBandNextXTR[134] = 1;
  12358. isoBandNextYTR[36] = isoBandNextYTR[134] = 0;
  12359. isoBandNextOTR[36] = isoBandNextOTR[134] = 0;
  12360. isoBandNextXRT[9] = isoBandNextXRT[161] = -1;
  12361. isoBandNextYRT[9] = isoBandNextYRT[161] = 0;
  12362. isoBandNextORT[9] = isoBandNextORT[161] = 0;
  12363. isoBandNextXRB[9] = isoBandNextXRB[161] = 0;
  12364. isoBandNextYRB[9] = isoBandNextYRB[161] = -1;
  12365. isoBandNextORB[9] = isoBandNextORB[161] = 0;
  12366. isoBandNextXBL[9] = isoBandNextXBL[161] = 1;
  12367. isoBandNextYBL[9] = isoBandNextYBL[161] = 0;
  12368. isoBandNextOBL[9] = isoBandNextOBL[161] = 0;
  12369. isoBandNextXLB[9] = isoBandNextXLB[161] = 1;
  12370. isoBandNextYLB[9] = isoBandNextYLB[161] = 0;
  12371. isoBandNextOLB[9] = isoBandNextOLB[161] = 1;
  12372. /* 8-sided cases */
  12373. isoBandNextXRT[136] = 0;
  12374. isoBandNextYRT[136] = 1;
  12375. isoBandNextORT[136] = 1;
  12376. isoBandNextXRB[136] = 0;
  12377. isoBandNextYRB[136] = 1;
  12378. isoBandNextORB[136] = 0;
  12379. isoBandNextXBR[136] = -1;
  12380. isoBandNextYBR[136] = 0;
  12381. isoBandNextOBR[136] = 1;
  12382. isoBandNextXBL[136] = -1;
  12383. isoBandNextYBL[136] = 0;
  12384. isoBandNextOBL[136] = 0;
  12385. isoBandNextXLB[136] = 0;
  12386. isoBandNextYLB[136] = -1;
  12387. isoBandNextOLB[136] = 0;
  12388. isoBandNextXLT[136] = 0;
  12389. isoBandNextYLT[136] = -1;
  12390. isoBandNextOLT[136] = 1;
  12391. isoBandNextXTL[136] = 1;
  12392. isoBandNextYTL[136] = 0;
  12393. isoBandNextOTL[136] = 0;
  12394. isoBandNextXTR[136] = 1;
  12395. isoBandNextYTR[136] = 0;
  12396. isoBandNextOTR[136] = 1;
  12397. isoBandNextXRT[34] = 0;
  12398. isoBandNextYRT[34] = -1;
  12399. isoBandNextORT[34] = 0;
  12400. isoBandNextXRB[34] = 0;
  12401. isoBandNextYRB[34] = -1;
  12402. isoBandNextORB[34] = 1;
  12403. isoBandNextXBR[34] = 1;
  12404. isoBandNextYBR[34] = 0;
  12405. isoBandNextOBR[34] = 0;
  12406. isoBandNextXBL[34] = 1;
  12407. isoBandNextYBL[34] = 0;
  12408. isoBandNextOBL[34] = 1;
  12409. isoBandNextXLB[34] = 0;
  12410. isoBandNextYLB[34] = 1;
  12411. isoBandNextOLB[34] = 1;
  12412. isoBandNextXLT[34] = 0;
  12413. isoBandNextYLT[34] = 1;
  12414. isoBandNextOLT[34] = 0;
  12415. isoBandNextXTL[34] = -1;
  12416. isoBandNextYTL[34] = 0;
  12417. isoBandNextOTL[34] = 1;
  12418. isoBandNextXTR[34] = -1;
  12419. isoBandNextYTR[34] = 0;
  12420. isoBandNextOTR[34] = 0;
  12421. isoBandNextXRT[35] = 0;
  12422. isoBandNextYRT[35] = 1;
  12423. isoBandNextORT[35] = 1;
  12424. isoBandNextXRB[35] = 0;
  12425. isoBandNextYRB[35] = -1;
  12426. isoBandNextORB[35] = 1;
  12427. isoBandNextXBR[35] = 1;
  12428. isoBandNextYBR[35] = 0;
  12429. isoBandNextOBR[35] = 0;
  12430. isoBandNextXBL[35] = -1;
  12431. isoBandNextYBL[35] = 0;
  12432. isoBandNextOBL[35] = 0;
  12433. isoBandNextXLB[35] = 0;
  12434. isoBandNextYLB[35] = -1;
  12435. isoBandNextOLB[35] = 0;
  12436. isoBandNextXLT[35] = 0;
  12437. isoBandNextYLT[35] = 1;
  12438. isoBandNextOLT[35] = 0;
  12439. isoBandNextXTL[35] = -1;
  12440. isoBandNextYTL[35] = 0;
  12441. isoBandNextOTL[35] = 1;
  12442. isoBandNextXTR[35] = 1;
  12443. isoBandNextYTR[35] = 0;
  12444. isoBandNextOTR[35] = 1;
  12445. /* 6-sided cases */
  12446. isoBandNextXRT[153] = 0;
  12447. isoBandNextYRT[153] = 1;
  12448. isoBandNextORT[153] = 1;
  12449. isoBandNextXBL[153] = -1;
  12450. isoBandNextYBL[153] = 0;
  12451. isoBandNextOBL[153] = 0;
  12452. isoBandNextXLB[153] = 0;
  12453. isoBandNextYLB[153] = -1;
  12454. isoBandNextOLB[153] = 0;
  12455. isoBandNextXTR[153] = 1;
  12456. isoBandNextYTR[153] = 0;
  12457. isoBandNextOTR[153] = 1;
  12458. isoBandNextXRB[102] = 0;
  12459. isoBandNextYRB[102] = -1;
  12460. isoBandNextORB[102] = 1;
  12461. isoBandNextXBR[102] = 1;
  12462. isoBandNextYBR[102] = 0;
  12463. isoBandNextOBR[102] = 0;
  12464. isoBandNextXLT[102] = 0;
  12465. isoBandNextYLT[102] = 1;
  12466. isoBandNextOLT[102] = 0;
  12467. isoBandNextXTL[102] = -1;
  12468. isoBandNextYTL[102] = 0;
  12469. isoBandNextOTL[102] = 1;
  12470. isoBandNextXRT[155] = 0;
  12471. isoBandNextYRT[155] = -1;
  12472. isoBandNextORT[155] = 0;
  12473. isoBandNextXBL[155] = 1;
  12474. isoBandNextYBL[155] = 0;
  12475. isoBandNextOBL[155] = 1;
  12476. isoBandNextXLB[155] = 0;
  12477. isoBandNextYLB[155] = 1;
  12478. isoBandNextOLB[155] = 1;
  12479. isoBandNextXTR[155] = -1;
  12480. isoBandNextYTR[155] = 0;
  12481. isoBandNextOTR[155] = 0;
  12482. isoBandNextXRB[103] = 0;
  12483. isoBandNextYRB[103] = 1;
  12484. isoBandNextORB[103] = 0;
  12485. isoBandNextXBR[103] = -1;
  12486. isoBandNextYBR[103] = 0;
  12487. isoBandNextOBR[103] = 1;
  12488. isoBandNextXLT[103] = 0;
  12489. isoBandNextYLT[103] = -1;
  12490. isoBandNextOLT[103] = 1;
  12491. isoBandNextXTL[103] = 1;
  12492. isoBandNextYTL[103] = 0;
  12493. isoBandNextOTL[103] = 0;
  12494. /* 7-sided cases */
  12495. isoBandNextXRT[152] = 0;
  12496. isoBandNextYRT[152] = 1;
  12497. isoBandNextORT[152] = 1;
  12498. isoBandNextXBR[152] = -1;
  12499. isoBandNextYBR[152] = 0;
  12500. isoBandNextOBR[152] = 1;
  12501. isoBandNextXBL[152] = -1;
  12502. isoBandNextYBL[152] = 0;
  12503. isoBandNextOBL[152] = 0;
  12504. isoBandNextXLB[152] = 0;
  12505. isoBandNextYLB[152] = -1;
  12506. isoBandNextOLB[152] = 0;
  12507. isoBandNextXLT[152] = 0;
  12508. isoBandNextYLT[152] = -1;
  12509. isoBandNextOLT[152] = 1;
  12510. isoBandNextXTR[152] = 1;
  12511. isoBandNextYTR[152] = 0;
  12512. isoBandNextOTR[152] = 1;
  12513. isoBandNextXRT[156] = 0;
  12514. isoBandNextYRT[156] = -1;
  12515. isoBandNextORT[156] = 1;
  12516. isoBandNextXBR[156] = 1;
  12517. isoBandNextYBR[156] = 0;
  12518. isoBandNextOBR[156] = 1;
  12519. isoBandNextXBL[156] = -1;
  12520. isoBandNextYBL[156] = 0;
  12521. isoBandNextOBL[156] = 0;
  12522. isoBandNextXLB[156] = 0;
  12523. isoBandNextYLB[156] = -1;
  12524. isoBandNextOLB[156] = 0;
  12525. isoBandNextXLT[156] = 0;
  12526. isoBandNextYLT[156] = 1;
  12527. isoBandNextOLT[156] = 1;
  12528. isoBandNextXTR[156] = -1;
  12529. isoBandNextYTR[156] = 0;
  12530. isoBandNextOTR[156] = 1;
  12531. isoBandNextXRT[137] = 0;
  12532. isoBandNextYRT[137] = 1;
  12533. isoBandNextORT[137] = 1;
  12534. isoBandNextXRB[137] = 0;
  12535. isoBandNextYRB[137] = 1;
  12536. isoBandNextORB[137] = 0;
  12537. isoBandNextXBL[137] = -1;
  12538. isoBandNextYBL[137] = 0;
  12539. isoBandNextOBL[137] = 0;
  12540. isoBandNextXLB[137] = 0;
  12541. isoBandNextYLB[137] = -1;
  12542. isoBandNextOLB[137] = 0;
  12543. isoBandNextXTL[137] = 1;
  12544. isoBandNextYTL[137] = 0;
  12545. isoBandNextOTL[137] = 0;
  12546. isoBandNextXTR[137] = 1;
  12547. isoBandNextYTR[137] = 0;
  12548. isoBandNextOTR[137] = 1;
  12549. isoBandNextXRT[139] = 0;
  12550. isoBandNextYRT[139] = 1;
  12551. isoBandNextORT[139] = 1;
  12552. isoBandNextXRB[139] = 0;
  12553. isoBandNextYRB[139] = -1;
  12554. isoBandNextORB[139] = 0;
  12555. isoBandNextXBL[139] = 1;
  12556. isoBandNextYBL[139] = 0;
  12557. isoBandNextOBL[139] = 0;
  12558. isoBandNextXLB[139] = 0;
  12559. isoBandNextYLB[139] = 1;
  12560. isoBandNextOLB[139] = 0;
  12561. isoBandNextXTL[139] = -1;
  12562. isoBandNextYTL[139] = 0;
  12563. isoBandNextOTL[139] = 0;
  12564. isoBandNextXTR[139] = 1;
  12565. isoBandNextYTR[139] = 0;
  12566. isoBandNextOTR[139] = 1;
  12567. isoBandNextXRT[98] = 0;
  12568. isoBandNextYRT[98] = -1;
  12569. isoBandNextORT[98] = 0;
  12570. isoBandNextXRB[98] = 0;
  12571. isoBandNextYRB[98] = -1;
  12572. isoBandNextORB[98] = 1;
  12573. isoBandNextXBR[98] = 1;
  12574. isoBandNextYBR[98] = 0;
  12575. isoBandNextOBR[98] = 0;
  12576. isoBandNextXBL[98] = 1;
  12577. isoBandNextYBL[98] = 0;
  12578. isoBandNextOBL[98] = 1;
  12579. isoBandNextXLT[98] = 0;
  12580. isoBandNextYLT[98] = 1;
  12581. isoBandNextOLT[98] = 0;
  12582. isoBandNextXTL[98] = -1;
  12583. isoBandNextYTL[98] = 0;
  12584. isoBandNextOTL[98] = 1;
  12585. isoBandNextXRT[99] = 0;
  12586. isoBandNextYRT[99] = 1;
  12587. isoBandNextORT[99] = 0;
  12588. isoBandNextXRB[99] = 0;
  12589. isoBandNextYRB[99] = -1;
  12590. isoBandNextORB[99] = 1;
  12591. isoBandNextXBR[99] = 1;
  12592. isoBandNextYBR[99] = 0;
  12593. isoBandNextOBR[99] = 0;
  12594. isoBandNextXBL[99] = -1;
  12595. isoBandNextYBL[99] = 0;
  12596. isoBandNextOBL[99] = 1;
  12597. isoBandNextXLT[99] = 0;
  12598. isoBandNextYLT[99] = -1;
  12599. isoBandNextOLT[99] = 0;
  12600. isoBandNextXTL[99] = 1;
  12601. isoBandNextYTL[99] = 0;
  12602. isoBandNextOTL[99] = 1;
  12603. isoBandNextXRB[38] = 0;
  12604. isoBandNextYRB[38] = -1;
  12605. isoBandNextORB[38] = 1;
  12606. isoBandNextXBR[38] = 1;
  12607. isoBandNextYBR[38] = 0;
  12608. isoBandNextOBR[38] = 0;
  12609. isoBandNextXLB[38] = 0;
  12610. isoBandNextYLB[38] = 1;
  12611. isoBandNextOLB[38] = 1;
  12612. isoBandNextXLT[38] = 0;
  12613. isoBandNextYLT[38] = 1;
  12614. isoBandNextOLT[38] = 0;
  12615. isoBandNextXTL[38] = -1;
  12616. isoBandNextYTL[38] = 0;
  12617. isoBandNextOTL[38] = 1;
  12618. isoBandNextXTR[38] = -1;
  12619. isoBandNextYTR[38] = 0;
  12620. isoBandNextOTR[38] = 0;
  12621. isoBandNextXRB[39] = 0;
  12622. isoBandNextYRB[39] = 1;
  12623. isoBandNextORB[39] = 1;
  12624. isoBandNextXBR[39] = -1;
  12625. isoBandNextYBR[39] = 0;
  12626. isoBandNextOBR[39] = 0;
  12627. isoBandNextXLB[39] = 0;
  12628. isoBandNextYLB[39] = -1;
  12629. isoBandNextOLB[39] = 1;
  12630. isoBandNextXLT[39] = 0;
  12631. isoBandNextYLT[39] = 1;
  12632. isoBandNextOLT[39] = 0;
  12633. isoBandNextXTL[39] = -1;
  12634. isoBandNextYTL[39] = 0;
  12635. isoBandNextOTL[39] = 1;
  12636. isoBandNextXTR[39] = 1;
  12637. isoBandNextYTR[39] = 0;
  12638. isoBandNextOTR[39] = 0;
  12639. /*
  12640. Define helper functions for the polygon_table
  12641. */
  12642. /* triangle cases */
  12643. var p00 = function (cell) {
  12644. return [[cell.bottomleft, 0], [0, 0], [0, cell.leftbottom]];
  12645. };
  12646. var p01 = function (cell) {
  12647. return [[1, cell.rightbottom], [1, 0], [cell.bottomright, 0]];
  12648. };
  12649. var p02 = function (cell) {
  12650. return [[cell.topright, 1], [1, 1], [1, cell.righttop]];
  12651. };
  12652. var p03 = function (cell) {
  12653. return [[0, cell.lefttop], [0, 1], [cell.topleft, 1]];
  12654. };
  12655. /* trapezoid cases */
  12656. var p04 = function (cell) {
  12657. return [[cell.bottomright, 0], [cell.bottomleft, 0], [0, cell.leftbottom], [0, cell.lefttop]];
  12658. };
  12659. var p05 = function (cell) {
  12660. return [[cell.bottomright, 0], [cell.bottomleft, 0], [1, cell.righttop], [1, cell.rightbottom]];
  12661. };
  12662. var p06 = function (cell) {
  12663. return [[1, cell.righttop], [1, cell.rightbottom], [cell.topleft, 1], [cell.topright, 1]];
  12664. };
  12665. var p07 = function (cell) {
  12666. return [[0, cell.leftbottom], [0, cell.lefttop], [cell.topleft, 1], [cell.topright, 1]];
  12667. };
  12668. /* rectangle cases */
  12669. var p08 = function (cell) {
  12670. return [[0, 0], [0, cell.leftbottom], [1, cell.rightbottom], [1, 0]];
  12671. };
  12672. var p09 = function (cell) {
  12673. return [[1, 0], [cell.bottomright, 0], [cell.topright, 1], [1, 1]];
  12674. };
  12675. var p10 = function (cell) {
  12676. return [[1, 1], [1, cell.righttop], [0, cell.lefttop], [0, 1]];
  12677. };
  12678. var p11 = function (cell) {
  12679. return [[cell.bottomleft, 0], [0, 0], [0, 1], [cell.topleft, 1]];
  12680. };
  12681. var p12 = function (cell) {
  12682. return [[1, cell.righttop], [1, cell.rightbottom], [0, cell.leftbottom], [0, cell.lefttop]];
  12683. };
  12684. var p13 = function (cell) {
  12685. return [[cell.topleft, 1], [cell.topright, 1], [cell.bottomright, 0], [cell.bottomleft, 0]];
  12686. };
  12687. /* square case */
  12688. var p14 = function () {
  12689. return [[0, 0], [0, 1], [1, 1], [1, 0]];
  12690. };
  12691. /* pentagon cases */
  12692. var p15 = function (cell) {
  12693. return [[1, cell.rightbottom], [1, 0], [0, 0], [0, 1], [cell.topleft, 1]];
  12694. };
  12695. /* 1211 || 1011 */
  12696. var p16 = function (cell) {
  12697. return [[cell.topright, 1], [1, 1], [1, 0], [0, 0], [0, cell.leftbottom]];
  12698. };
  12699. /* 2111 || 0111 */
  12700. var p17 = function (cell) {
  12701. return [[1, 0], [cell.bottomright, 0], [0, cell.lefttop], [0, 1], [1, 1]];
  12702. };
  12703. /* 1112 || 1110 */
  12704. var p18 = function (cell) {
  12705. return [[1, 1], [1, cell.righttop], [cell.bottomleft, 0], [0, 0], [0, 1]];
  12706. };
  12707. /* 1121 || 1101 */
  12708. var p19 = function (cell) {
  12709. return [[1, cell.righttop], [1, cell.rightbottom], [0, cell.lefttop], [0, 1], [cell.topleft, 1]];
  12710. };
  12711. /* 1200 || 1022 */
  12712. var p20 = function (cell) {
  12713. return [[1, 1], [1, cell.righttop], [cell.bottomright, 0], [cell.bottomleft, 0], [cell.topright, 1]];
  12714. };
  12715. /* 0120 || 2102 */
  12716. var p21 = function (cell) {
  12717. return [[1, cell.rightbottom], [1, 0], [cell.bottomright, 0], [0, cell.leftbottom], [0, cell.lefttop]];
  12718. };
  12719. /* 0012 || 2210 */
  12720. var p22 = function (cell) {
  12721. return [[cell.topright, 1], [cell.bottomleft, 0], [0, 0], [0, cell.leftbottom], [cell.topleft, 1]];
  12722. };
  12723. /* 2001 || 0221 */
  12724. var p23 = function (cell) {
  12725. return [[cell.bottomright, 0], [cell.bottomleft, 0], [0, cell.lefttop], [0, 1], [cell.topleft, 1]];
  12726. };
  12727. /* 1002 || 1220 */
  12728. var p24 = function (cell) {
  12729. return [[1, 1], [1, cell.righttop], [0, cell.leftbottom], [0, cell.lefttop], [cell.topright, 1]];
  12730. };
  12731. /* 2100 || 0122 */
  12732. var p25 = function (cell) {
  12733. return [[1, cell.rightbottom], [1, 0], [cell.bottomright, 0], [cell.topleft, 1], [cell.topright, 1]];
  12734. };
  12735. /* 0210 || 2012 */
  12736. var p26 = function (cell) {
  12737. return [[1, cell.righttop], [1, cell.rightbottom], [cell.bottomleft, 0], [0, 0], [0, cell.leftbottom]];
  12738. };
  12739. /* 0021 || 2201 */
  12740. /*hexagon cases */
  12741. var p27 = function (cell) {
  12742. return [[1, cell.rightbottom], [1, 0], [0, 0], [0, cell.leftbottom], [cell.topleft, 1], [cell.topright, 1]];
  12743. };
  12744. /* 0211 || 2011 */
  12745. var p28 = function (cell) {
  12746. return [[1, 1], [1, 0], [cell.bottomright, 0], [0, cell.leftbottom], [0, cell.lefttop], [cell.topright, 1]];
  12747. };
  12748. /* 2110 || 0112 */
  12749. var p29 = function (cell) {
  12750. return [[1, 1], [1, cell.righttop], [cell.bottomright, 0], [cell.bottomleft, 0], [0, cell.lefttop], [0, 1]];
  12751. };
  12752. /* 1102 || 1120 */
  12753. var p30 = function (cell) {
  12754. return [[1, cell.righttop], [1, cell.rightbottom], [cell.bottomleft, 0], [0, 0], [0, 1], [cell.topleft, 1]];
  12755. };
  12756. /* 1021 || 1201 */
  12757. var p31 = function (cell) {
  12758. return [[1, 1], [1, cell.righttop], [cell.bottomleft, 0], [0, 0], [0, cell.leftbottom], [cell.topright, 1]];
  12759. };
  12760. /* 2101 || 0121 */
  12761. var p32 = function (cell) {
  12762. return [[1, cell.rightbottom], [1, 0], [cell.bottomright, 0], [0, cell.lefttop], [0, 1], [cell.topleft, 1]];
  12763. };
  12764. /* 1012 || 1210 */
  12765. /* 8-sided cases */
  12766. var p33 = function (cell) {
  12767. return [[1, cell.righttop], [1, cell.rightbottom], [cell.bottomright, 0], [cell.bottomleft, 0], [0, cell.leftbottom], [0, cell.lefttop], [cell.topleft, 1], [cell.topright, 1]];
  12768. };
  12769. /* flipped == 1 state for 0202 and 2020 */
  12770. /* 6-sided cases */
  12771. var p34 = function (cell) {
  12772. return [[1, 1], [1, cell.righttop], [cell.bottomleft, 0], [0, 0], [0, cell.leftbottom], [cell.topright, 1]];
  12773. };
  12774. /* 0101 with flipped == 1 || 2121 with flipped == 1 */
  12775. var p35 = function (cell) {
  12776. return [[1, cell.rightbottom], [1, 0], [cell.bottomright, 0], [0, cell.lefttop], [0, 1], [cell.topleft, 1]];
  12777. };
  12778. /* 1010 with flipped == 1 || 1212 with flipped == 1 */
  12779. /* 7-sided cases */
  12780. var p36 = function (cell) {
  12781. return [[1, 1], [1, cell.righttop], [cell.bottomright, 0], [cell.bottomleft, 0], [0, cell.leftbottom], [0, cell.lefttop], [cell.topright, 1]];
  12782. };
  12783. /* 2120 with flipped == 1 || 0102 with flipped == 1 */
  12784. var p37 = function (cell) {
  12785. return [[1, cell.righttop], [1, cell.rightbottom], [cell.bottomleft, 0], [0, 0], [0, cell.leftbottom], [cell.topleft, 1], [cell.topright, 1]];
  12786. };
  12787. /* 2021 with flipped == 1 || 0201 with flipped == 1 */
  12788. var p38 = function (cell) {
  12789. return [[1, cell.righttop], [1, cell.rightbottom], [cell.bottomright, 0], [cell.bottomleft, 0], [0, cell.lefttop], [0, 1], [cell.topleft, 1]];
  12790. };
  12791. /* 1202 with flipped == 1 || 1020 with flipped == 1 */
  12792. var p39 = function (cell) {
  12793. return [[1, cell.rightbottom], [1, 0], [cell.bottomright, 0], [0, cell.leftbottom], [0, cell.lefttop], [cell.topleft, 1], [cell.topright, 1]];
  12794. };
  12795. /* 0212 with flipped == 1 || 2010 with flipped == 1 */
  12796. /*
  12797. The lookup tables for edge number given the polygon
  12798. is entered at a specific location
  12799. */
  12800. var isoBandEdgeRT = [];
  12801. var isoBandEdgeRB = [];
  12802. var isoBandEdgeBR = [];
  12803. var isoBandEdgeBL = [];
  12804. var isoBandEdgeLB = [];
  12805. var isoBandEdgeLT = [];
  12806. var isoBandEdgeTL = [];
  12807. var isoBandEdgeTR = [];
  12808. /* triangle cases */
  12809. isoBandEdgeBL[1] = isoBandEdgeLB[1] = 18;
  12810. isoBandEdgeBL[169] = isoBandEdgeLB[169] = 18;
  12811. isoBandEdgeBR[4] = isoBandEdgeRB[4] = 12;
  12812. isoBandEdgeBR[166] = isoBandEdgeRB[166] = 12;
  12813. isoBandEdgeRT[16] = isoBandEdgeTR[16] = 4;
  12814. isoBandEdgeRT[154] = isoBandEdgeTR[154] = 4;
  12815. isoBandEdgeLT[64] = isoBandEdgeTL[64] = 22;
  12816. isoBandEdgeLT[106] = isoBandEdgeTL[106] = 22;
  12817. /* trapezoid cases */
  12818. isoBandEdgeBR[2] = isoBandEdgeLT[2] = 17;
  12819. isoBandEdgeBL[2] = isoBandEdgeLB[2] = 18;
  12820. isoBandEdgeBR[168] = isoBandEdgeLT[168] = 17;
  12821. isoBandEdgeBL[168] = isoBandEdgeLB[168] = 18;
  12822. isoBandEdgeRT[8] = isoBandEdgeBL[8] = 9;
  12823. isoBandEdgeRB[8] = isoBandEdgeBR[8] = 12;
  12824. isoBandEdgeRT[162] = isoBandEdgeBL[162] = 9;
  12825. isoBandEdgeRB[162] = isoBandEdgeBR[162] = 12;
  12826. isoBandEdgeRT[32] = isoBandEdgeTR[32] = 4;
  12827. isoBandEdgeRB[32] = isoBandEdgeTL[32] = 1;
  12828. isoBandEdgeRT[138] = isoBandEdgeTR[138] = 4;
  12829. isoBandEdgeRB[138] = isoBandEdgeTL[138] = 1;
  12830. isoBandEdgeLB[128] = isoBandEdgeTR[128] = 21;
  12831. isoBandEdgeLT[128] = isoBandEdgeTL[128] = 22;
  12832. isoBandEdgeLB[42] = isoBandEdgeTR[42] = 21;
  12833. isoBandEdgeLT[42] = isoBandEdgeTL[42] = 22;
  12834. /* rectangle cases */
  12835. isoBandEdgeRB[5] = isoBandEdgeLB[5] = 14;
  12836. isoBandEdgeRB[165] = isoBandEdgeLB[165] = 14;
  12837. isoBandEdgeBR[20] = isoBandEdgeTR[20] = 6;
  12838. isoBandEdgeBR[150] = isoBandEdgeTR[150] = 6;
  12839. isoBandEdgeRT[80] = isoBandEdgeLT[80] = 11;
  12840. isoBandEdgeRT[90] = isoBandEdgeLT[90] = 11;
  12841. isoBandEdgeBL[65] = isoBandEdgeTL[65] = 3;
  12842. isoBandEdgeBL[105] = isoBandEdgeTL[105] = 3;
  12843. isoBandEdgeRT[160] = isoBandEdgeLT[160] = 11;
  12844. isoBandEdgeRB[160] = isoBandEdgeLB[160] = 14;
  12845. isoBandEdgeRT[10] = isoBandEdgeLT[10] = 11;
  12846. isoBandEdgeRB[10] = isoBandEdgeLB[10] = 14;
  12847. isoBandEdgeBR[130] = isoBandEdgeTR[130] = 6;
  12848. isoBandEdgeBL[130] = isoBandEdgeTL[130] = 3;
  12849. isoBandEdgeBR[40] = isoBandEdgeTR[40] = 6;
  12850. isoBandEdgeBL[40] = isoBandEdgeTL[40] = 3;
  12851. /* pentagon cases */
  12852. isoBandEdgeRB[101] = isoBandEdgeTL[101] = 1;
  12853. isoBandEdgeRB[69] = isoBandEdgeTL[69] = 1;
  12854. isoBandEdgeLB[149] = isoBandEdgeTR[149] = 21;
  12855. isoBandEdgeLB[21] = isoBandEdgeTR[21] = 21;
  12856. isoBandEdgeBR[86] = isoBandEdgeLT[86] = 17;
  12857. isoBandEdgeBR[84] = isoBandEdgeLT[84] = 17;
  12858. isoBandEdgeRT[89] = isoBandEdgeBL[89] = 9;
  12859. isoBandEdgeRT[81] = isoBandEdgeBL[81] = 9;
  12860. isoBandEdgeRT[96] = isoBandEdgeTL[96] = 0;
  12861. isoBandEdgeRB[96] = isoBandEdgeLT[96] = 15;
  12862. isoBandEdgeRT[74] = isoBandEdgeTL[74] = 0;
  12863. isoBandEdgeRB[74] = isoBandEdgeLT[74] = 15;
  12864. isoBandEdgeRT[24] = isoBandEdgeBR[24] = 8;
  12865. isoBandEdgeBL[24] = isoBandEdgeTR[24] = 7;
  12866. isoBandEdgeRT[146] = isoBandEdgeBR[146] = 8;
  12867. isoBandEdgeBL[146] = isoBandEdgeTR[146] = 7;
  12868. isoBandEdgeRB[6] = isoBandEdgeLT[6] = 15;
  12869. isoBandEdgeBR[6] = isoBandEdgeLB[6] = 16;
  12870. isoBandEdgeRB[164] = isoBandEdgeLT[164] = 15;
  12871. isoBandEdgeBR[164] = isoBandEdgeLB[164] = 16;
  12872. isoBandEdgeBL[129] = isoBandEdgeTR[129] = 7;
  12873. isoBandEdgeLB[129] = isoBandEdgeTL[129] = 20;
  12874. isoBandEdgeBL[41] = isoBandEdgeTR[41] = 7;
  12875. isoBandEdgeLB[41] = isoBandEdgeTL[41] = 20;
  12876. isoBandEdgeBR[66] = isoBandEdgeTL[66] = 2;
  12877. isoBandEdgeBL[66] = isoBandEdgeLT[66] = 19;
  12878. isoBandEdgeBR[104] = isoBandEdgeTL[104] = 2;
  12879. isoBandEdgeBL[104] = isoBandEdgeLT[104] = 19;
  12880. isoBandEdgeRT[144] = isoBandEdgeLB[144] = 10;
  12881. isoBandEdgeLT[144] = isoBandEdgeTR[144] = 23;
  12882. isoBandEdgeRT[26] = isoBandEdgeLB[26] = 10;
  12883. isoBandEdgeLT[26] = isoBandEdgeTR[26] = 23;
  12884. isoBandEdgeRB[36] = isoBandEdgeTR[36] = 5;
  12885. isoBandEdgeBR[36] = isoBandEdgeTL[36] = 2;
  12886. isoBandEdgeRB[134] = isoBandEdgeTR[134] = 5;
  12887. isoBandEdgeBR[134] = isoBandEdgeTL[134] = 2;
  12888. isoBandEdgeRT[9] = isoBandEdgeLB[9] = 10;
  12889. isoBandEdgeRB[9] = isoBandEdgeBL[9] = 13;
  12890. isoBandEdgeRT[161] = isoBandEdgeLB[161] = 10;
  12891. isoBandEdgeRB[161] = isoBandEdgeBL[161] = 13;
  12892. /* hexagon cases */
  12893. isoBandEdgeRB[37] = isoBandEdgeTR[37] = 5;
  12894. isoBandEdgeLB[37] = isoBandEdgeTL[37] = 20;
  12895. isoBandEdgeRB[133] = isoBandEdgeTR[133] = 5;
  12896. isoBandEdgeLB[133] = isoBandEdgeTL[133] = 20;
  12897. isoBandEdgeBR[148] = isoBandEdgeLB[148] = 16;
  12898. isoBandEdgeLT[148] = isoBandEdgeTR[148] = 23;
  12899. isoBandEdgeBR[22] = isoBandEdgeLB[22] = 16;
  12900. isoBandEdgeLT[22] = isoBandEdgeTR[22] = 23;
  12901. isoBandEdgeRT[82] = isoBandEdgeBR[82] = 8;
  12902. isoBandEdgeBL[82] = isoBandEdgeLT[82] = 19;
  12903. isoBandEdgeRT[88] = isoBandEdgeBR[88] = 8;
  12904. isoBandEdgeBL[88] = isoBandEdgeLT[88] = 19;
  12905. isoBandEdgeRT[73] = isoBandEdgeTL[73] = 0;
  12906. isoBandEdgeRB[73] = isoBandEdgeBL[73] = 13;
  12907. isoBandEdgeRT[97] = isoBandEdgeTL[97] = 0;
  12908. isoBandEdgeRB[97] = isoBandEdgeBL[97] = 13;
  12909. isoBandEdgeRT[145] = isoBandEdgeBL[145] = 9;
  12910. isoBandEdgeLB[145] = isoBandEdgeTR[145] = 21;
  12911. isoBandEdgeRT[25] = isoBandEdgeBL[25] = 9;
  12912. isoBandEdgeLB[25] = isoBandEdgeTR[25] = 21;
  12913. isoBandEdgeRB[70] = isoBandEdgeTL[70] = 1;
  12914. isoBandEdgeBR[70] = isoBandEdgeLT[70] = 17;
  12915. isoBandEdgeRB[100] = isoBandEdgeTL[100] = 1;
  12916. isoBandEdgeBR[100] = isoBandEdgeLT[100] = 17;
  12917. /* 8-sided cases */
  12918. isoBandEdgeRT[34] = isoBandEdgeBL[34] = 9;
  12919. isoBandEdgeRB[34] = isoBandEdgeBR[34] = 12;
  12920. isoBandEdgeLB[34] = isoBandEdgeTR[34] = 21;
  12921. isoBandEdgeLT[34] = isoBandEdgeTL[34] = 22;
  12922. isoBandEdgeRT[136] = isoBandEdgeTR[136] = 4;
  12923. isoBandEdgeRB[136] = isoBandEdgeTL[136] = 1;
  12924. isoBandEdgeBR[136] = isoBandEdgeLT[136] = 17;
  12925. isoBandEdgeBL[136] = isoBandEdgeLB[136] = 18;
  12926. isoBandEdgeRT[35] = isoBandEdgeTR[35] = 4;
  12927. isoBandEdgeRB[35] = isoBandEdgeBR[35] = 12;
  12928. isoBandEdgeBL[35] = isoBandEdgeLB[35] = 18;
  12929. isoBandEdgeLT[35] = isoBandEdgeTL[35] = 22;
  12930. /* 6-sided cases */
  12931. isoBandEdgeRT[153] = isoBandEdgeTR[153] = 4;
  12932. isoBandEdgeBL[153] = isoBandEdgeLB[153] = 18;
  12933. isoBandEdgeRB[102] = isoBandEdgeBR[102] = 12;
  12934. isoBandEdgeLT[102] = isoBandEdgeTL[102] = 22;
  12935. isoBandEdgeRT[155] = isoBandEdgeBL[155] = 9;
  12936. isoBandEdgeLB[155] = isoBandEdgeTR[155] = 23;
  12937. isoBandEdgeRB[103] = isoBandEdgeTL[103] = 1;
  12938. isoBandEdgeBR[103] = isoBandEdgeLT[103] = 17;
  12939. /* 7-sided cases */
  12940. isoBandEdgeRT[152] = isoBandEdgeTR[152] = 4;
  12941. isoBandEdgeBR[152] = isoBandEdgeLT[152] = 17;
  12942. isoBandEdgeBL[152] = isoBandEdgeLB[152] = 18;
  12943. isoBandEdgeRT[156] = isoBandEdgeBR[156] = 8;
  12944. isoBandEdgeBL[156] = isoBandEdgeLB[156] = 18;
  12945. isoBandEdgeLT[156] = isoBandEdgeTR[156] = 23;
  12946. isoBandEdgeRT[137] = isoBandEdgeTR[137] = 4;
  12947. isoBandEdgeRB[137] = isoBandEdgeTL[137] = 1;
  12948. isoBandEdgeBL[137] = isoBandEdgeLB[137] = 18;
  12949. isoBandEdgeRT[139] = isoBandEdgeTR[139] = 4;
  12950. isoBandEdgeRB[139] = isoBandEdgeBL[139] = 13;
  12951. isoBandEdgeLB[139] = isoBandEdgeTL[139] = 20;
  12952. isoBandEdgeRT[98] = isoBandEdgeBL[98] = 9;
  12953. isoBandEdgeRB[98] = isoBandEdgeBR[98] = 12;
  12954. isoBandEdgeLT[98] = isoBandEdgeTL[98] = 22;
  12955. isoBandEdgeRT[99] = isoBandEdgeTL[99] = 0;
  12956. isoBandEdgeRB[99] = isoBandEdgeBR[99] = 12;
  12957. isoBandEdgeBL[99] = isoBandEdgeLT[99] = 19;
  12958. isoBandEdgeRB[38] = isoBandEdgeBR[38] = 12;
  12959. isoBandEdgeLB[38] = isoBandEdgeTR[38] = 21;
  12960. isoBandEdgeLT[38] = isoBandEdgeTL[38] = 22;
  12961. isoBandEdgeRB[39] = isoBandEdgeTR[39] = 5;
  12962. isoBandEdgeBR[39] = isoBandEdgeLB[39] = 16;
  12963. isoBandEdgeLT[39] = isoBandEdgeTL[39] = 22;
  12964. /*
  12965. The lookup tables for all different polygons that
  12966. may appear within a grid cell
  12967. */
  12968. var polygon_table = [];
  12969. /* triangle cases */
  12970. polygon_table[1] = polygon_table[169] = p00; /* 2221 || 0001 */
  12971. polygon_table[4] = polygon_table[166] = p01; /* 2212 || 0010 */
  12972. polygon_table[16] = polygon_table[154] = p02; /* 2122 || 0100 */
  12973. polygon_table[64] = polygon_table[106] = p03; /* 1222 || 1000 */
  12974. /* trapezoid cases */
  12975. polygon_table[168] = polygon_table[2] = p04; /* 2220 || 0002 */
  12976. polygon_table[162] = polygon_table[8] = p05; /* 2202 || 0020 */
  12977. polygon_table[138] = polygon_table[32] = p06; /* 2022 || 0200 */
  12978. polygon_table[42] = polygon_table[128] = p07; /* 0222 || 2000 */
  12979. /* rectangle cases */
  12980. polygon_table[5] = polygon_table[165] = p08; /* 0011 || 2211 */
  12981. polygon_table[20] = polygon_table[150] = p09; /* 0110 || 2112 */
  12982. polygon_table[80] = polygon_table[90] = p10; /* 1100 || 1122 */
  12983. polygon_table[65] = polygon_table[105] = p11; /* 1001 || 1221 */
  12984. polygon_table[160] = polygon_table[10] = p12; /* 2200 || 0022 */
  12985. polygon_table[130] = polygon_table[40] = p13; /* 2002 || 0220 */
  12986. /* square case */
  12987. polygon_table[85] = p14; /* 1111 */
  12988. /* pentagon cases */
  12989. polygon_table[101] = polygon_table[69] = p15; /* 1211 || 1011 */
  12990. polygon_table[149] = polygon_table[21] = p16; /* 2111 || 0111 */
  12991. polygon_table[86] = polygon_table[84] = p17; /* 1112 || 1110 */
  12992. polygon_table[89] = polygon_table[81] = p18; /* 1121 || 1101 */
  12993. polygon_table[96] = polygon_table[74] = p19; /* 1200 || 1022 */
  12994. polygon_table[24] = polygon_table[146] = p20; /* 0120 || 2102 */
  12995. polygon_table[6] = polygon_table[164] = p21; /* 0012 || 2210 */
  12996. polygon_table[129] = polygon_table[41] = p22; /* 2001 || 0221 */
  12997. polygon_table[66] = polygon_table[104] = p23; /* 1002 || 1220 */
  12998. polygon_table[144] = polygon_table[26] = p24; /* 2100 || 0122 */
  12999. polygon_table[36] = polygon_table[134] = p25; /* 0210 || 2012 */
  13000. polygon_table[9] = polygon_table[161] = p26; /* 0021 || 2201 */
  13001. /* hexagon cases */
  13002. polygon_table[37] = polygon_table[133] = p27; /* 0211 || 2011 */
  13003. polygon_table[148] = polygon_table[22] = p28; /* 2110 || 0112 */
  13004. polygon_table[82] = polygon_table[88] = p29; /* 1102 || 1120 */
  13005. polygon_table[73] = polygon_table[97] = p30; /* 1021 || 1201 */
  13006. polygon_table[145] = polygon_table[25] = p31; /* 2101 || 0121 */
  13007. polygon_table[70] = polygon_table[100] = p32; /* 1012 || 1210 */
  13008. /* 8-sided cases */
  13009. polygon_table[34] = function (c) { return [p07(c), p05(c)]; }; /* 0202 || 2020 with flipped == 0 */
  13010. polygon_table[35] = p33; /* flipped == 1 state for 0202 and 2020 */
  13011. polygon_table[136] = function (c) { return [p06(c), p04(c)]; }; /* 2020 || 0202 with flipped == 0 */
  13012. /* 6-sided cases */
  13013. polygon_table[153] = function (c) { return [p02(c), p00(c)]; }; /* 0101 with flipped == 0 || 2121 with flipped == 2 */
  13014. polygon_table[102] = function (c) { return [p01(c), p03(c)]; }; /* 1010 with flipped == 0 || 1212 with flipped == 2 */
  13015. polygon_table[155] = p34; /* 0101 with flipped == 1 || 2121 with flipped == 1 */
  13016. polygon_table[103] = p35; /* 1010 with flipped == 1 || 1212 with flipped == 1 */
  13017. /* 7-sided cases */
  13018. polygon_table[152] = function (c) { return [p02(c), p04(c)]; }; /* 2120 with flipped == 2 || 0102 with flipped == 0 */
  13019. polygon_table[156] = p36; /* 2120 with flipped == 1 || 0102 with flipped == 1 */
  13020. polygon_table[137] = function (c) { return [p06(c), p00(c)]; }; /* 2021 with flipped == 2 || 0201 with flipped == 0 */
  13021. polygon_table[139] = p37; /* 2021 with flipped == 1 || 0201 with flipped == 1 */
  13022. polygon_table[98] = function (c) { return [p05(c), p03(c)]; }; /* 1202 with flipped == 2 || 1020 with flipped == 0 */
  13023. polygon_table[99] = p38; /* 1202 with flipped == 1 || 1020 with flipped == 1 */
  13024. polygon_table[38] = function (c) { return [p01(c), p07(c)]; }; /* 0212 with flipped == 2 || 2010 with flipped == 0 */
  13025. polygon_table[39] = p39; /* 0212 with flipped == 1 || 2010 with flipped == 1 */
  13026. /*
  13027. ####################################
  13028. Some small helper functions
  13029. ####################################
  13030. */
  13031. /* assume that x1 == 1 && x0 == 0 */
  13032. function interpolateX$1(y, y0, y1) {
  13033. return (y - y0) / (y1 - y0);
  13034. }
  13035. function isArray(myArray) {
  13036. return myArray.constructor.toString().indexOf('Array') > -1;
  13037. }
  13038. /*
  13039. ####################################
  13040. Below is the actual Marching Squares implementation
  13041. ####################################
  13042. */
  13043. function computeBandGrid(data, minV, bandwidth) {
  13044. var rows = data.length - 1;
  13045. var cols = data[0].length - 1;
  13046. var BandGrid = { rows: rows, cols: cols, cells: [] };
  13047. var maxV = minV + Math.abs(bandwidth);
  13048. for (var j = 0; j < rows; ++j) {
  13049. BandGrid.cells[j] = [];
  13050. for (var i = 0; i < cols; ++i) {
  13051. /* compose the 4-trit corner representation */
  13052. var cval = 0;
  13053. var tl = data[j + 1][i];
  13054. var tr = data[j + 1][i + 1];
  13055. var br = data[j][i + 1];
  13056. var bl = data[j][i];
  13057. if (isNaN(tl) || isNaN(tr) || isNaN(br) || isNaN(bl)) {
  13058. continue;
  13059. }
  13060. cval |= (tl < minV) ? 0 : (tl > maxV) ? 128 : 64;
  13061. cval |= (tr < minV) ? 0 : (tr > maxV) ? 32 : 16;
  13062. cval |= (br < minV) ? 0 : (br > maxV) ? 8 : 4;
  13063. cval |= (bl < minV) ? 0 : (bl > maxV) ? 2 : 1;
  13064. var cval_real = +cval;
  13065. /* resolve ambiguity via averaging */
  13066. var flipped = 0;
  13067. if ((cval === 17) || /* 0101 */
  13068. (cval === 18) || /* 0102 */
  13069. (cval === 33) || /* 0201 */
  13070. (cval === 34) || /* 0202 */
  13071. (cval === 38) || /* 0212 */
  13072. (cval === 68) || /* 1010 */
  13073. (cval === 72) || /* 1020 */
  13074. (cval === 98) || /* 1202 */
  13075. (cval === 102) || /* 1212 */
  13076. (cval === 132) || /* 2010 */
  13077. (cval === 136) || /* 2020 */
  13078. (cval === 137) || /* 2021 */
  13079. (cval === 152) || /* 2120 */
  13080. (cval === 153) /* 2121 */
  13081. ) {
  13082. var average = (tl + tr + br + bl) / 4;
  13083. /* set flipped state */
  13084. flipped = (average > maxV) ? 2 : (average < minV) ? 0 : 1;
  13085. /* adjust cval for flipped cases */
  13086. /* 8-sided cases */
  13087. if (cval === 34) {
  13088. if (flipped === 1) {
  13089. cval = 35;
  13090. } else if (flipped === 0) {
  13091. cval = 136;
  13092. }
  13093. } else if (cval === 136) {
  13094. if (flipped === 1) {
  13095. cval = 35;
  13096. flipped = 4;
  13097. } else if (flipped === 0) {
  13098. cval = 34;
  13099. }
  13100. }
  13101. /* 6-sided polygon cases */
  13102. else if (cval === 17) {
  13103. if (flipped === 1) {
  13104. cval = 155;
  13105. flipped = 4;
  13106. } else if (flipped === 0) {
  13107. cval = 153;
  13108. }
  13109. } else if (cval === 68) {
  13110. if (flipped === 1) {
  13111. cval = 103;
  13112. flipped = 4;
  13113. } else if (flipped === 0) {
  13114. cval = 102;
  13115. }
  13116. } else if (cval === 153) {
  13117. if (flipped === 1)
  13118. cval = 155;
  13119. } else if (cval === 102) {
  13120. if (flipped === 1)
  13121. cval = 103;
  13122. }
  13123. /* 7-sided polygon cases */
  13124. else if (cval === 152) {
  13125. if (flipped < 2) {
  13126. cval = 156;
  13127. flipped = 1;
  13128. }
  13129. } else if (cval === 137) {
  13130. if (flipped < 2) {
  13131. cval = 139;
  13132. flipped = 1;
  13133. }
  13134. } else if (cval === 98) {
  13135. if (flipped < 2) {
  13136. cval = 99;
  13137. flipped = 1;
  13138. }
  13139. } else if (cval === 38) {
  13140. if (flipped < 2) {
  13141. cval = 39;
  13142. flipped = 1;
  13143. }
  13144. } else if (cval === 18) {
  13145. if (flipped > 0) {
  13146. cval = 156;
  13147. flipped = 4;
  13148. } else {
  13149. cval = 152;
  13150. }
  13151. } else if (cval === 33) {
  13152. if (flipped > 0) {
  13153. cval = 139;
  13154. flipped = 4;
  13155. } else {
  13156. cval = 137;
  13157. }
  13158. } else if (cval === 72) {
  13159. if (flipped > 0) {
  13160. cval = 99;
  13161. flipped = 4;
  13162. } else {
  13163. cval = 98;
  13164. }
  13165. } else if (cval === 132) {
  13166. if (flipped > 0) {
  13167. cval = 39;
  13168. flipped = 4;
  13169. } else {
  13170. cval = 38;
  13171. }
  13172. }
  13173. }
  13174. /* add cell to BandGrid if it contains at least one polygon-side */
  13175. if ((cval != 0) && (cval != 170)) {
  13176. var topleft, topright, bottomleft, bottomright,
  13177. righttop, rightbottom, lefttop, leftbottom;
  13178. topleft = topright = bottomleft = bottomright = righttop =
  13179. rightbottom = lefttop = leftbottom = 0.5;
  13180. var edges = [];
  13181. /* do interpolation here */
  13182. /* 1st Triangles */
  13183. if (cval === 1) { /* 0001 */
  13184. bottomleft = 1 - interpolateX$1(minV, br, bl);
  13185. leftbottom = 1 - interpolateX$1(minV, tl, bl);
  13186. edges.push(isoBandEdgeBL[cval]);
  13187. } else if (cval === 169) { /* 2221 */
  13188. bottomleft = interpolateX$1(maxV, bl, br);
  13189. leftbottom = interpolateX$1(maxV, bl, tl);
  13190. edges.push(isoBandEdgeBL[cval]);
  13191. } else if (cval === 4) { /* 0010 */
  13192. rightbottom = 1 - interpolateX$1(minV, tr, br);
  13193. bottomright = interpolateX$1(minV, bl, br);
  13194. edges.push(isoBandEdgeRB[cval]);
  13195. } else if (cval === 166) { /* 2212 */
  13196. rightbottom = interpolateX$1(maxV, br, tr);
  13197. bottomright = 1 - interpolateX$1(maxV, br, bl);
  13198. edges.push(isoBandEdgeRB[cval]);
  13199. } else if (cval === 16) { /* 0100 */
  13200. righttop = interpolateX$1(minV, br, tr);
  13201. topright = interpolateX$1(minV, tl, tr);
  13202. edges.push(isoBandEdgeRT[cval]);
  13203. } else if (cval === 154) { /* 2122 */
  13204. righttop = 1 - interpolateX$1(maxV, tr, br);
  13205. topright = 1 - interpolateX$1(maxV, tr, tl);
  13206. edges.push(isoBandEdgeRT[cval]);
  13207. } else if (cval === 64) { /* 1000 */
  13208. lefttop = interpolateX$1(minV, bl, tl);
  13209. topleft = 1 - interpolateX$1(minV, tr, tl);
  13210. edges.push(isoBandEdgeLT[cval]);
  13211. } else if (cval === 106) { /* 1222 */
  13212. lefttop = 1 - interpolateX$1(maxV, tl, bl);
  13213. topleft = interpolateX$1(maxV, tl, tr);
  13214. edges.push(isoBandEdgeLT[cval]);
  13215. }
  13216. /* 2nd Trapezoids */
  13217. else if (cval === 168) { /* 2220 */
  13218. bottomright = interpolateX$1(maxV, bl, br);
  13219. bottomleft = interpolateX$1(minV, bl, br);
  13220. leftbottom = interpolateX$1(minV, bl, tl);
  13221. lefttop = interpolateX$1(maxV, bl, tl);
  13222. edges.push(isoBandEdgeBR[cval]);
  13223. edges.push(isoBandEdgeBL[cval]);
  13224. } else if (cval === 2) { /* 0002 */
  13225. bottomright = 1 - interpolateX$1(minV, br, bl);
  13226. bottomleft = 1 - interpolateX$1(maxV, br, bl);
  13227. leftbottom = 1 - interpolateX$1(maxV, tl, bl);
  13228. lefttop = 1 - interpolateX$1(minV, tl, bl);
  13229. edges.push(isoBandEdgeBR[cval]);
  13230. edges.push(isoBandEdgeBL[cval]);
  13231. } else if (cval === 162) { /* 2202 */
  13232. righttop = interpolateX$1(maxV, br, tr);
  13233. rightbottom = interpolateX$1(minV, br, tr);
  13234. bottomright = 1 - interpolateX$1(minV, br, bl);
  13235. bottomleft = 1 - interpolateX$1(maxV, br, bl);
  13236. edges.push(isoBandEdgeBR[cval]);
  13237. edges.push(isoBandEdgeBL[cval]);
  13238. } else if (cval === 8) { /* 0020 */
  13239. righttop = 1 - interpolateX$1(minV, tr, br);
  13240. rightbottom = 1 - interpolateX$1(maxV, tr, br);
  13241. bottomright = interpolateX$1(maxV, bl, br);
  13242. bottomleft = interpolateX$1(minV, bl, br);
  13243. edges.push(isoBandEdgeRT[cval]);
  13244. edges.push(isoBandEdgeRB[cval]);
  13245. } else if (cval === 138) { /* 2022 */
  13246. righttop = 1 - interpolateX$1(minV, tr, br);
  13247. rightbottom = 1 - interpolateX$1(maxV, tr, br);
  13248. topleft = 1 - interpolateX$1(maxV, tr, tl);
  13249. topright = 1 - interpolateX$1(minV, tr, tl);
  13250. edges.push(isoBandEdgeRT[cval]);
  13251. edges.push(isoBandEdgeRB[cval]);
  13252. } else if (cval === 32) { /* 0200 */
  13253. righttop = interpolateX$1(maxV, br, tr);
  13254. rightbottom = interpolateX$1(minV, br, tr);
  13255. topleft = interpolateX$1(minV, tl, tr);
  13256. topright = interpolateX$1(maxV, tl, tr);
  13257. edges.push(isoBandEdgeRT[cval]);
  13258. edges.push(isoBandEdgeRB[cval]);
  13259. } else if (cval === 42) { /* 0222 */
  13260. leftbottom = 1 - interpolateX$1(maxV, tl, bl);
  13261. lefttop = 1 - interpolateX$1(minV, tl, bl);
  13262. topleft = interpolateX$1(minV, tl, tr);
  13263. topright = interpolateX$1(maxV, tl, tr);
  13264. edges.push(isoBandEdgeLB[cval]);
  13265. edges.push(isoBandEdgeLT[cval]);
  13266. } else if (cval === 128) { /* 2000 */
  13267. leftbottom = interpolateX$1(minV, bl, tl);
  13268. lefttop = interpolateX$1(maxV, bl, tl);
  13269. topleft = 1 - interpolateX$1(maxV, tr, tl);
  13270. topright = 1 - interpolateX$1(minV, tr, tl);
  13271. edges.push(isoBandEdgeLB[cval]);
  13272. edges.push(isoBandEdgeLT[cval]);
  13273. }
  13274. /* 3rd rectangle cases */
  13275. if (cval === 5) { /* 0011 */
  13276. rightbottom = 1 - interpolateX$1(minV, tr, br);
  13277. leftbottom = 1 - interpolateX$1(minV, tl, bl);
  13278. edges.push(isoBandEdgeRB[cval]);
  13279. } else if (cval === 165) { /* 2211 */
  13280. rightbottom = interpolateX$1(maxV, br, tr);
  13281. leftbottom = interpolateX$1(maxV, bl, tl);
  13282. edges.push(isoBandEdgeRB[cval]);
  13283. } else if (cval === 20) { /* 0110 */
  13284. bottomright = interpolateX$1(minV, bl, br);
  13285. topright = interpolateX$1(minV, tl, tr);
  13286. edges.push(isoBandEdgeBR[cval]);
  13287. } else if (cval === 150) { /* 2112 */
  13288. bottomright = 1 - interpolateX$1(maxV, br, bl);
  13289. topright = 1 - interpolateX$1(maxV, tr, tl);
  13290. edges.push(isoBandEdgeBR[cval]);
  13291. } else if (cval === 80) { /* 1100 */
  13292. righttop = interpolateX$1(minV, br, tr);
  13293. lefttop = interpolateX$1(minV, bl, tl);
  13294. edges.push(isoBandEdgeRT[cval]);
  13295. } else if (cval === 90) { /* 1122 */
  13296. righttop = 1 - interpolateX$1(maxV, tr, br);
  13297. lefttop = 1 - interpolateX$1(maxV, tl, bl);
  13298. edges.push(isoBandEdgeRT[cval]);
  13299. } else if (cval === 65) { /* 1001 */
  13300. bottomleft = 1 - interpolateX$1(minV, br, bl);
  13301. topleft = 1 - interpolateX$1(minV, tr, tl);
  13302. edges.push(isoBandEdgeBL[cval]);
  13303. } else if (cval === 105) { /* 1221 */
  13304. bottomleft = interpolateX$1(maxV, bl, br);
  13305. topleft = interpolateX$1(maxV, tl, tr);
  13306. edges.push(isoBandEdgeBL[cval]);
  13307. } else if (cval === 160) { /* 2200 */
  13308. righttop = interpolateX$1(maxV, br, tr);
  13309. rightbottom = interpolateX$1(minV, br, tr);
  13310. leftbottom = interpolateX$1(minV, bl, tl);
  13311. lefttop = interpolateX$1(maxV, bl, tl);
  13312. edges.push(isoBandEdgeRT[cval]);
  13313. edges.push(isoBandEdgeRB[cval]);
  13314. } else if (cval === 10) { /* 0022 */
  13315. righttop = 1 - interpolateX$1(minV, tr, br);
  13316. rightbottom = 1 - interpolateX$1(maxV, tr, br);
  13317. leftbottom = 1 - interpolateX$1(maxV, tl, bl);
  13318. lefttop = 1 - interpolateX$1(minV, tl, bl);
  13319. edges.push(isoBandEdgeRT[cval]);
  13320. edges.push(isoBandEdgeRB[cval]);
  13321. } else if (cval === 130) { /* 2002 */
  13322. bottomright = 1 - interpolateX$1(minV, br, bl);
  13323. bottomleft = 1 - interpolateX$1(maxV, br, bl);
  13324. topleft = 1 - interpolateX$1(maxV, tr, tl);
  13325. topright = 1 - interpolateX$1(minV, tr, tl);
  13326. edges.push(isoBandEdgeBR[cval]);
  13327. edges.push(isoBandEdgeBL[cval]);
  13328. } else if (cval === 40) { /* 0220 */
  13329. bottomright = interpolateX$1(maxV, bl, br);
  13330. bottomleft = interpolateX$1(minV, bl, br);
  13331. topleft = interpolateX$1(minV, tl, tr);
  13332. topright = interpolateX$1(maxV, tl, tr);
  13333. edges.push(isoBandEdgeBR[cval]);
  13334. edges.push(isoBandEdgeBL[cval]);
  13335. }
  13336. /* 4th single pentagon cases */
  13337. else if (cval === 101) { /* 1211 */
  13338. rightbottom = interpolateX$1(maxV, br, tr);
  13339. topleft = interpolateX$1(maxV, tl, tr);
  13340. edges.push(isoBandEdgeRB[cval]);
  13341. } else if (cval === 69) { /* 1011 */
  13342. rightbottom = 1 - interpolateX$1(minV, tr, br);
  13343. topleft = 1 - interpolateX$1(minV, tr, tl);
  13344. edges.push(isoBandEdgeRB[cval]);
  13345. } else if (cval === 149) { /* 2111 */
  13346. leftbottom = interpolateX$1(maxV, bl, tl);
  13347. topright = 1 - interpolateX$1(maxV, tr, tl);
  13348. edges.push(isoBandEdgeLB[cval]);
  13349. } else if (cval === 21) { /* 0111 */
  13350. leftbottom = 1 - interpolateX$1(minV, tl, bl);
  13351. topright = interpolateX$1(minV, tl, tr);
  13352. edges.push(isoBandEdgeLB[cval]);
  13353. } else if (cval === 86) { /* 1112 */
  13354. bottomright = 1 - interpolateX$1(maxV, br, bl);
  13355. lefttop = 1 - interpolateX$1(maxV, tl, bl);
  13356. edges.push(isoBandEdgeBR[cval]);
  13357. } else if (cval === 84) { /* 1110 */
  13358. bottomright = interpolateX$1(minV, bl, br);
  13359. lefttop = interpolateX$1(minV, bl, tl);
  13360. edges.push(isoBandEdgeBR[cval]);
  13361. } else if (cval === 89) { /* 1121 */
  13362. righttop = 1 - interpolateX$1(maxV, tr, br);
  13363. bottomleft = interpolateX$1(maxV, bl, br);
  13364. edges.push(isoBandEdgeBL[cval]);
  13365. } else if (cval === 81) { /* 1101 */
  13366. righttop = interpolateX$1(minV, br, tr);
  13367. bottomleft = 1 - interpolateX$1(minV, br, bl);
  13368. edges.push(isoBandEdgeBL[cval]);
  13369. } else if (cval === 96) { /* 1200 */
  13370. righttop = interpolateX$1(maxV, br, tr);
  13371. rightbottom = interpolateX$1(minV, br, tr);
  13372. lefttop = interpolateX$1(minV, bl, tl);
  13373. topleft = interpolateX$1(maxV, tl, tr);
  13374. edges.push(isoBandEdgeRT[cval]);
  13375. edges.push(isoBandEdgeRB[cval]);
  13376. } else if (cval === 74) { /* 1022 */
  13377. righttop = 1 - interpolateX$1(minV, tr, br);
  13378. rightbottom = 1 - interpolateX$1(maxV, tr, br);
  13379. lefttop = 1 - interpolateX$1(maxV, tl, bl);
  13380. topleft = 1 - interpolateX$1(minV, tr, tl);
  13381. edges.push(isoBandEdgeRT[cval]);
  13382. edges.push(isoBandEdgeRB[cval]);
  13383. } else if (cval === 24) { /* 0120 */
  13384. righttop = 1 - interpolateX$1(maxV, tr, br);
  13385. bottomright = interpolateX$1(maxV, bl, br);
  13386. bottomleft = interpolateX$1(minV, bl, br);
  13387. topright = interpolateX$1(minV, tl, tr);
  13388. edges.push(isoBandEdgeRT[cval]);
  13389. edges.push(isoBandEdgeBL[cval]);
  13390. } else if (cval === 146) { /* 2102 */
  13391. righttop = interpolateX$1(minV, br, tr);
  13392. bottomright = 1 - interpolateX$1(minV, br, bl);
  13393. bottomleft = 1 - interpolateX$1(maxV, br, bl);
  13394. topright = 1 - interpolateX$1(maxV, tr, tl);
  13395. edges.push(isoBandEdgeRT[cval]);
  13396. edges.push(isoBandEdgeBL[cval]);
  13397. } else if (cval === 6) { /* 0012 */
  13398. rightbottom = 1 - interpolateX$1(minV, tr, br);
  13399. bottomright = 1 - interpolateX$1(maxV, br, bl);
  13400. leftbottom = 1 - interpolateX$1(maxV, tl, bl);
  13401. lefttop = 1 - interpolateX$1(minV, tl, bl);
  13402. edges.push(isoBandEdgeRB[cval]);
  13403. edges.push(isoBandEdgeBR[cval]);
  13404. } else if (cval === 164) { /* 2210 */
  13405. rightbottom = interpolateX$1(maxV, br, tr);
  13406. bottomright = interpolateX$1(minV, bl, br);
  13407. leftbottom = interpolateX$1(minV, bl, tl);
  13408. lefttop = interpolateX$1(maxV, bl, tl);
  13409. edges.push(isoBandEdgeRB[cval]);
  13410. edges.push(isoBandEdgeBR[cval]);
  13411. } else if (cval === 129) { /* 2001 */
  13412. bottomleft = 1 - interpolateX$1(minV, br, bl);
  13413. leftbottom = interpolateX$1(maxV, bl, tl);
  13414. topleft = 1 - interpolateX$1(maxV, tr, tl);
  13415. topright = 1 - interpolateX$1(minV, tr, tl);
  13416. edges.push(isoBandEdgeBL[cval]);
  13417. edges.push(isoBandEdgeLB[cval]);
  13418. } else if (cval === 41) { /* 0221 */
  13419. bottomleft = interpolateX$1(maxV, bl, br);
  13420. leftbottom = 1 - interpolateX$1(minV, tl, bl);
  13421. topleft = interpolateX$1(minV, tl, tr);
  13422. topright = interpolateX$1(maxV, tl, tr);
  13423. edges.push(isoBandEdgeBL[cval]);
  13424. edges.push(isoBandEdgeLB[cval]);
  13425. } else if (cval === 66) { /* 1002 */
  13426. bottomright = 1 - interpolateX$1(minV, br, bl);
  13427. bottomleft = 1 - interpolateX$1(maxV, br, bl);
  13428. lefttop = 1 - interpolateX$1(maxV, tl, bl);
  13429. topleft = 1 - interpolateX$1(minV, tr, tl);
  13430. edges.push(isoBandEdgeBR[cval]);
  13431. edges.push(isoBandEdgeBL[cval]);
  13432. } else if (cval === 104) { /* 1220 */
  13433. bottomright = interpolateX$1(maxV, bl, br);
  13434. bottomleft = interpolateX$1(minV, bl, br);
  13435. lefttop = interpolateX$1(minV, bl, tl);
  13436. topleft = interpolateX$1(maxV, tl, tr);
  13437. edges.push(isoBandEdgeBL[cval]);
  13438. edges.push(isoBandEdgeTL[cval]);
  13439. } else if (cval === 144) { /* 2100 */
  13440. righttop = interpolateX$1(minV, br, tr);
  13441. leftbottom = interpolateX$1(minV, bl, tl);
  13442. lefttop = interpolateX$1(maxV, bl, tl);
  13443. topright = 1 - interpolateX$1(maxV, tr, tl);
  13444. edges.push(isoBandEdgeRT[cval]);
  13445. edges.push(isoBandEdgeLT[cval]);
  13446. } else if (cval === 26) { /* 0122 */
  13447. righttop = 1 - interpolateX$1(maxV, tr, br);
  13448. leftbottom = 1 - interpolateX$1(maxV, tl, bl);
  13449. lefttop = 1 - interpolateX$1(minV, tl, bl);
  13450. topright = interpolateX$1(minV, tl, tr);
  13451. edges.push(isoBandEdgeRT[cval]);
  13452. edges.push(isoBandEdgeLT[cval]);
  13453. } else if (cval === 36) { /* 0210 */
  13454. rightbottom = interpolateX$1(maxV, br, tr);
  13455. bottomright = interpolateX$1(minV, bl, br);
  13456. topleft = interpolateX$1(minV, tl, tr);
  13457. topright = interpolateX$1(maxV, tl, tr);
  13458. edges.push(isoBandEdgeRB[cval]);
  13459. edges.push(isoBandEdgeBR[cval]);
  13460. } else if (cval === 134) { /* 2012 */
  13461. rightbottom = 1 - interpolateX$1(minV, tr, br);
  13462. bottomright = 1 - interpolateX$1(maxV, br, bl);
  13463. topleft = 1 - interpolateX$1(maxV, tr, tl);
  13464. topright = 1 - interpolateX$1(minV, tr, tl);
  13465. edges.push(isoBandEdgeRB[cval]);
  13466. edges.push(isoBandEdgeBR[cval]);
  13467. } else if (cval === 9) { /* 0021 */
  13468. righttop = 1 - interpolateX$1(minV, tr, br);
  13469. rightbottom = 1 - interpolateX$1(maxV, tr, br);
  13470. bottomleft = interpolateX$1(maxV, bl, br);
  13471. leftbottom = 1 - interpolateX$1(minV, tl, bl);
  13472. edges.push(isoBandEdgeRT[cval]);
  13473. edges.push(isoBandEdgeRB[cval]);
  13474. } else if (cval === 161) { /* 2201 */
  13475. righttop = interpolateX$1(maxV, br, tr);
  13476. rightbottom = interpolateX$1(minV, br, tr);
  13477. bottomleft = 1 - interpolateX$1(minV, br, bl);
  13478. leftbottom = interpolateX$1(maxV, bl, tl);
  13479. edges.push(isoBandEdgeRT[cval]);
  13480. edges.push(isoBandEdgeRB[cval]);
  13481. }
  13482. /* 5th single hexagon cases */
  13483. else if (cval === 37) { /* 0211 */
  13484. rightbottom = interpolateX$1(maxV, br, tr);
  13485. leftbottom = 1 - interpolateX$1(minV, tl, bl);
  13486. topleft = interpolateX$1(minV, tl, tr);
  13487. topright = interpolateX$1(maxV, tl, tr);
  13488. edges.push(isoBandEdgeRB[cval]);
  13489. edges.push(isoBandEdgeLB[cval]);
  13490. } else if (cval === 133) { /* 2011 */
  13491. rightbottom = 1 - interpolateX$1(minV, tr, br);
  13492. leftbottom = interpolateX$1(maxV, bl, tl);
  13493. topleft = 1 - interpolateX$1(maxV, tr, tl);
  13494. topright = 1 - interpolateX$1(minV, tr, tl);
  13495. edges.push(isoBandEdgeRB[cval]);
  13496. edges.push(isoBandEdgeLB[cval]);
  13497. } else if (cval === 148) { /* 2110 */
  13498. bottomright = interpolateX$1(minV, bl, br);
  13499. leftbottom = interpolateX$1(minV, bl, tl);
  13500. lefttop = interpolateX$1(maxV, bl, tl);
  13501. topright = 1 - interpolateX$1(maxV, tr, tl);
  13502. edges.push(isoBandEdgeBR[cval]);
  13503. edges.push(isoBandEdgeLT[cval]);
  13504. } else if (cval === 22) { /* 0112 */
  13505. bottomright = 1 - interpolateX$1(maxV, br, bl);
  13506. leftbottom = 1 - interpolateX$1(maxV, tl, bl);
  13507. lefttop = 1 - interpolateX$1(minV, tl, bl);
  13508. topright = interpolateX$1(minV, tl, tr);
  13509. edges.push(isoBandEdgeBR[cval]);
  13510. edges.push(isoBandEdgeLT[cval]);
  13511. } else if (cval === 82) { /* 1102 */
  13512. righttop = interpolateX$1(minV, br, tr);
  13513. bottomright = 1 - interpolateX$1(minV, br, bl);
  13514. bottomleft = 1 - interpolateX$1(maxV, br, bl);
  13515. lefttop = 1 - interpolateX$1(maxV, tl, bl);
  13516. edges.push(isoBandEdgeRT[cval]);
  13517. edges.push(isoBandEdgeBL[cval]);
  13518. } else if (cval === 88) { /* 1120 */
  13519. righttop = 1 - interpolateX$1(maxV, tr, br);
  13520. bottomright = interpolateX$1(maxV, bl, br);
  13521. bottomleft = interpolateX$1(minV, bl, br);
  13522. lefttop = interpolateX$1(minV, bl, tl);
  13523. edges.push(isoBandEdgeRT[cval]);
  13524. edges.push(isoBandEdgeBL[cval]);
  13525. } else if (cval === 73) { /* 1021 */
  13526. righttop = 1 - interpolateX$1(minV, tr, br);
  13527. rightbottom = 1 - interpolateX$1(maxV, tr, br);
  13528. bottomleft = interpolateX$1(maxV, bl, br);
  13529. topleft = 1 - interpolateX$1(minV, tr, tl);
  13530. edges.push(isoBandEdgeRT[cval]);
  13531. edges.push(isoBandEdgeRB[cval]);
  13532. } else if (cval === 97) { /* 1201 */
  13533. righttop = interpolateX$1(maxV, br, tr);
  13534. rightbottom = interpolateX$1(minV, br, tr);
  13535. bottomleft = 1 - interpolateX$1(minV, br, bl);
  13536. topleft = interpolateX$1(maxV, tl, tr);
  13537. edges.push(isoBandEdgeRT[cval]);
  13538. edges.push(isoBandEdgeRB[cval]);
  13539. } else if (cval === 145) { /* 2101 */
  13540. righttop = interpolateX$1(minV, br, tr);
  13541. bottomleft = 1 - interpolateX$1(minV, br, bl);
  13542. leftbottom = interpolateX$1(maxV, bl, tl);
  13543. topright = 1 - interpolateX$1(maxV, tr, tl);
  13544. edges.push(isoBandEdgeRT[cval]);
  13545. edges.push(isoBandEdgeLB[cval]);
  13546. } else if (cval === 25) { /* 0121 */
  13547. righttop = 1 - interpolateX$1(maxV, tr, br);
  13548. bottomleft = interpolateX$1(maxV, bl, br);
  13549. leftbottom = 1 - interpolateX$1(minV, tl, bl);
  13550. topright = interpolateX$1(minV, tl, tr);
  13551. edges.push(isoBandEdgeRT[cval]);
  13552. edges.push(isoBandEdgeLB[cval]);
  13553. } else if (cval === 70) { /* 1012 */
  13554. rightbottom = 1 - interpolateX$1(minV, tr, br);
  13555. bottomright = 1 - interpolateX$1(maxV, br, bl);
  13556. lefttop = 1 - interpolateX$1(maxV, tl, bl);
  13557. topleft = 1 - interpolateX$1(minV, tr, tl);
  13558. edges.push(isoBandEdgeRB[cval]);
  13559. edges.push(isoBandEdgeBR[cval]);
  13560. } else if (cval === 100) { /* 1210 */
  13561. rightbottom = interpolateX$1(maxV, br, tr);
  13562. bottomright = interpolateX$1(minV, bl, br);
  13563. lefttop = interpolateX$1(minV, bl, tl);
  13564. topleft = interpolateX$1(maxV, tl, tr);
  13565. edges.push(isoBandEdgeRB[cval]);
  13566. edges.push(isoBandEdgeBR[cval]);
  13567. }
  13568. /* 8-sided cases */
  13569. else if (cval === 34) { /* 0202 || 2020 with flipped == 0 */
  13570. if (flipped === 0) {
  13571. righttop = 1 - interpolateX$1(minV, tr, br);
  13572. rightbottom = 1 - interpolateX$1(maxV, tr, br);
  13573. bottomright = interpolateX$1(maxV, bl, br);
  13574. bottomleft = interpolateX$1(minV, bl, br);
  13575. leftbottom = interpolateX$1(minV, bl, tl);
  13576. lefttop = interpolateX$1(maxV, bl, tl);
  13577. topleft = 1 - interpolateX$1(maxV, tr, tl);
  13578. topright = 1 - interpolateX$1(minV, tr, tl);
  13579. } else {
  13580. righttop = interpolateX$1(maxV, br, tr);
  13581. rightbottom = interpolateX$1(minV, br, tr);
  13582. bottomright = 1 - interpolateX$1(minV, br, bl);
  13583. bottomleft = 1 - interpolateX$1(maxV, br, bl);
  13584. leftbottom = 1 - interpolateX$1(maxV, tl, bl);
  13585. lefttop = 1 - interpolateX$1(minV, tl, bl);
  13586. topleft = interpolateX$1(minV, tl, tr);
  13587. topright = interpolateX$1(maxV, tl, tr);
  13588. }
  13589. edges.push(isoBandEdgeRT[cval]);
  13590. edges.push(isoBandEdgeRB[cval]);
  13591. edges.push(isoBandEdgeLB[cval]);
  13592. edges.push(isoBandEdgeLT[cval]);
  13593. } else if (cval === 35) { /* flipped == 1 state for 0202, and 2020 with flipped == 4*/
  13594. if (flipped === 4) {
  13595. righttop = 1 - interpolateX$1(minV, tr, br);
  13596. rightbottom = 1 - interpolateX$1(maxV, tr, br);
  13597. bottomright = interpolateX$1(maxV, bl, br);
  13598. bottomleft = interpolateX$1(minV, bl, br);
  13599. leftbottom = interpolateX$1(minV, bl, tl);
  13600. lefttop = interpolateX$1(maxV, bl, tl);
  13601. topleft = 1 - interpolateX$1(maxV, tr, tl);
  13602. topright = 1 - interpolateX$1(minV, tr, tl);
  13603. } else {
  13604. righttop = interpolateX$1(maxV, br, tr);
  13605. rightbottom = interpolateX$1(minV, br, tr);
  13606. bottomright = 1 - interpolateX$1(minV, br, bl);
  13607. bottomleft = 1 - interpolateX$1(maxV, br, bl);
  13608. leftbottom = 1 - interpolateX$1(maxV, tl, bl);
  13609. lefttop = 1 - interpolateX$1(minV, tl, bl);
  13610. topleft = interpolateX$1(minV, tl, tr);
  13611. topright = interpolateX$1(maxV, tl, tr);
  13612. }
  13613. edges.push(isoBandEdgeRT[cval]);
  13614. edges.push(isoBandEdgeRB[cval]);
  13615. edges.push(isoBandEdgeBL[cval]);
  13616. edges.push(isoBandEdgeLT[cval]);
  13617. } else if (cval === 136) { /* 2020 || 0202 with flipped == 0 */
  13618. if (flipped === 0) {
  13619. righttop = interpolateX$1(maxV, br, tr);
  13620. rightbottom = interpolateX$1(minV, br, tr);
  13621. bottomright = 1 - interpolateX$1(minV, br, bl);
  13622. bottomleft = 1 - interpolateX$1(maxV, br, bl);
  13623. leftbottom = 1 - interpolateX$1(maxV, tl, bl);
  13624. lefttop = 1 - interpolateX$1(minV, tl, bl);
  13625. topleft = interpolateX$1(minV, tl, tr);
  13626. topright = interpolateX$1(maxV, tl, tr);
  13627. } else {
  13628. righttop = 1 - interpolateX$1(minV, tr, br);
  13629. rightbottom = 1 - interpolateX$1(maxV, tr, br);
  13630. bottomright = interpolateX$1(maxV, bl, br);
  13631. bottomleft = interpolateX$1(minV, bl, br);
  13632. leftbottom = interpolateX$1(minV, bl, tl);
  13633. lefttop = interpolateX$1(maxV, bl, tl);
  13634. topleft = 1 - interpolateX$1(maxV, tr, tl);
  13635. topright = 1 - interpolateX$1(minV, tr, tl);
  13636. }
  13637. edges.push(isoBandEdgeRT[cval]);
  13638. edges.push(isoBandEdgeRB[cval]);
  13639. edges.push(isoBandEdgeLB[cval]);
  13640. edges.push(isoBandEdgeLT[cval]);
  13641. }
  13642. /* 6-sided polygon cases */
  13643. else if (cval === 153) { /* 0101 with flipped == 0 || 2121 with flipped == 2 */
  13644. if (flipped === 0) {
  13645. righttop = interpolateX$1(minV, br, tr);
  13646. bottomleft = 1 - interpolateX$1(minV, br, bl);
  13647. leftbottom = 1 - interpolateX$1(minV, tl, bl);
  13648. topright = interpolateX$1(minV, tl, tr);
  13649. } else {
  13650. righttop = 1 - interpolateX$1(maxV, tr, br);
  13651. bottomleft = interpolateX$1(maxV, bl, br);
  13652. leftbottom = interpolateX$1(maxV, bl, tl);
  13653. topright = 1 - interpolateX$1(maxV, tr, tl);
  13654. }
  13655. edges.push(isoBandEdgeRT[cval]);
  13656. edges.push(isoBandEdgeBL[cval]);
  13657. } else if (cval === 102) { /* 1010 with flipped == 0 || 1212 with flipped == 2 */
  13658. if (flipped === 0) {
  13659. rightbottom = 1 - interpolateX$1(minV, tr, br);
  13660. bottomright = interpolateX$1(minV, bl, br);
  13661. lefttop = interpolateX$1(minV, bl, tl);
  13662. topleft = 1 - interpolateX$1(minV, tr, tl);
  13663. } else {
  13664. rightbottom = interpolateX$1(maxV, br, tr);
  13665. bottomright = 1 - interpolateX$1(maxV, br, bl);
  13666. lefttop = 1 - interpolateX$1(maxV, tl, bl);
  13667. topleft = interpolateX$1(maxV, tl, tr);
  13668. }
  13669. edges.push(isoBandEdgeRB[cval]);
  13670. edges.push(isoBandEdgeLT[cval]);
  13671. } else if (cval === 155) { /* 0101 with flipped == 4 || 2121 with flipped == 1 */
  13672. if (flipped === 4) {
  13673. righttop = interpolateX$1(minV, br, tr);
  13674. bottomleft = 1 - interpolateX$1(minV, br, bl);
  13675. leftbottom = 1 - interpolateX$1(minV, tl, bl);
  13676. topright = interpolateX$1(minV, tl, tr);
  13677. } else {
  13678. righttop = 1 - interpolateX$1(maxV, tr, br);
  13679. bottomleft = interpolateX$1(maxV, bl, br);
  13680. leftbottom = interpolateX$1(maxV, bl, tl);
  13681. topright = 1 - interpolateX$1(maxV, tr, tl);
  13682. }
  13683. edges.push(isoBandEdgeRT[cval]);
  13684. edges.push(isoBandEdgeLB[cval]);
  13685. } else if (cval === 103) { /* 1010 with flipped == 4 || 1212 with flipped == 1 */
  13686. if (flipped === 4) {
  13687. rightbottom = 1 - interpolateX$1(minV, tr, br);
  13688. bottomright = interpolateX$1(minV, bl, br);
  13689. lefttop = interpolateX$1(minV, bl, tl);
  13690. topleft = 1 - interpolateX$1(minV, tr, tl);
  13691. } else {
  13692. rightbottom = interpolateX$1(maxV, br, tr);
  13693. bottomright = 1 - interpolateX$1(maxV, br, bl);
  13694. lefttop = 1 - interpolateX$1(maxV, tl, bl);
  13695. topleft = interpolateX$1(maxV, tl, tr);
  13696. }
  13697. edges.push(isoBandEdgeRB[cval]);
  13698. edges.push(isoBandEdgeBR[cval]);
  13699. }
  13700. /* 7-sided polygon cases */
  13701. else if (cval === 152) { /* 2120 with flipped == 2 || 0102 with flipped == 0 */
  13702. if (flipped === 0) {
  13703. righttop = interpolateX$1(minV, br, tr);
  13704. bottomright = 1 - interpolateX$1(minV, br, bl);
  13705. bottomleft = 1 - interpolateX$1(maxV, br, bl);
  13706. leftbottom = 1 - interpolateX$1(maxV, tl, bl);
  13707. lefttop = 1 - interpolateX$1(minV, tl, bl);
  13708. topright = interpolateX$1(minV, tl, tr);
  13709. } else {
  13710. righttop = 1 - interpolateX$1(maxV, tr, br);
  13711. bottomright = interpolateX$1(maxV, bl, br);
  13712. bottomleft = interpolateX$1(minV, bl, br);
  13713. leftbottom = interpolateX$1(minV, bl, tl);
  13714. lefttop = interpolateX$1(maxV, bl, tl);
  13715. topright = 1 - interpolateX$1(maxV, tr, tl);
  13716. }
  13717. edges.push(isoBandEdgeRT[cval]);
  13718. edges.push(isoBandEdgeBR[cval]);
  13719. edges.push(isoBandEdgeBL[cval]);
  13720. } else if (cval === 156) { /* 2120 with flipped == 1 || 0102 with flipped == 4 */
  13721. if (flipped === 4) {
  13722. righttop = interpolateX$1(minV, br, tr);
  13723. bottomright = 1 - interpolateX$1(minV, br, bl);
  13724. bottomleft = 1 - interpolateX$1(maxV, br, bl);
  13725. leftbottom = 1 - interpolateX$1(maxV, tl, bl);
  13726. lefttop = 1 - interpolateX$1(minV, tl, bl);
  13727. topright = interpolateX$1(minV, tl, tr);
  13728. } else {
  13729. righttop = 1 - interpolateX$1(maxV, tr, br);
  13730. bottomright = interpolateX$1(maxV, bl, br);
  13731. bottomleft = interpolateX$1(minV, bl, br);
  13732. leftbottom = interpolateX$1(minV, bl, tl);
  13733. lefttop = interpolateX$1(maxV, bl, tl);
  13734. topright = 1 - interpolateX$1(maxV, tr, tl);
  13735. }
  13736. edges.push(isoBandEdgeRT[cval]);
  13737. edges.push(isoBandEdgeBL[cval]);
  13738. edges.push(isoBandEdgeLT[cval]);
  13739. } else if (cval === 137) { /* 2021 with flipped == 2 || 0201 with flipped == 0 */
  13740. if (flipped === 0) {
  13741. righttop = interpolateX$1(maxV, br, tr);
  13742. rightbottom = interpolateX$1(minV, br, tr);
  13743. bottomleft = 1 - interpolateX$1(minV, br, bl);
  13744. leftbottom = 1 - interpolateX$1(minV, tl, bl);
  13745. topleft = interpolateX$1(minV, tl, tr);
  13746. topright = interpolateX$1(maxV, tl, tr);
  13747. } else {
  13748. righttop = 1 - interpolateX$1(minV, tr, br);
  13749. rightbottom = 1 - interpolateX$1(maxV, tr, br);
  13750. bottomleft = interpolateX$1(maxV, bl, br);
  13751. leftbottom = interpolateX$1(maxV, bl, tl);
  13752. topleft = 1 - interpolateX$1(maxV, tr, tl);
  13753. topright = 1 - interpolateX$1(minV, tr, tl);
  13754. }
  13755. edges.push(isoBandEdgeRT[cval]);
  13756. edges.push(isoBandEdgeRB[cval]);
  13757. edges.push(isoBandEdgeBL[cval]);
  13758. } else if (cval === 139) { /* 2021 with flipped == 1 || 0201 with flipped == 4 */
  13759. if (flipped === 4) {
  13760. righttop = interpolateX$1(maxV, br, tr);
  13761. rightbottom = interpolateX$1(minV, br, tr);
  13762. bottomleft = 1 - interpolateX$1(minV, br, bl);
  13763. leftbottom = 1 - interpolateX$1(minV, tl, bl);
  13764. topleft = interpolateX$1(minV, tl, tr);
  13765. topright = interpolateX$1(maxV, tl, tr);
  13766. } else {
  13767. righttop = 1 - interpolateX$1(minV, tr, br);
  13768. rightbottom = 1 - interpolateX$1(maxV, tr, br);
  13769. bottomleft = interpolateX$1(maxV, bl, br);
  13770. leftbottom = interpolateX$1(maxV, bl, tl);
  13771. topleft = 1 - interpolateX$1(maxV, tr, tl);
  13772. topright = 1 - interpolateX$1(minV, tr, tl);
  13773. }
  13774. edges.push(isoBandEdgeRT[cval]);
  13775. edges.push(isoBandEdgeRB[cval]);
  13776. edges.push(isoBandEdgeLB[cval]);
  13777. } else if (cval === 98) { /* 1202 with flipped == 2 || 1020 with flipped == 0 */
  13778. if (flipped === 0) {
  13779. righttop = 1 - interpolateX$1(minV, tr, br);
  13780. rightbottom = 1 - interpolateX$1(maxV, tr, br);
  13781. bottomright = interpolateX$1(maxV, bl, br);
  13782. bottomleft = interpolateX$1(minV, bl, br);
  13783. lefttop = interpolateX$1(minV, bl, tl);
  13784. topleft = 1 - interpolateX$1(minV, tr, tl);
  13785. } else {
  13786. righttop = interpolateX$1(maxV, br, tr);
  13787. rightbottom = interpolateX$1(minV, br, tr);
  13788. bottomright = 1 - interpolateX$1(minV, br, bl);
  13789. bottomleft = 1 - interpolateX$1(maxV, br, bl);
  13790. lefttop = 1 - interpolateX$1(maxV, tl, bl);
  13791. topleft = interpolateX$1(maxV, tl, tr);
  13792. }
  13793. edges.push(isoBandEdgeRT[cval]);
  13794. edges.push(isoBandEdgeRB[cval]);
  13795. edges.push(isoBandEdgeLT[cval]);
  13796. } else if (cval === 99) { /* 1202 with flipped == 1 || 1020 with flipped == 4 */
  13797. if (flipped === 4) {
  13798. righttop = 1 - interpolateX$1(minV, tr, br);
  13799. rightbottom = 1 - interpolateX$1(maxV, tr, br);
  13800. bottomright = interpolateX$1(maxV, bl, br);
  13801. bottomleft = interpolateX$1(minV, bl, br);
  13802. lefttop = interpolateX$1(minV, bl, tl);
  13803. topleft = 1 - interpolateX$1(minV, tr, tl);
  13804. } else {
  13805. righttop = interpolateX$1(maxV, br, tr);
  13806. rightbottom = interpolateX$1(minV, br, tr);
  13807. bottomright = 1 - interpolateX$1(minV, br, bl);
  13808. bottomleft = 1 - interpolateX$1(maxV, br, bl);
  13809. lefttop = 1 - interpolateX$1(maxV, tl, bl);
  13810. topleft = interpolateX$1(maxV, tl, tr);
  13811. }
  13812. edges.push(isoBandEdgeRT[cval]);
  13813. edges.push(isoBandEdgeRB[cval]);
  13814. edges.push(isoBandEdgeBL[cval]);
  13815. } else if (cval === 38) { /* 0212 with flipped == 2 || 2010 with flipped == 0 */
  13816. if (flipped === 0) {
  13817. rightbottom = 1 - interpolateX$1(minV, tr, br);
  13818. bottomright = interpolateX$1(minV, bl, br);
  13819. leftbottom = interpolateX$1(minV, bl, tl);
  13820. lefttop = interpolateX$1(maxV, bl, tl);
  13821. topleft = 1 - interpolateX$1(maxV, tr, tl);
  13822. topright = 1 - interpolateX$1(minV, tr, tl);
  13823. } else {
  13824. rightbottom = interpolateX$1(maxV, br, tr);
  13825. bottomright = 1 - interpolateX$1(maxV, br, bl);
  13826. leftbottom = 1 - interpolateX$1(maxV, tl, bl);
  13827. lefttop = 1 - interpolateX$1(minV, tl, bl);
  13828. topleft = interpolateX$1(minV, tl, tr);
  13829. topright = interpolateX$1(maxV, tl, tr);
  13830. }
  13831. edges.push(isoBandEdgeRB[cval]);
  13832. edges.push(isoBandEdgeLB[cval]);
  13833. edges.push(isoBandEdgeLT[cval]);
  13834. } else if (cval === 39) { /* 0212 with flipped == 1 || 2010 with flipped == 4 */
  13835. if (flipped === 4) {
  13836. rightbottom = 1 - interpolateX$1(minV, tr, br);
  13837. bottomright = interpolateX$1(minV, bl, br);
  13838. leftbottom = interpolateX$1(minV, bl, tl);
  13839. lefttop = interpolateX$1(maxV, bl, tl);
  13840. topleft = 1 - interpolateX$1(maxV, tr, tl);
  13841. topright = 1 - interpolateX$1(minV, tr, tl);
  13842. } else {
  13843. rightbottom = interpolateX$1(maxV, br, tr);
  13844. bottomright = 1 - interpolateX$1(maxV, br, bl);
  13845. leftbottom = 1 - interpolateX$1(maxV, tl, bl);
  13846. lefttop = 1 - interpolateX$1(minV, tl, bl);
  13847. topleft = interpolateX$1(minV, tl, tr);
  13848. topright = interpolateX$1(maxV, tl, tr);
  13849. }
  13850. edges.push(isoBandEdgeRB[cval]);
  13851. edges.push(isoBandEdgeBR[cval]);
  13852. edges.push(isoBandEdgeLT[cval]);
  13853. } else if (cval === 85) {
  13854. righttop = 1;
  13855. rightbottom = 0;
  13856. bottomright = 1;
  13857. bottomleft = 0;
  13858. leftbottom = 0;
  13859. lefttop = 1;
  13860. topleft = 0;
  13861. topright = 1;
  13862. }
  13863. if (topleft < 0 || topleft > 1 || topright < 0 || topright > 1 || righttop < 0 || righttop > 1 || bottomright < 0 || bottomright > 1 || leftbottom < 0 || leftbottom > 1 || lefttop < 0 || lefttop > 1) {
  13864. console.log('MarchingSquaresJS-isoBands: ' + cval + ' ' + cval_real + ' ' + tl + ',' + tr + ',' + br + ',' + bl + ' ' + flipped + ' ' + topleft + ' ' + topright + ' ' + righttop + ' ' + rightbottom + ' ' + bottomright + ' ' + bottomleft + ' ' + leftbottom + ' ' + lefttop);
  13865. }
  13866. BandGrid.cells[j][i] = {
  13867. cval: cval,
  13868. cval_real: cval_real,
  13869. flipped: flipped,
  13870. topleft: topleft,
  13871. topright: topright,
  13872. righttop: righttop,
  13873. rightbottom: rightbottom,
  13874. bottomright: bottomright,
  13875. bottomleft: bottomleft,
  13876. leftbottom: leftbottom,
  13877. lefttop: lefttop,
  13878. edges: edges
  13879. };
  13880. }
  13881. }
  13882. }
  13883. return BandGrid;
  13884. }
  13885. function BandGrid2AreaPaths(grid) {
  13886. var areas = [];
  13887. var rows = grid.rows;
  13888. var cols = grid.cols;
  13889. var currentPolygon = [];
  13890. for (var j = 0; j < rows; j++) {
  13891. for (var i = 0; i < cols; i++) {
  13892. if ((typeof grid.cells[j][i] !== 'undefined') && (grid.cells[j][i].edges.length > 0)) {
  13893. /* trace back polygon path starting from this cell */
  13894. var cell = grid.cells[j][i];
  13895. /* get start coordinates */
  13896. var prev = getStartXY(cell),
  13897. next = null,
  13898. p = i,
  13899. q = j;
  13900. if (prev !== null) {
  13901. currentPolygon.push([prev.p[0] + p, prev.p[1] + q]);
  13902. //console.log(cell);
  13903. //console.log("coords: " + (prev.p[0] + p) + " " + (prev.p[1] + q));
  13904. }
  13905. do {
  13906. //console.log(p + "," + q);
  13907. //console.log(grid.cells[q][p]);
  13908. //console.log(grid.cells[q][p].edges);
  13909. //console.log("from : " + prev.x + " " + prev.y + " " + prev.o);
  13910. next = getExitXY(grid.cells[q][p], prev.x, prev.y, prev.o);
  13911. if (next !== null) {
  13912. //console.log("coords: " + (next.p[0] + p) + " " + (next.p[1] + q));
  13913. currentPolygon.push([next.p[0] + p, next.p[1] + q]);
  13914. p += next.x;
  13915. q += next.y;
  13916. prev = next;
  13917. } else {
  13918. //console.log("getExitXY() returned null!");
  13919. break;
  13920. }
  13921. //console.log("to : " + next.x + " " + next.y + " " + next.o);
  13922. /* special case, where we've reached the grid boundaries */
  13923. if ((q < 0) || (q >= rows) || (p < 0) || (p >= cols) || (typeof grid.cells[q][p] === 'undefined')) {
  13924. /* to create a closed path, we need to trace our way
  13925. arround the missing data, until we find an entry
  13926. point again
  13927. */
  13928. /* set back coordinates of current cell */
  13929. p -= next.x;
  13930. q -= next.y;
  13931. //console.log("reached boundary at " + p + " " + q);
  13932. var missing = traceOutOfGridPath(grid, p, q, next.x, next.y, next.o);
  13933. if (missing !== null) {
  13934. missing.path.forEach(function (pp) {
  13935. //console.log("coords: " + (pp[0]) + " " + (pp[1]));
  13936. currentPolygon.push(pp);
  13937. });
  13938. p = missing.i;
  13939. q = missing.j;
  13940. prev = missing;
  13941. } else {
  13942. break;
  13943. }
  13944. //console.log(grid.cells[q][p]);
  13945. }
  13946. } while ((typeof grid.cells[q][p] !== 'undefined') &&
  13947. (grid.cells[q][p].edges.length > 0));
  13948. areas.push(currentPolygon);
  13949. //console.log("next polygon");
  13950. //console.log(currentPolygon);
  13951. currentPolygon = [];
  13952. if (grid.cells[j][i].edges.length > 0)
  13953. i--;
  13954. }
  13955. }
  13956. }
  13957. return areas;
  13958. }
  13959. function traceOutOfGridPath(grid, i, j, d_x, d_y, d_o) {
  13960. var cell = grid.cells[j][i];
  13961. var cval = cell.cval_real;
  13962. var p = i + d_x,
  13963. q = j + d_y;
  13964. var path = [];
  13965. var closed = false;
  13966. while (!closed) {
  13967. //console.log("processing cell " + p + "," + q + " " + d_x + " " + d_y + " " + d_o);
  13968. if ((typeof grid.cells[q] === 'undefined') || (typeof grid.cells[q][p] === 'undefined')) {
  13969. //console.log("which is undefined");
  13970. /* we can't move on, so we have to change direction to proceed further */
  13971. /* go back to previous cell */
  13972. q -= d_y;
  13973. p -= d_x;
  13974. cell = grid.cells[q][p];
  13975. cval = cell.cval_real;
  13976. /* check where we've left defined cells of the grid... */
  13977. if (d_y === -1) { /* we came from top */
  13978. if (d_o === 0) { /* exit left */
  13979. if (cval & Node3) { /* lower left node is within range, so we move left */
  13980. path.push([p, q]);
  13981. d_x = -1;
  13982. d_y = 0;
  13983. d_o = 0;
  13984. } else if (cval & Node2) { /* lower right node is within range, so we move right */
  13985. path.push([p + 1, q]);
  13986. d_x = 1;
  13987. d_y = 0;
  13988. d_o = 0;
  13989. } else { /* close the path */
  13990. path.push([p + cell.bottomright, q]);
  13991. d_x = 0;
  13992. d_y = 1;
  13993. d_o = 1;
  13994. closed = true;
  13995. break;
  13996. }
  13997. } else if (cval & Node3) {
  13998. path.push([p, q]);
  13999. d_x = -1;
  14000. d_y = 0;
  14001. d_o = 0;
  14002. } else if (cval & Node2) {
  14003. path.push([p + cell.bottomright, q]);
  14004. d_x = 0;
  14005. d_y = 1;
  14006. d_o = 1;
  14007. closed = true;
  14008. break;
  14009. } else {
  14010. path.push([p + cell.bottomleft, q]);
  14011. d_x = 0;
  14012. d_y = 1;
  14013. d_o = 0;
  14014. closed = true;
  14015. break;
  14016. }
  14017. } else if (d_y === 1) { /* we came from bottom */
  14018. //console.log("we came from bottom and hit a non-existing cell " + (p + d_x) + "," + (q + d_y) + "!");
  14019. if (d_o === 0) { /* exit left */
  14020. if (cval & Node1) { /* top right node is within range, so we move right */
  14021. path.push([p + 1, q + 1]);
  14022. d_x = 1;
  14023. d_y = 0;
  14024. d_o = 1;
  14025. } else if (!(cval & Node0)) { /* found entry within same cell */
  14026. path.push([p + cell.topright, q + 1]);
  14027. d_x = 0;
  14028. d_y = -1;
  14029. d_o = 1;
  14030. closed = true;
  14031. //console.log("found entry from bottom at " + p + "," + q);
  14032. break;
  14033. } else {
  14034. path.push([p + cell.topleft, q + 1]);
  14035. d_x = 0;
  14036. d_y = -1;
  14037. d_o = 0;
  14038. closed = true;
  14039. break;
  14040. }
  14041. } else if (cval & Node1) {
  14042. path.push([p + 1, q + 1]);
  14043. d_x = 1;
  14044. d_y = 0;
  14045. d_o = 1;
  14046. } else { /* move right */
  14047. path.push([p + 1, q + 1]);
  14048. d_x = 1;
  14049. d_y = 0;
  14050. d_o = 1;
  14051. //console.log("wtf");
  14052. //break;
  14053. }
  14054. } else if (d_x === -1) { /* we came from right */
  14055. //console.log("we came from right and hit a non-existing cell at " + (p + d_x) + "," + (q + d_y) + "!");
  14056. if (d_o === 0) {
  14057. //console.log("continue at bottom");
  14058. if (cval & Node0) {
  14059. path.push([p, q + 1]);
  14060. d_x = 0;
  14061. d_y = 1;
  14062. d_o = 0;
  14063. //console.log("moving upwards to " + (p + d_x) + "," + (q + d_y) + "!");
  14064. } else if (!(cval & Node3)) { /* there has to be an entry into the regular grid again! */
  14065. //console.log("exiting top");
  14066. path.push([p, q + cell.lefttop]);
  14067. d_x = 1;
  14068. d_y = 0;
  14069. d_o = 1;
  14070. closed = true;
  14071. break;
  14072. } else {
  14073. //console.log("exiting bottom");
  14074. path.push([p, q + cell.leftbottom]);
  14075. d_x = 1;
  14076. d_y = 0;
  14077. d_o = 0;
  14078. closed = true;
  14079. break;
  14080. }
  14081. } else {
  14082. //console.log("continue at top");
  14083. if (cval & Node0) {
  14084. path.push([p, q + 1]);
  14085. d_x = 0;
  14086. d_y = 1;
  14087. d_o = 0;
  14088. //console.log("moving upwards to " + (p + d_x) + "," + (q + d_y) + "!");
  14089. } else { /* */
  14090. console.log('MarchingSquaresJS-isoBands: wtf');
  14091. break;
  14092. }
  14093. }
  14094. } else if (d_x === 1) { /* we came from left */
  14095. //console.log("we came from left and hit a non-existing cell " + (p + d_x) + "," + (q + d_y) + "!");
  14096. if (d_o === 0) { /* exit bottom */
  14097. if (cval & Node2) {
  14098. path.push([p + 1, q]);
  14099. d_x = 0;
  14100. d_y = -1;
  14101. d_o = 1;
  14102. } else {
  14103. path.push([p + 1, q + cell.rightbottom]);
  14104. d_x = -1;
  14105. d_y = 0;
  14106. d_o = 0;
  14107. closed = true;
  14108. break;
  14109. }
  14110. } else { /* exit top */
  14111. if (cval & Node2) {
  14112. path.push([p + 1, q]);
  14113. d_x = 0;
  14114. d_y = -1;
  14115. d_o = 1;
  14116. } else if (!(cval & Node1)) {
  14117. path.push([p + 1, q + cell.rightbottom]);
  14118. d_x = -1;
  14119. d_y = 0;
  14120. d_o = 0;
  14121. closed = true;
  14122. break;
  14123. } else {
  14124. path.push([p + 1, q + cell.righttop]);
  14125. d_x = -1;
  14126. d_y = 0;
  14127. d_o = 1;
  14128. break;
  14129. }
  14130. }
  14131. } else { /* we came from the same cell */
  14132. console.log('MarchingSquaresJS-isoBands: we came from nowhere!');
  14133. break;
  14134. }
  14135. } else { /* try to find an entry into the regular grid again! */
  14136. cell = grid.cells[q][p];
  14137. cval = cell.cval_real;
  14138. //console.log("which is defined");
  14139. if (d_x === -1) {
  14140. if (d_o === 0) {
  14141. /* try to go downwards */
  14142. if ((typeof grid.cells[q - 1] !== 'undefined') && (typeof grid.cells[q - 1][p] !== 'undefined')) {
  14143. d_x = 0;
  14144. d_y = -1;
  14145. d_o = 1;
  14146. } else if (cval & Node3) { /* proceed searching in x-direction */
  14147. //console.log("proceeding in x-direction!");
  14148. path.push([p, q]);
  14149. } else { /* we must have found an entry into the regular grid */
  14150. path.push([p + cell.bottomright, q]);
  14151. d_x = 0;
  14152. d_y = 1;
  14153. d_o = 1;
  14154. closed = true;
  14155. //console.log("found entry from bottom at " + p + "," + q);
  14156. break;
  14157. }
  14158. } else if (cval & Node0) { /* proceed searchin in x-direction */
  14159. console.log('MarchingSquaresJS-isoBands: proceeding in x-direction!');
  14160. } else { /* we must have found an entry into the regular grid */
  14161. console.log('MarchingSquaresJS-isoBands: found entry from top at ' + p + ',' + q);
  14162. break;
  14163. }
  14164. } else if (d_x === 1) {
  14165. if (d_o === 0) {
  14166. console.log('MarchingSquaresJS-isoBands: wtf');
  14167. break;
  14168. } else {
  14169. /* try to go upwards */
  14170. if ((typeof grid.cells[q + 1] !== 'undefined') && (typeof grid.cells[q + 1][p] !== 'undefined')) {
  14171. d_x = 0;
  14172. d_y = 1;
  14173. d_o = 0;
  14174. } else if (cval & Node1) {
  14175. path.push([p + 1, q + 1]);
  14176. d_x = 1;
  14177. d_y = 0;
  14178. d_o = 1;
  14179. } else { /* found an entry point into regular grid! */
  14180. path.push([p + cell.topleft, q + 1]);
  14181. d_x = 0;
  14182. d_y = -1;
  14183. d_o = 0;
  14184. closed = true;
  14185. //console.log("found entry from bottom at " + p + "," + q);
  14186. break;
  14187. }
  14188. }
  14189. } else if (d_y === -1) {
  14190. if (d_o === 1) {
  14191. /* try to go right */
  14192. if (typeof grid.cells[q][p + 1] !== 'undefined') {
  14193. d_x = 1;
  14194. d_y = 0;
  14195. d_o = 1;
  14196. } else if (cval & Node2) {
  14197. path.push([p + 1, q]);
  14198. d_x = 0;
  14199. d_y = -1;
  14200. d_o = 1;
  14201. } else { /* found entry into regular grid! */
  14202. path.push([p + 1, q + cell.righttop]);
  14203. d_x = -1;
  14204. d_y = 0;
  14205. d_o = 1;
  14206. closed = true;
  14207. //console.log("found entry from top at " + p + "," + q);
  14208. break;
  14209. }
  14210. } else {
  14211. console.log('MarchingSquaresJS-isoBands: wtf');
  14212. break;
  14213. }
  14214. } else if (d_y === 1) {
  14215. if (d_o === 0) {
  14216. //console.log("we came from bottom left and proceed to the left");
  14217. /* try to go left */
  14218. if (typeof grid.cells[q][p - 1] !== 'undefined') {
  14219. d_x = -1;
  14220. d_y = 0;
  14221. d_o = 0;
  14222. } else if (cval & Node0) {
  14223. path.push([p, q + 1]);
  14224. d_x = 0;
  14225. d_y = 1;
  14226. d_o = 0;
  14227. } else { /* found an entry point into regular grid! */
  14228. path.push([p, q + cell.leftbottom]);
  14229. d_x = 1;
  14230. d_y = 0;
  14231. d_o = 0;
  14232. closed = true;
  14233. //console.log("found entry from bottom at " + p + "," + q);
  14234. break;
  14235. }
  14236. } else {
  14237. //console.log("we came from bottom right and proceed to the right");
  14238. console.log('MarchingSquaresJS-isoBands: wtf');
  14239. break;
  14240. }
  14241. } else {
  14242. console.log('MarchingSquaresJS-isoBands: where did we came from???');
  14243. break;
  14244. }
  14245. }
  14246. p += d_x;
  14247. q += d_y;
  14248. //console.log("going on to " + p + "," + q + " via " + d_x + " " + d_y + " " + d_o);
  14249. if ((p === i) && (q === j)) { /* bail out, once we've closed a circle path */
  14250. break;
  14251. }
  14252. }
  14253. //console.log("exit with " + p + "," + q + " " + d_x + " " + d_y + " " + d_o);
  14254. return { path: path, i: p, j: q, x: d_x, y: d_y, o: d_o };
  14255. }
  14256. function deleteEdge(cell, edgeIdx) {
  14257. delete cell.edges[edgeIdx];
  14258. for (var k = edgeIdx + 1; k < cell.edges.length; k++) {
  14259. cell.edges[k - 1] = cell.edges[k];
  14260. }
  14261. cell.edges.pop();
  14262. }
  14263. function getStartXY(cell) {
  14264. if (cell.edges.length > 0) {
  14265. var e = cell.edges[cell.edges.length - 1];
  14266. //console.log("starting with edge " + e);
  14267. var cval = cell.cval_real;
  14268. switch (e) {
  14269. case 0: if (cval & Node1) { /* node 1 within range */
  14270. return {p: [1, cell.righttop], x: -1, y: 0, o: 1};
  14271. } else { /* node 1 below or above threshold */
  14272. return {p: [cell.topleft, 1], x: 0, y: -1, o: 0};
  14273. }
  14274. case 1: if (cval & Node2) {
  14275. return {p: [cell.topleft, 1], x: 0, y: -1, o: 0};
  14276. } else {
  14277. return {p: [1, cell.rightbottom], x: -1, y: 0, o: 0};
  14278. }
  14279. case 2: if (cval & Node2) {
  14280. return {p: [cell.bottomright, 0], x: 0, y: 1, o: 1};
  14281. } else {
  14282. return {p: [cell.topleft, 1], x: 0, y: -1, o: 0};
  14283. }
  14284. case 3: if (cval & Node3) {
  14285. return {p: [cell.topleft, 1], x: 0, y: -1, o: 0};
  14286. } else {
  14287. return {p: [cell.bottomleft, 0], x: 0, y: 1, o: 0};
  14288. }
  14289. case 4: if (cval & Node1) {
  14290. return {p: [1, cell.righttop], x: -1, y: 0, o: 1};
  14291. } else {
  14292. return {p: [cell.topright, 1], x: 0, y: -1, o: 1};
  14293. }
  14294. case 5: if (cval & Node2) {
  14295. return {p: [cell.topright, 1], x: 0, y: -1, o: 1};
  14296. } else {
  14297. return {p: [1, cell.rightbottom], x: -1, y: 0, o: 0};
  14298. }
  14299. case 6: if (cval & Node2) {
  14300. return {p: [cell.bottomright, 0], x: 0, y: 1, o: 1};
  14301. } else {
  14302. return {p: [cell.topright, 1], x: 0, y: -1, o: 1};
  14303. }
  14304. case 7: if (cval & Node3) {
  14305. return {p: [cell.topright, 1], x: 0, y: -1, o: 1};
  14306. } else {
  14307. return {p: [cell.bottomleft, 0], x: 0, y: 1, o: 0};
  14308. }
  14309. case 8: if (cval & Node2) {
  14310. return {p: [cell.bottomright, 0], x: 0, y: 1, o: 1};
  14311. } else {
  14312. return {p: [1, cell.righttop], x: -1, y: 0, o: 1};
  14313. }
  14314. case 9: if (cval & Node3) {
  14315. return {p: [1, cell.righttop], x: -1, y: 0, o: 1};
  14316. } else {
  14317. return {p: [cell.bottomleft, 0], x: 0, y: 1, o: 0};
  14318. }
  14319. case 10: if (cval & Node3) {
  14320. return {p: [0, cell.leftbottom], x: 1, y: 0, o: 0};
  14321. } else {
  14322. return {p: [1, cell.righttop], x: -1, y: 0, o: 1};
  14323. }
  14324. case 11: if (cval & Node0) {
  14325. return {p: [1, cell.righttop], x: -1, y: 0, o: 1};
  14326. } else {
  14327. return {p: [0, cell.lefttop], x: 1, y: 0, o: 1};
  14328. }
  14329. case 12: if (cval & Node2) {
  14330. return {p: [cell.bottomright, 0], x: 0, y: 1, o: 1};
  14331. } else {
  14332. return {p: [1, cell.rightbottom], x: -1, y: 0, o: 0};
  14333. }
  14334. case 13: if (cval & Node3) {
  14335. return {p: [1, cell.rightbottom], x: -1, y: 0, o: 0};
  14336. } else {
  14337. return {p: [cell.bottomleft, 0], x: 0, y: 1, o: 0};
  14338. }
  14339. case 14: if (cval & Node3) {
  14340. return {p: [0, cell.leftbottom], x: 1, y: 0, o: 0};
  14341. } else {
  14342. return {p: [1, cell.rightbottom], x: -1, y: 0, o: 0};
  14343. }
  14344. case 15: if (cval & Node0) {
  14345. return {p: [1, cell.rightbottom], x: -1, y: 0, o: 0};
  14346. } else {
  14347. return {p: [0, cell.lefttop], x: 1, y: 0, o: 1};
  14348. }
  14349. case 16: if (cval & Node2) {
  14350. return {p: [cell.bottomright, 0], x: 0, y: 1, o: 1};
  14351. } else {
  14352. return {p: [0, cell.leftbottom], x: 1, y: 0, o: 0};
  14353. }
  14354. case 17: if (cval & Node0) {
  14355. return {p: [cell.bottomright, 0], x: 0, y: 1, o: 1};
  14356. } else {
  14357. return {p: [0, cell.lefttop], x: 1, y: 0, o: 1};
  14358. }
  14359. case 18: if (cval & Node3) {
  14360. return {p: [0, cell.leftbottom], x: 1, y: 0, o: 0};
  14361. } else {
  14362. return {p: [cell.bottomleft, 0], x: 0, y: 1, o: 0};
  14363. }
  14364. case 19: if (cval & Node0) {
  14365. return {p: [cell.bottomleft, 0], x: 0, y: 1, o: 0};
  14366. } else {
  14367. return {p: [0, cell.lefttop], x: 1, y: 0, o: 1};
  14368. }
  14369. case 20: if (cval & Node0) {
  14370. return {p: [cell.topleft, 1], x: 0, y: -1, o: 0};
  14371. } else {
  14372. return {p: [0, cell.leftbottom], x: 1, y: 0, o: 0};
  14373. }
  14374. case 21: if (cval & Node1) {
  14375. return {p: [0, cell.leftbottom], x: 1, y: 0, o: 0};
  14376. } else {
  14377. return {p: [cell.topright, 1], x: 0, y: -1, o: 1};
  14378. }
  14379. case 22: if (cval & Node0) {
  14380. return {p: [cell.topleft, 1], x: 0, y: -1, o: 0};
  14381. } else {
  14382. return {p: [0, cell.lefttop], x: 1, y: 0, o: 1};
  14383. }
  14384. case 23: if (cval & Node1) {
  14385. return {p: [0, cell.lefttop], x: 1, y: 0, o: 1};
  14386. } else {
  14387. return {p: [cell.topright, 1], x: 0, y: -1, o: 1};
  14388. }
  14389. default: console.log('MarchingSquaresJS-isoBands: edge index out of range!');
  14390. console.log(cell);
  14391. break;
  14392. }
  14393. }
  14394. return null;
  14395. }
  14396. function getExitXY(cell, x, y, o) {
  14397. var e, id_x, d_x, d_y, cval = cell.cval;
  14398. var d_o;
  14399. switch (x) {
  14400. case -1: switch (o) {
  14401. case 0: e = isoBandEdgeRB[cval];
  14402. d_x = isoBandNextXRB[cval];
  14403. d_y = isoBandNextYRB[cval];
  14404. d_o = isoBandNextORB[cval];
  14405. break;
  14406. default: e = isoBandEdgeRT[cval];
  14407. d_x = isoBandNextXRT[cval];
  14408. d_y = isoBandNextYRT[cval];
  14409. d_o = isoBandNextORT[cval];
  14410. break;
  14411. }
  14412. break;
  14413. case 1: switch (o) {
  14414. case 0: e = isoBandEdgeLB[cval];
  14415. d_x = isoBandNextXLB[cval];
  14416. d_y = isoBandNextYLB[cval];
  14417. d_o = isoBandNextOLB[cval];
  14418. break;
  14419. default: e = isoBandEdgeLT[cval];
  14420. d_x = isoBandNextXLT[cval];
  14421. d_y = isoBandNextYLT[cval];
  14422. d_o = isoBandNextOLT[cval];
  14423. break;
  14424. }
  14425. break;
  14426. default: switch (y) {
  14427. case -1: switch (o) {
  14428. case 0: e = isoBandEdgeTL[cval];
  14429. d_x = isoBandNextXTL[cval];
  14430. d_y = isoBandNextYTL[cval];
  14431. d_o = isoBandNextOTL[cval];
  14432. break;
  14433. default: e = isoBandEdgeTR[cval];
  14434. d_x = isoBandNextXTR[cval];
  14435. d_y = isoBandNextYTR[cval];
  14436. d_o = isoBandNextOTR[cval];
  14437. break;
  14438. }
  14439. break;
  14440. case 1: switch (o) {
  14441. case 0: e = isoBandEdgeBL[cval];
  14442. d_x = isoBandNextXBL[cval];
  14443. d_y = isoBandNextYBL[cval];
  14444. d_o = isoBandNextOBL[cval];
  14445. break;
  14446. default: e = isoBandEdgeBR[cval];
  14447. d_x = isoBandNextXBR[cval];
  14448. d_y = isoBandNextYBR[cval];
  14449. d_o = isoBandNextOBR[cval];
  14450. break;
  14451. }
  14452. break;
  14453. default: break;
  14454. }
  14455. break;
  14456. }
  14457. id_x = cell.edges.indexOf(e);
  14458. if (typeof cell.edges[id_x] !== 'undefined') {
  14459. deleteEdge(cell, id_x);
  14460. } else {
  14461. //console.log("wrong edges...");
  14462. //console.log(x + " " + y + " " + o);
  14463. //console.log(cell);
  14464. return null;
  14465. }
  14466. cval = cell.cval_real;
  14467. switch (e) {
  14468. case 0: if (cval & Node1) { /* node 1 within range */
  14469. x = cell.topleft;
  14470. y = 1;
  14471. } else { /* node 1 below or above threshold */
  14472. x = 1;
  14473. y = cell.righttop;
  14474. }
  14475. break;
  14476. case 1: if (cval & Node2) {
  14477. x = 1;
  14478. y = cell.rightbottom;
  14479. } else {
  14480. x = cell.topleft;
  14481. y = 1;
  14482. }
  14483. break;
  14484. case 2: if (cval & Node2) {
  14485. x = cell.topleft;
  14486. y = 1;
  14487. } else {
  14488. x = cell.bottomright;
  14489. y = 0;
  14490. }
  14491. break;
  14492. case 3: if (cval & Node3) {
  14493. x = cell.bottomleft;
  14494. y = 0;
  14495. } else {
  14496. x = cell.topleft;
  14497. y = 1;
  14498. }
  14499. break;
  14500. case 4: if (cval & Node1) {
  14501. x = cell.topright;
  14502. y = 1;
  14503. } else {
  14504. x = 1;
  14505. y = cell.righttop;
  14506. }
  14507. break;
  14508. case 5: if (cval & Node2) {
  14509. x = 1;
  14510. y = cell.rightbottom;
  14511. } else {
  14512. x = cell.topright;
  14513. y = 1;
  14514. }
  14515. break;
  14516. case 6: if (cval & Node2) {
  14517. x = cell.topright;
  14518. y = 1;
  14519. } else {
  14520. x = cell.bottomright;
  14521. y = 0;
  14522. }
  14523. break;
  14524. case 7: if (cval & Node3) {
  14525. x = cell.bottomleft;
  14526. y = 0;
  14527. } else {
  14528. x = cell.topright;
  14529. y = 1;
  14530. }
  14531. break;
  14532. case 8: if (cval & Node2) {
  14533. x = 1;
  14534. y = cell.righttop;
  14535. } else {
  14536. x = cell.bottomright;
  14537. y = 0;
  14538. }
  14539. break;
  14540. case 9: if (cval & Node3) {
  14541. x = cell.bottomleft;
  14542. y = 0;
  14543. } else {
  14544. x = 1;
  14545. y = cell.righttop;
  14546. }
  14547. break;
  14548. case 10: if (cval & Node3) {
  14549. x = 1;
  14550. y = cell.righttop;
  14551. } else {
  14552. x = 0;
  14553. y = cell.leftbottom;
  14554. }
  14555. break;
  14556. case 11: if (cval & Node0) {
  14557. x = 0;
  14558. y = cell.lefttop;
  14559. } else {
  14560. x = 1;
  14561. y = cell.righttop;
  14562. }
  14563. break;
  14564. case 12: if (cval & Node2) {
  14565. x = 1;
  14566. y = cell.rightbottom;
  14567. } else {
  14568. x = cell.bottomright;
  14569. y = 0;
  14570. }
  14571. break;
  14572. case 13: if (cval & Node3) {
  14573. x = cell.bottomleft;
  14574. y = 0;
  14575. } else {
  14576. x = 1;
  14577. y = cell.rightbottom;
  14578. }
  14579. break;
  14580. case 14: if (cval & Node3) {
  14581. x = 1;
  14582. y = cell.rightbottom;
  14583. } else {
  14584. x = 0;
  14585. y = cell.leftbottom;
  14586. }
  14587. break;
  14588. case 15: if (cval & Node0) {
  14589. x = 0;
  14590. y = cell.lefttop;
  14591. } else {
  14592. x = 1;
  14593. y = cell.rightbottom;
  14594. }
  14595. break;
  14596. case 16: if (cval & Node2) {
  14597. x = 0;
  14598. y = cell.leftbottom;
  14599. } else {
  14600. x = cell.bottomright;
  14601. y = 0;
  14602. }
  14603. break;
  14604. case 17: if (cval & Node0) {
  14605. x = 0;
  14606. y = cell.lefttop;
  14607. } else {
  14608. x = cell.bottomright;
  14609. y = 0;
  14610. }
  14611. break;
  14612. case 18: if (cval & Node3) {
  14613. x = cell.bottomleft;
  14614. y = 0;
  14615. } else {
  14616. x = 0;
  14617. y = cell.leftbottom;
  14618. }
  14619. break;
  14620. case 19: if (cval & Node0) {
  14621. x = 0;
  14622. y = cell.lefttop;
  14623. } else {
  14624. x = cell.bottomleft;
  14625. y = 0;
  14626. }
  14627. break;
  14628. case 20: if (cval & Node0) {
  14629. x = 0;
  14630. y = cell.leftbottom;
  14631. } else {
  14632. x = cell.topleft;
  14633. y = 1;
  14634. }
  14635. break;
  14636. case 21: if (cval & Node1) {
  14637. x = cell.topright;
  14638. y = 1;
  14639. } else {
  14640. x = 0;
  14641. y = cell.leftbottom;
  14642. }
  14643. break;
  14644. case 22: if (cval & Node0) {
  14645. x = 0;
  14646. y = cell.lefttop;
  14647. } else {
  14648. x = cell.topleft;
  14649. y = 1;
  14650. }
  14651. break;
  14652. case 23: if (cval & Node1) {
  14653. x = cell.topright;
  14654. y = 1;
  14655. } else {
  14656. x = 0;
  14657. y = cell.lefttop;
  14658. }
  14659. break;
  14660. default: console.log('MarchingSquaresJS-isoBands: edge index out of range!');
  14661. console.log(cell);
  14662. return null;
  14663. }
  14664. if ((typeof x === 'undefined') || (typeof y === 'undefined') ||
  14665. (typeof d_x === 'undefined') || (typeof d_y === 'undefined') ||
  14666. (typeof d_o === 'undefined')) {
  14667. console.log('MarchingSquaresJS-isoBands: undefined value!');
  14668. console.log(cell);
  14669. console.log(x + ' ' + y + ' ' + d_x + ' ' + d_y + ' ' + d_o);
  14670. }
  14671. return {p: [x, y], x: d_x, y: d_y, o: d_o};
  14672. }
  14673. function BandGrid2Areas(grid) {
  14674. var areas = [];
  14675. var area_idx = 0;
  14676. grid.cells.forEach(function (g, j) {
  14677. g.forEach(function (gg, i) {
  14678. if (typeof gg !== 'undefined') {
  14679. var a = polygon_table[gg.cval](gg);
  14680. if ((typeof a === 'object') && isArray(a)) {
  14681. if ((typeof a[0] === 'object') && isArray(a[0])) {
  14682. if ((typeof a[0][0] === 'object') && isArray(a[0][0])) {
  14683. a.forEach(function (aa) {
  14684. aa.forEach(function (aaa) {
  14685. aaa[0] += i;
  14686. aaa[1] += j;
  14687. });
  14688. areas[area_idx++] = aa;
  14689. });
  14690. } else {
  14691. a.forEach(function (aa) {
  14692. aa[0] += i;
  14693. aa[1] += j;
  14694. });
  14695. areas[area_idx++] = a;
  14696. }
  14697. } else {
  14698. console.log('MarchingSquaresJS-isoBands: bandcell polygon with malformed coordinates');
  14699. }
  14700. } else {
  14701. console.log('MarchingSquaresJS-isoBands: bandcell polygon with null coordinates');
  14702. }
  14703. }
  14704. });
  14705. });
  14706. return areas;
  14707. }
  14708. /**
  14709. * Takes a grid {@link FeatureCollection} of {@link Point} features with z-values and an array of
  14710. * value breaks and generates filled contour isobands.
  14711. *
  14712. * @name isobands
  14713. * @param {FeatureCollection<Point>} pointGrid input points
  14714. * @param {Array<number>} breaks where to draw contours
  14715. * @param {Object} [options={}] options on output
  14716. * @param {string} [options.zProperty='elevation'] the property name in `points` from which z-values will be pulled
  14717. * @param {Object} [options.commonProperties={}] GeoJSON properties passed to ALL isobands
  14718. * @param {Array<Object>} [options.breaksProperties=[]] GeoJSON properties passed, in order, to the correspondent isoband (order defined by breaks)
  14719. * @returns {FeatureCollection<MultiPolygon>} a FeatureCollection of {@link MultiPolygon} features representing isobands
  14720. */
  14721. function isobands(pointGrid, breaks, options) {
  14722. // Optional parameters
  14723. options = options || {};
  14724. if (!isObject(options)) throw new Error('options is invalid');
  14725. var zProperty = options.zProperty || 'elevation';
  14726. var commonProperties = options.commonProperties || {};
  14727. var breaksProperties = options.breaksProperties || [];
  14728. // Validation
  14729. collectionOf(pointGrid, 'Point', 'Input must contain Points');
  14730. if (!breaks) throw new Error('breaks is required');
  14731. if (!Array.isArray(breaks)) throw new Error('breaks is not an Array');
  14732. if (!isObject(commonProperties)) throw new Error('commonProperties is not an Object');
  14733. if (!Array.isArray(breaksProperties)) throw new Error('breaksProperties is not an Array');
  14734. // Isoband methods
  14735. var matrix = gridToMatrix$1(pointGrid, {zProperty: zProperty, flip: true});
  14736. var contours = createContourLines(matrix, breaks, zProperty);
  14737. contours = rescaleContours(contours, matrix, pointGrid);
  14738. var multipolygons = contours.map(function (contour, index) {
  14739. if (breaksProperties[index] && !isObject(breaksProperties[index])) {
  14740. throw new Error('Each mappedProperty is required to be an Object');
  14741. }
  14742. // collect all properties
  14743. var contourProperties = Object.assign(
  14744. {},
  14745. commonProperties,
  14746. breaksProperties[index]
  14747. );
  14748. contourProperties[zProperty] = contour[zProperty];
  14749. var multiP = multiPolygon(contour.groupedRings, contourProperties);
  14750. return multiP;
  14751. });
  14752. return featureCollection(multipolygons);
  14753. }
  14754. /**
  14755. * Creates the contours lines (featuresCollection of polygon features) from the 2D data grid
  14756. *
  14757. * Marchingsquares process the grid data as a 3D representation of a function on a 2D plane, therefore it
  14758. * assumes the points (x-y coordinates) are one 'unit' distance. The result of the IsoBands function needs to be
  14759. * rescaled, with turfjs, to the original area and proportions on the map
  14760. *
  14761. * @private
  14762. * @param {Array<Array<number>>} matrix Grid Data
  14763. * @param {Array<number>} breaks Breaks
  14764. * @param {string} [property='elevation'] Property
  14765. * @returns {Array<any>} contours
  14766. */
  14767. function createContourLines(matrix, breaks, property) {
  14768. var contours = [];
  14769. for (var i = 1; i < breaks.length; i++) {
  14770. var lowerBand = +breaks[i - 1]; // make sure the breaks value is a number
  14771. var upperBand = +breaks[i];
  14772. var isobandsCoords = isoBands(matrix, lowerBand, upperBand - lowerBand);
  14773. // as per GeoJson rules for creating a Polygon, make sure the first element
  14774. // in the array of LinearRings represents the exterior ring (i.e. biggest area),
  14775. // and any subsequent elements represent interior rings (i.e. smaller area);
  14776. // this avoids rendering issues of the MultiPolygons on the map
  14777. var nestedRings = orderByArea(isobandsCoords);
  14778. var groupedRings = groupNestedRings(nestedRings);
  14779. var obj = {};
  14780. obj['groupedRings'] = groupedRings;
  14781. obj[property] = lowerBand + '-' + upperBand;
  14782. contours.push(obj);
  14783. }
  14784. return contours;
  14785. }
  14786. /**
  14787. * Transform isobands of 2D grid to polygons for the map
  14788. *
  14789. * @private
  14790. * @param {Array<any>} contours Contours
  14791. * @param {Array<Array<number>>} matrix Grid Data
  14792. * @param {Object} points Points by Latitude
  14793. * @returns {Array<any>} contours
  14794. */
  14795. function rescaleContours(contours, matrix, points$$1) {
  14796. // get dimensions (on the map) of the original grid
  14797. var gridBbox = bbox(points$$1); // [ minX, minY, maxX, maxY ]
  14798. var originalWidth = gridBbox[2] - gridBbox[0];
  14799. var originalHeigth = gridBbox[3] - gridBbox[1];
  14800. // get origin, which is the first point of the last row on the rectangular data on the map
  14801. var x0 = gridBbox[0];
  14802. var y0 = gridBbox[1];
  14803. // get number of cells per side
  14804. var matrixWidth = matrix[0].length - 1;
  14805. var matrixHeight = matrix.length - 1;
  14806. // calculate the scaling factor between matrix and rectangular grid on the map
  14807. var scaleX = originalWidth / matrixWidth;
  14808. var scaleY = originalHeigth / matrixHeight;
  14809. var resize = function (point$$1) {
  14810. point$$1[0] = point$$1[0] * scaleX + x0;
  14811. point$$1[1] = point$$1[1] * scaleY + y0;
  14812. };
  14813. // resize and shift each point/line of the isobands
  14814. contours.forEach(function (contour) {
  14815. contour.groupedRings.forEach(function (lineRingSet) {
  14816. lineRingSet.forEach(function (lineRing) {
  14817. lineRing.forEach(resize);
  14818. });
  14819. });
  14820. });
  14821. return contours;
  14822. }
  14823. /* utility functions */
  14824. /**
  14825. * Returns an array of coordinates (of LinearRings) in descending order by area
  14826. *
  14827. * @private
  14828. * @param {Array<LineString>} ringsCoords array of closed LineString
  14829. * @returns {Array} array of the input LineString ordered by area
  14830. */
  14831. function orderByArea(ringsCoords) {
  14832. var ringsWithArea = [];
  14833. var areas = [];
  14834. ringsCoords.forEach(function (coords) {
  14835. // var poly = polygon([points]);
  14836. var ringArea = area$1(polygon([coords]));
  14837. // create an array of areas value
  14838. areas.push(ringArea);
  14839. // associate each lineRing with its area
  14840. ringsWithArea.push({ring: coords, area: ringArea});
  14841. });
  14842. areas.sort(function (a, b) { // bigger --> smaller
  14843. return b - a;
  14844. });
  14845. // create a new array of linearRings coordinates ordered by their area
  14846. var orderedByArea = [];
  14847. areas.forEach(function (area$$1) {
  14848. for (var lr = 0; lr < ringsWithArea.length; lr++) {
  14849. if (ringsWithArea[lr].area === area$$1) {
  14850. orderedByArea.push(ringsWithArea[lr].ring);
  14851. ringsWithArea.splice(lr, 1);
  14852. break;
  14853. }
  14854. }
  14855. });
  14856. return orderedByArea;
  14857. }
  14858. /**
  14859. * Returns an array of arrays of coordinates, each representing
  14860. * a set of (coordinates of) nested LinearRings,
  14861. * i.e. the first ring contains all the others
  14862. *
  14863. * @private
  14864. * @param {Array} orderedLinearRings array of coordinates (of LinearRings) in descending order by area
  14865. * @returns {Array<Array>} Array of coordinates of nested LinearRings
  14866. */
  14867. function groupNestedRings(orderedLinearRings) {
  14868. // create a list of the (coordinates of) LinearRings
  14869. var lrList = orderedLinearRings.map(function (lr) {
  14870. return {lrCoordinates: lr, grouped: false};
  14871. });
  14872. var groupedLinearRingsCoords = [];
  14873. while (!allGrouped(lrList)) {
  14874. for (var i = 0; i < lrList.length; i++) {
  14875. if (!lrList[i].grouped) {
  14876. // create new group starting with the larger not already grouped ring
  14877. var group = [];
  14878. group.push(lrList[i].lrCoordinates);
  14879. lrList[i].grouped = true;
  14880. var outerMostPoly = polygon([lrList[i].lrCoordinates]);
  14881. // group all the rings contained by the outermost ring
  14882. for (var j = i + 1; j < lrList.length; j++) {
  14883. if (!lrList[j].grouped) {
  14884. var lrPoly = polygon([lrList[j].lrCoordinates]);
  14885. if (isInside(lrPoly, outerMostPoly)) {
  14886. group.push(lrList[j].lrCoordinates);
  14887. lrList[j].grouped = true;
  14888. }
  14889. }
  14890. }
  14891. // insert the new group
  14892. groupedLinearRingsCoords.push(group);
  14893. }
  14894. }
  14895. }
  14896. return groupedLinearRingsCoords;
  14897. }
  14898. /**
  14899. * @private
  14900. * @param {Polygon} testPolygon polygon of interest
  14901. * @param {Polygon} targetPolygon polygon you want to compare with
  14902. * @returns {boolean} true if test-Polygon is inside target-Polygon
  14903. */
  14904. function isInside(testPolygon, targetPolygon) {
  14905. var points$$1 = explode(testPolygon);
  14906. for (var i = 0; i < points$$1.features.length; i++) {
  14907. if (!booleanPointInPolygon(points$$1.features[i], targetPolygon)) {
  14908. return false;
  14909. }
  14910. }
  14911. return true;
  14912. }
  14913. /**
  14914. * @private
  14915. * @param {Array<Object>} list list of objects which might contain the 'group' attribute
  14916. * @returns {boolean} true if all the objects in the list are marked as grouped
  14917. */
  14918. function allGrouped(list) {
  14919. for (var i = 0; i < list.length; i++) {
  14920. if (list[i].grouped === false) {
  14921. return false;
  14922. }
  14923. }
  14924. return true;
  14925. }
  14926. /**
  14927. * Rotates any geojson Feature or Geometry of a specified angle, around its `centroid` or a given `pivot` point;
  14928. * all rotations follow the right-hand rule: https://en.wikipedia.org/wiki/Right-hand_rule
  14929. *
  14930. * @name transformRotate
  14931. * @param {GeoJSON} geojson object to be rotated
  14932. * @param {number} angle of rotation (along the vertical axis), from North in decimal degrees, negative clockwise
  14933. * @param {Object} [options={}] Optional parameters
  14934. * @param {Coord} [options.pivot='centroid'] point around which the rotation will be performed
  14935. * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
  14936. * @returns {GeoJSON} the rotated GeoJSON feature
  14937. * @example
  14938. * var poly = turf.polygon([[[0,29],[3.5,29],[2.5,32],[0,29]]]);
  14939. * var options = {pivot: [0, 25]};
  14940. * var rotatedPoly = turf.transformRotate(poly, 10, options);
  14941. *
  14942. * //addToMap
  14943. * var addToMap = [poly, rotatedPoly];
  14944. * rotatedPoly.properties = {stroke: '#F00', 'stroke-width': 4};
  14945. */
  14946. function transformRotate(geojson, angle, options) {
  14947. // Optional parameters
  14948. options = options || {};
  14949. if (!isObject(options)) throw new Error('options is invalid');
  14950. var pivot = options.pivot;
  14951. var mutate = options.mutate;
  14952. // Input validation
  14953. if (!geojson) throw new Error('geojson is required');
  14954. if (angle === undefined || angle === null || isNaN(angle)) throw new Error('angle is required');
  14955. // Shortcut no-rotation
  14956. if (angle === 0) return geojson;
  14957. // Use centroid of GeoJSON if pivot is not provided
  14958. if (!pivot) pivot = centroid(geojson);
  14959. // Clone geojson to avoid side effects
  14960. if (mutate === false || mutate === undefined) geojson = clone(geojson);
  14961. // Rotate each coordinate
  14962. coordEach(geojson, function (pointCoords) {
  14963. var initialAngle = rhumbBearing(pivot, pointCoords);
  14964. var finalAngle = initialAngle + angle;
  14965. var distance = rhumbDistance(pivot, pointCoords);
  14966. var newCoords = getCoords(rhumbDestination(pivot, distance, finalAngle));
  14967. pointCoords[0] = newCoords[0];
  14968. pointCoords[1] = newCoords[1];
  14969. });
  14970. return geojson;
  14971. }
  14972. /**
  14973. * Scale a GeoJSON from a given point by a factor of scaling (ex: factor=2 would make the GeoJSON 200% larger).
  14974. * If a FeatureCollection is provided, the origin point will be calculated based on each individual Feature.
  14975. *
  14976. * @name transformScale
  14977. * @param {GeoJSON} geojson GeoJSON to be scaled
  14978. * @param {number} factor of scaling, positive or negative values greater than 0
  14979. * @param {Object} [options={}] Optional parameters
  14980. * @param {string|Coord} [options.origin='centroid'] Point from which the scaling will occur (string options: sw/se/nw/ne/center/centroid)
  14981. * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
  14982. * @returns {GeoJSON} scaled GeoJSON
  14983. * @example
  14984. * var poly = turf.polygon([[[0,29],[3.5,29],[2.5,32],[0,29]]]);
  14985. * var scaledPoly = turf.transformScale(poly, 3);
  14986. *
  14987. * //addToMap
  14988. * var addToMap = [poly, scaledPoly];
  14989. * scaledPoly.properties = {stroke: '#F00', 'stroke-width': 4};
  14990. */
  14991. function transformScale(geojson, factor, options) {
  14992. // Optional parameters
  14993. options = options || {};
  14994. if (!isObject(options)) throw new Error('options is invalid');
  14995. var origin = options.origin;
  14996. var mutate = options.mutate;
  14997. // Input validation
  14998. if (!geojson) throw new Error('geojson required');
  14999. if (typeof factor !== 'number' || factor === 0) throw new Error('invalid factor');
  15000. var originIsPoint = Array.isArray(origin) || typeof origin === 'object';
  15001. // Clone geojson to avoid side effects
  15002. if (mutate !== true) geojson = clone(geojson);
  15003. // Scale each Feature separately
  15004. if (geojson.type === 'FeatureCollection' && !originIsPoint) {
  15005. featureEach(geojson, function (feature$$1, index) {
  15006. geojson.features[index] = scale(feature$$1, factor, origin);
  15007. });
  15008. return geojson;
  15009. }
  15010. // Scale Feature/Geometry
  15011. return scale(geojson, factor, origin);
  15012. }
  15013. /**
  15014. * Scale Feature/Geometry
  15015. *
  15016. * @private
  15017. * @param {Feature|Geometry} feature GeoJSON Feature/Geometry
  15018. * @param {number} factor of scaling, positive or negative values greater than 0
  15019. * @param {string|Coord} [origin="centroid"] Point from which the scaling will occur (string options: sw/se/nw/ne/center/centroid)
  15020. * @returns {Feature|Geometry} scaled GeoJSON Feature/Geometry
  15021. */
  15022. function scale(feature$$1, factor, origin) {
  15023. // Default params
  15024. var isPoint = getType(feature$$1) === 'Point';
  15025. origin = defineOrigin(feature$$1, origin);
  15026. // Shortcut no-scaling
  15027. if (factor === 1 || isPoint) return feature$$1;
  15028. // Scale each coordinate
  15029. coordEach(feature$$1, function (coord) {
  15030. var originalDistance = rhumbDistance(origin, coord);
  15031. var bearing = rhumbBearing(origin, coord);
  15032. var newDistance = originalDistance * factor;
  15033. var newCoord = getCoords(rhumbDestination(origin, newDistance, bearing));
  15034. coord[0] = newCoord[0];
  15035. coord[1] = newCoord[1];
  15036. if (coord.length === 3) coord[2] *= factor;
  15037. });
  15038. return feature$$1;
  15039. }
  15040. /**
  15041. * Define Origin
  15042. *
  15043. * @private
  15044. * @param {GeoJSON} geojson GeoJSON
  15045. * @param {string|Coord} origin sw/se/nw/ne/center/centroid
  15046. * @returns {Feature<Point>} Point origin
  15047. */
  15048. function defineOrigin(geojson, origin) {
  15049. // Default params
  15050. if (origin === undefined || origin === null) origin = 'centroid';
  15051. // Input Coord
  15052. if (Array.isArray(origin) || typeof origin === 'object') return getCoord(origin);
  15053. // Define BBox
  15054. var bbox$$1 = (geojson.bbox) ? geojson.bbox : bbox(geojson);
  15055. var west = bbox$$1[0];
  15056. var south = bbox$$1[1];
  15057. var east = bbox$$1[2];
  15058. var north = bbox$$1[3];
  15059. switch (origin) {
  15060. case 'sw':
  15061. case 'southwest':
  15062. case 'westsouth':
  15063. case 'bottomleft':
  15064. return point([west, south]);
  15065. case 'se':
  15066. case 'southeast':
  15067. case 'eastsouth':
  15068. case 'bottomright':
  15069. return point([east, south]);
  15070. case 'nw':
  15071. case 'northwest':
  15072. case 'westnorth':
  15073. case 'topleft':
  15074. return point([west, north]);
  15075. case 'ne':
  15076. case 'northeast':
  15077. case 'eastnorth':
  15078. case 'topright':
  15079. return point([east, north]);
  15080. case 'center':
  15081. return center(geojson);
  15082. case undefined:
  15083. case null:
  15084. case 'centroid':
  15085. return centroid(geojson);
  15086. default:
  15087. throw new Error('invalid origin');
  15088. }
  15089. }
  15090. /**
  15091. * Moves any geojson Feature or Geometry of a specified distance along a Rhumb Line
  15092. * on the provided direction angle.
  15093. *
  15094. * @name transformTranslate
  15095. * @param {GeoJSON} geojson object to be translated
  15096. * @param {number} distance length of the motion; negative values determine motion in opposite direction
  15097. * @param {number} direction of the motion; angle from North in decimal degrees, positive clockwise
  15098. * @param {Object} [options={}] Optional parameters
  15099. * @param {string} [options.units='kilometers'] in which `distance` will be express; miles, kilometers, degrees, or radians
  15100. * @param {number} [options.zTranslation=0] length of the vertical motion, same unit of distance
  15101. * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
  15102. * @returns {GeoJSON} the translated GeoJSON object
  15103. * @example
  15104. * var poly = turf.polygon([[[0,29],[3.5,29],[2.5,32],[0,29]]]);
  15105. * var translatedPoly = turf.transformTranslate(poly, 100, 35);
  15106. *
  15107. * //addToMap
  15108. * var addToMap = [poly, translatedPoly];
  15109. * translatedPoly.properties = {stroke: '#F00', 'stroke-width': 4};
  15110. */
  15111. function transformTranslate(geojson, distance, direction, options) {
  15112. // Optional parameters
  15113. options = options || {};
  15114. if (!isObject(options)) throw new Error('options is invalid');
  15115. var units = options.units;
  15116. var zTranslation = options.zTranslation;
  15117. var mutate = options.mutate;
  15118. // Input validation
  15119. if (!geojson) throw new Error('geojson is required');
  15120. if (distance === undefined || distance === null || isNaN(distance)) throw new Error('distance is required');
  15121. if (zTranslation && typeof zTranslation !== 'number' && isNaN(zTranslation)) throw new Error('zTranslation is not a number');
  15122. // Shortcut no-motion
  15123. zTranslation = (zTranslation !== undefined) ? zTranslation : 0;
  15124. if (distance === 0 && zTranslation === 0) return geojson;
  15125. if (direction === undefined || direction === null || isNaN(direction)) throw new Error('direction is required');
  15126. // Invert with negative distances
  15127. if (distance < 0) {
  15128. distance = -distance;
  15129. direction = -direction;
  15130. }
  15131. // Clone geojson to avoid side effects
  15132. if (mutate === false || mutate === undefined) geojson = clone(geojson);
  15133. // Translate each coordinate
  15134. coordEach(geojson, function (pointCoords) {
  15135. var newCoords = getCoords(rhumbDestination(pointCoords, distance, direction, {units: units}));
  15136. pointCoords[0] = newCoords[0];
  15137. pointCoords[1] = newCoords[1];
  15138. if (zTranslation && pointCoords.length === 3) pointCoords[2] += zTranslation;
  15139. });
  15140. return geojson;
  15141. }
  15142. /**
  15143. * https://github.com/rook2pawn/node-intersection
  15144. *
  15145. * Author @rook2pawn
  15146. */
  15147. /**
  15148. * AB
  15149. *
  15150. * @private
  15151. * @param {Array<Array<number>>} segment - 2 vertex line segment
  15152. * @returns {Array<number>} coordinates [x, y]
  15153. */
  15154. function ab(segment) {
  15155. var start = segment[0];
  15156. var end = segment[1];
  15157. return [end[0] - start[0], end[1] - start[1]];
  15158. }
  15159. /**
  15160. * Cross Product
  15161. *
  15162. * @private
  15163. * @param {Array<number>} v1 coordinates [x, y]
  15164. * @param {Array<number>} v2 coordinates [x, y]
  15165. * @returns {Array<number>} Cross Product
  15166. */
  15167. function crossProduct(v1, v2) {
  15168. return (v1[0] * v2[1]) - (v2[0] * v1[1]);
  15169. }
  15170. /**
  15171. * Add
  15172. *
  15173. * @private
  15174. * @param {Array<number>} v1 coordinates [x, y]
  15175. * @param {Array<number>} v2 coordinates [x, y]
  15176. * @returns {Array<number>} Add
  15177. */
  15178. function add(v1, v2) {
  15179. return [v1[0] + v2[0], v1[1] + v2[1]];
  15180. }
  15181. /**
  15182. * Sub
  15183. *
  15184. * @private
  15185. * @param {Array<number>} v1 coordinates [x, y]
  15186. * @param {Array<number>} v2 coordinates [x, y]
  15187. * @returns {Array<number>} Sub
  15188. */
  15189. function sub(v1, v2) {
  15190. return [v1[0] - v2[0], v1[1] - v2[1]];
  15191. }
  15192. /**
  15193. * scalarMult
  15194. *
  15195. * @private
  15196. * @param {number} s scalar
  15197. * @param {Array<number>} v coordinates [x, y]
  15198. * @returns {Array<number>} scalarMult
  15199. */
  15200. function scalarMult(s, v) {
  15201. return [s * v[0], s * v[1]];
  15202. }
  15203. /**
  15204. * Intersect Segments
  15205. *
  15206. * @private
  15207. * @param {Array<number>} a coordinates [x, y]
  15208. * @param {Array<number>} b coordinates [x, y]
  15209. * @returns {Array<number>} intersection
  15210. */
  15211. function intersectSegments(a, b) {
  15212. var p = a[0];
  15213. var r = ab(a);
  15214. var q = b[0];
  15215. var s = ab(b);
  15216. var cross = crossProduct(r, s);
  15217. var qmp = sub(q, p);
  15218. var numerator = crossProduct(qmp, s);
  15219. var t = numerator / cross;
  15220. var intersection = add(p, scalarMult(t, r));
  15221. return intersection;
  15222. }
  15223. /**
  15224. * Is Parallel
  15225. *
  15226. * @private
  15227. * @param {Array<number>} a coordinates [x, y]
  15228. * @param {Array<number>} b coordinates [x, y]
  15229. * @returns {boolean} true if a and b are parallel (or co-linear)
  15230. */
  15231. function isParallel(a, b) {
  15232. var r = ab(a);
  15233. var s = ab(b);
  15234. return (crossProduct(r, s) === 0);
  15235. }
  15236. /**
  15237. * Intersection
  15238. *
  15239. * @private
  15240. * @param {Array<number>} a coordinates [x, y]
  15241. * @param {Array<number>} b coordinates [x, y]
  15242. * @returns {Array<number>|boolean} true if a and b are parallel (or co-linear)
  15243. */
  15244. function intersection(a, b) {
  15245. if (isParallel(a, b)) return false;
  15246. return intersectSegments(a, b);
  15247. }
  15248. /**
  15249. * Takes a {@link LineString|line} and returns a {@link LineString|line} at offset by the specified distance.
  15250. *
  15251. * @name lineOffset
  15252. * @param {Geometry|Feature<LineString|MultiLineString>} geojson input GeoJSON
  15253. * @param {number} distance distance to offset the line (can be of negative value)
  15254. * @param {Object} [options={}] Optional parameters
  15255. * @param {string} [options.units='kilometers'] can be degrees, radians, miles, kilometers, inches, yards, meters
  15256. * @returns {Feature<LineString|MultiLineString>} Line offset from the input line
  15257. * @example
  15258. * var line = turf.lineString([[-83, 30], [-84, 36], [-78, 41]], { "stroke": "#F00" });
  15259. *
  15260. * var offsetLine = turf.lineOffset(line, 2, {units: 'miles'});
  15261. *
  15262. * //addToMap
  15263. * var addToMap = [offsetLine, line]
  15264. * offsetLine.properties.stroke = "#00F"
  15265. */
  15266. function lineOffset(geojson, distance, options) {
  15267. // Optional parameters
  15268. options = options || {};
  15269. if (!isObject(options)) throw new Error('options is invalid');
  15270. var units = options.units;
  15271. // Valdiation
  15272. if (!geojson) throw new Error('geojson is required');
  15273. if (distance === undefined || distance === null || isNaN(distance)) throw new Error('distance is required');
  15274. var type = getType(geojson);
  15275. var properties = geojson.properties;
  15276. switch (type) {
  15277. case 'LineString':
  15278. return lineOffsetFeature(geojson, distance, units);
  15279. case 'MultiLineString':
  15280. var coords = [];
  15281. flattenEach(geojson, function (feature$$1) {
  15282. coords.push(lineOffsetFeature(feature$$1, distance, units).geometry.coordinates);
  15283. });
  15284. return multiLineString(coords, properties);
  15285. default:
  15286. throw new Error('geometry ' + type + ' is not supported');
  15287. }
  15288. }
  15289. /**
  15290. * Line Offset
  15291. *
  15292. * @private
  15293. * @param {Geometry|Feature<LineString>} line input line
  15294. * @param {number} distance distance to offset the line (can be of negative value)
  15295. * @param {string} [units=kilometers] units
  15296. * @returns {Feature<LineString>} Line offset from the input line
  15297. */
  15298. function lineOffsetFeature(line, distance, units) {
  15299. var segments = [];
  15300. var offsetDegrees = lengthToDegrees(distance, units);
  15301. var coords = getCoords(line);
  15302. var finalCoords = [];
  15303. coords.forEach(function (currentCoords, index) {
  15304. if (index !== coords.length - 1) {
  15305. var segment = processSegment(currentCoords, coords[index + 1], offsetDegrees);
  15306. segments.push(segment);
  15307. if (index > 0) {
  15308. var seg2Coords = segments[index - 1];
  15309. var intersects = intersection(segment, seg2Coords);
  15310. // Handling for line segments that aren't straight
  15311. if (intersects !== false) {
  15312. seg2Coords[1] = intersects;
  15313. segment[0] = intersects;
  15314. }
  15315. finalCoords.push(seg2Coords[0]);
  15316. if (index === coords.length - 2) {
  15317. finalCoords.push(segment[0]);
  15318. finalCoords.push(segment[1]);
  15319. }
  15320. }
  15321. // Handling for lines that only have 1 segment
  15322. if (coords.length === 2) {
  15323. finalCoords.push(segment[0]);
  15324. finalCoords.push(segment[1]);
  15325. }
  15326. }
  15327. });
  15328. return lineString(finalCoords, line.properties);
  15329. }
  15330. /**
  15331. * Process Segment
  15332. * Inspiration taken from http://stackoverflow.com/questions/2825412/draw-a-parallel-line
  15333. *
  15334. * @private
  15335. * @param {Array<number>} point1 Point coordinates
  15336. * @param {Array<number>} point2 Point coordinates
  15337. * @param {number} offset Offset
  15338. * @returns {Array<Array<number>>} offset points
  15339. */
  15340. function processSegment(point1, point2, offset) {
  15341. var L = Math.sqrt((point1[0] - point2[0]) * (point1[0] - point2[0]) + (point1[1] - point2[1]) * (point1[1] - point2[1]));
  15342. var out1x = point1[0] + offset * (point2[1] - point1[1]) / L;
  15343. var out2x = point2[0] + offset * (point2[1] - point1[1]) / L;
  15344. var out1y = point1[1] + offset * (point1[0] - point2[0]) / L;
  15345. var out2y = point2[1] + offset * (point1[0] - point2[0]) / L;
  15346. return [[out1x, out1y], [out2x, out2y]];
  15347. }
  15348. /**
  15349. * Returns the direction of the point q relative to the vector p1 -> p2.
  15350. *
  15351. * Implementation of geos::algorithm::CGAlgorithm::orientationIndex()
  15352. * (same as geos::algorithm::CGAlgorithm::computeOrientation())
  15353. *
  15354. * @param {number[]} p1 - the origin point of the vector
  15355. * @param {number[]} p2 - the final point of the vector
  15356. * @param {number[]} q - the point to compute the direction to
  15357. *
  15358. * @returns {number} - 1 if q is ccw (left) from p1->p2,
  15359. * -1 if q is cw (right) from p1->p2,
  15360. * 0 if q is colinear with p1->p2
  15361. */
  15362. function orientationIndex(p1, p2, q) {
  15363. var dx1 = p2[0] - p1[0],
  15364. dy1 = p2[1] - p1[1],
  15365. dx2 = q[0] - p2[0],
  15366. dy2 = q[1] - p2[1];
  15367. return Math.sign(dx1 * dy2 - dx2 * dy1);
  15368. }
  15369. /**
  15370. * Checks if two envelopes are equal.
  15371. *
  15372. * The function assumes that the arguments are envelopes, i.e.: Rectangular polygon
  15373. *
  15374. * @param {Feature<Polygon>} env1 - Envelope
  15375. * @param {Feature<Polygon>} env2 - Envelope
  15376. * @returns {boolean} - True if the envelopes are equal
  15377. */
  15378. function envelopeIsEqual(env1, env2) {
  15379. var envX1 = env1.geometry.coordinates.map(function (c) { return c[0]; }),
  15380. envY1 = env1.geometry.coordinates.map(function (c) { return c[1]; }),
  15381. envX2 = env2.geometry.coordinates.map(function (c) { return c[0]; }),
  15382. envY2 = env2.geometry.coordinates.map(function (c) { return c[1]; });
  15383. return Math.max(null, envX1) === Math.max(null, envX2) &&
  15384. Math.max(null, envY1) === Math.max(null, envY2) &&
  15385. Math.min(null, envX1) === Math.min(null, envX2) &&
  15386. Math.min(null, envY1) === Math.min(null, envY2);
  15387. }
  15388. /**
  15389. * Check if a envelope is contained in other one.
  15390. *
  15391. * The function assumes that the arguments are envelopes, i.e.: Convex polygon
  15392. * XXX: Envelopes are rectangular, checking if a point is inside a rectangule is something easy,
  15393. * this could be further improved.
  15394. *
  15395. * @param {Feature<Polygon>} self - Envelope
  15396. * @param {Feature<Polygon>} env - Envelope
  15397. * @returns {boolean} - True if env is contained in self
  15398. */
  15399. function envelopeContains(self, env) {
  15400. return env.geometry.coordinates[0].every(function (c) { return booleanPointInPolygon(point(c), self); });
  15401. }
  15402. /**
  15403. * Checks if two coordinates are equal.
  15404. *
  15405. * @param {number[]} coord1 - First coordinate
  15406. * @param {number[]} coord2 - Second coordinate
  15407. * @returns {boolean} - True if coordinates are equal
  15408. */
  15409. function coordinatesEqual(coord1, coord2) {
  15410. return coord1[0] === coord2[0] && coord1[1] === coord2[1];
  15411. }
  15412. /**
  15413. * Node
  15414. */
  15415. var Node$1 = function Node(coordinates) {
  15416. this.id = Node.buildId(coordinates);
  15417. this.coordinates = coordinates; //< {Number[]}
  15418. this.innerEdges = []; //< {Edge[]}
  15419. // We wil store to (out) edges in an CCW order as geos::planargraph::DirectedEdgeStar does
  15420. this.outerEdges = []; //< {Edge[]}
  15421. this.outerEdgesSorted = false; //< {Boolean} flag that stores if the outer Edges had been sorted
  15422. };
  15423. Node$1.buildId = function buildId (coordinates) {
  15424. return coordinates.join(',');
  15425. };
  15426. Node$1.prototype.removeInnerEdge = function removeInnerEdge (edge) {
  15427. this.innerEdges = this.innerEdges.filter(function (e) { return e.from.id !== edge.from.id; });
  15428. };
  15429. Node$1.prototype.removeOuterEdge = function removeOuterEdge (edge) {
  15430. this.outerEdges = this.outerEdges.filter(function (e) { return e.to.id !== edge.to.id; });
  15431. };
  15432. /**
  15433. * Outer edges are stored CCW order.
  15434. *
  15435. * @memberof Node
  15436. * @param {Edge} edge - Edge to add as an outerEdge.
  15437. */
  15438. Node$1.prototype.addOuterEdge = function addOuterEdge (edge) {
  15439. this.outerEdges.push(edge);
  15440. this.outerEdgesSorted = false;
  15441. };
  15442. /**
  15443. * Sorts outer edges in CCW way.
  15444. *
  15445. * @memberof Node
  15446. * @private
  15447. */
  15448. Node$1.prototype.sortOuterEdges = function sortOuterEdges () {
  15449. var this$1 = this;
  15450. if (!this.outerEdgesSorted) {
  15451. //this.outerEdges.sort((a, b) => a.compareTo(b));
  15452. // Using this comparator in order to be deterministic
  15453. this.outerEdges.sort(function (a, b) {
  15454. var aNode = a.to,
  15455. bNode = b.to;
  15456. if (aNode.coordinates[0] - this$1.coordinates[0] >= 0 && bNode.coordinates[0] - this$1.coordinates[0] < 0)
  15457. { return 1; }
  15458. if (aNode.coordinates[0] - this$1.coordinates[0] < 0 && bNode.coordinates[0] - this$1.coordinates[0] >= 0)
  15459. { return -1; }
  15460. if (aNode.coordinates[0] - this$1.coordinates[0] === 0 && bNode.coordinates[0] - this$1.coordinates[0] === 0) {
  15461. if (aNode.coordinates[1] - this$1.coordinates[1] >= 0 || bNode.coordinates[1] - this$1.coordinates[1] >= 0)
  15462. { return aNode.coordinates[1] - bNode.coordinates[1]; }
  15463. return bNode.coordinates[1] - aNode.coordinates[1];
  15464. }
  15465. var det = orientationIndex(this$1.coordinates, aNode.coordinates, bNode.coordinates);
  15466. if (det < 0)
  15467. { return 1; }
  15468. if (det > 0)
  15469. { return -1; }
  15470. var d1 = Math.pow(aNode.coordinates[0] - this$1.coordinates[0], 2) + Math.pow(aNode.coordinates[1] - this$1.coordinates[1], 2),
  15471. d2 = Math.pow(bNode.coordinates[0] - this$1.coordinates[0], 2) + Math.pow(bNode.coordinates[1] - this$1.coordinates[1], 2);
  15472. return d1 - d2;
  15473. });
  15474. this.outerEdgesSorted = true;
  15475. }
  15476. };
  15477. /**
  15478. * Retrieves outer edges.
  15479. *
  15480. * They are sorted if they aren't in the CCW order.
  15481. *
  15482. * @memberof Node
  15483. * @returns {Edge[]} - List of outer edges sorted in a CCW order.
  15484. */
  15485. Node$1.prototype.getOuterEdges = function getOuterEdges () {
  15486. this.sortOuterEdges();
  15487. return this.outerEdges;
  15488. };
  15489. Node$1.prototype.getOuterEdge = function getOuterEdge (i) {
  15490. this.sortOuterEdges();
  15491. return this.outerEdges[i];
  15492. };
  15493. Node$1.prototype.addInnerEdge = function addInnerEdge (edge) {
  15494. this.innerEdges.push(edge);
  15495. };
  15496. /**
  15497. * This class is inspired by GEOS's geos::operation::polygonize::PolygonizeDirectedEdge
  15498. */
  15499. var Edge = function Edge(from, to) {
  15500. this.from = from; //< start
  15501. this.to = to; //< End
  15502. this.next = undefined; //< The edge to be computed after
  15503. this.label = undefined; //< Used in order to detect Cut Edges (Bridges)
  15504. this.symetric = undefined; //< The symetric edge of this
  15505. this.ring = undefined; //< EdgeRing in which the Edge is
  15506. this.from.addOuterEdge(this);
  15507. this.to.addInnerEdge(this);
  15508. };
  15509. /**
  15510. * Removes edge from from and to nodes.
  15511. */
  15512. Edge.prototype.getSymetric = function getSymetric () {
  15513. if (!this.symetric) {
  15514. this.symetric = new Edge(this.to, this.from);
  15515. this.symetric.symetric = this;
  15516. }
  15517. return this.symetric;
  15518. };
  15519. Edge.prototype.deleteEdge = function deleteEdge () {
  15520. this.from.removeOuterEdge(this);
  15521. this.to.removeInnerEdge(this);
  15522. };
  15523. /**
  15524. * Compares Edge equallity.
  15525. *
  15526. * An edge is equal to another, if the from and to nodes are the same.
  15527. *
  15528. * @param {Edge} edge - Another Edge
  15529. * @returns {boolean} - True if Edges are equal, False otherwise
  15530. */
  15531. Edge.prototype.isEqual = function isEqual (edge) {
  15532. return this.from.id === edge.from.id && this.to.id === edge.to.id;
  15533. };
  15534. Edge.prototype.toString = function toString () {
  15535. return ("Edge { " + (this.from.id) + " -> " + (this.to.id) + " }");
  15536. };
  15537. /**
  15538. * Returns a LineString representation of the Edge
  15539. *
  15540. * @returns {Feature<LineString>} - LineString representation of the Edge
  15541. */
  15542. Edge.prototype.toLineString = function toLineString () {
  15543. return lineString([this.from.coordinates, this.to.coordinates]);
  15544. };
  15545. /**
  15546. * Comparator of two edges.
  15547. *
  15548. * Implementation of geos::planargraph::DirectedEdge::compareTo.
  15549. *
  15550. * @param {Edge} edge - Another edge to compare with this one
  15551. * @returns {number} -1 if this Edge has a greater angle with the positive x-axis than b,
  15552. * 0 if the Edges are colinear,
  15553. * 1 otherwise
  15554. */
  15555. Edge.prototype.compareTo = function compareTo (edge) {
  15556. return orientationIndex(edge.from.coordinates, edge.to.coordinates, this.to.coordinates);
  15557. };
  15558. /**
  15559. * Ring of edges which form a polygon.
  15560. *
  15561. * The ring may be either an outer shell or a hole.
  15562. *
  15563. * This class is inspired in GEOS's geos::operation::polygonize::EdgeRing
  15564. */
  15565. var EdgeRing = function EdgeRing() {
  15566. this.edges = [];
  15567. this.polygon = undefined; //< Caches Polygon representation
  15568. this.envelope = undefined; //< Caches Envelope representation
  15569. };
  15570. var prototypeAccessors = { length: { configurable: true } };
  15571. /**
  15572. * Add an edge to the ring, inserting it in the last position.
  15573. *
  15574. * @memberof EdgeRing
  15575. * @param {Edge} edge - Edge to be inserted
  15576. */
  15577. EdgeRing.prototype.push = function push (edge) {
  15578. // Emulate Array getter ([]) behaviour
  15579. this[this.edges.length] = edge;
  15580. this.edges.push(edge);
  15581. this.polygon = this.envelope = undefined;
  15582. };
  15583. /**
  15584. * Get Edge.
  15585. *
  15586. * @memberof EdgeRing
  15587. * @param {number} i - Index
  15588. * @returns {Edge} - Edge in the i position
  15589. */
  15590. EdgeRing.prototype.get = function get (i) {
  15591. return this.edges[i];
  15592. };
  15593. /**
  15594. * Getter of length property.
  15595. *
  15596. * @memberof EdgeRing
  15597. * @returns {number} - Length of the edge ring.
  15598. */
  15599. prototypeAccessors.length.get = function () {
  15600. return this.edges.length;
  15601. };
  15602. /**
  15603. * Similar to Array.prototype.forEach for the list of Edges in the EdgeRing.
  15604. *
  15605. * @memberof EdgeRing
  15606. * @param {Function} f - The same function to be passed to Array.prototype.forEach
  15607. */
  15608. EdgeRing.prototype.forEach = function forEach (f) {
  15609. this.edges.forEach(f);
  15610. };
  15611. /**
  15612. * Similar to Array.prototype.map for the list of Edges in the EdgeRing.
  15613. *
  15614. * @memberof EdgeRing
  15615. * @param {Function} f - The same function to be passed to Array.prototype.map
  15616. * @returns {Array} - The mapped values in the function
  15617. */
  15618. EdgeRing.prototype.map = function map (f) {
  15619. return this.edges.map(f);
  15620. };
  15621. /**
  15622. * Similar to Array.prototype.some for the list of Edges in the EdgeRing.
  15623. *
  15624. * @memberof EdgeRing
  15625. * @param {Function} f - The same function to be passed to Array.prototype.some
  15626. * @returns {boolean} - True if an Edge check the condition
  15627. */
  15628. EdgeRing.prototype.some = function some (f) {
  15629. return this.edges.some(f);
  15630. };
  15631. /**
  15632. * Check if the ring is valid in geomtry terms.
  15633. *
  15634. * A ring must have either 0 or 4 or more points. The first and the last must be
  15635. * equal (in 2D)
  15636. * geos::geom::LinearRing::validateConstruction
  15637. *
  15638. * @memberof EdgeRing
  15639. * @returns {boolean} - Validity of the EdgeRing
  15640. */
  15641. EdgeRing.prototype.isValid = function isValid () {
  15642. // TODO: stub
  15643. return true;
  15644. };
  15645. /**
  15646. * Tests whether this ring is a hole.
  15647. *
  15648. * A ring is a hole if it is oriented counter-clockwise.
  15649. * Similar implementation of geos::algorithm::CGAlgorithms::isCCW
  15650. *
  15651. * @memberof EdgeRing
  15652. * @returns {boolean} - true: if it is a hole
  15653. */
  15654. EdgeRing.prototype.isHole = function isHole () {
  15655. var this$1 = this;
  15656. // XXX: Assuming Ring is valid
  15657. // Find highest point
  15658. var hiIndex = this.edges.reduce(function (high, edge, i) {
  15659. if (edge.from.coordinates[1] > this$1.edges[high].from.coordinates[1])
  15660. { high = i; }
  15661. return high;
  15662. }, 0),
  15663. iPrev = (hiIndex === 0 ? this.length : hiIndex) - 1,
  15664. iNext = (hiIndex + 1) % this.length,
  15665. disc = orientationIndex(this.edges[iPrev].from.coordinates, this.edges[hiIndex].from.coordinates, this.edges[iNext].from.coordinates);
  15666. if (disc === 0)
  15667. { return this.edges[iPrev].from.coordinates[0] > this.edges[iNext].from.coordinates[0]; }
  15668. return disc > 0;
  15669. };
  15670. /**
  15671. * Creates a MultiPoint representing the EdgeRing (discarts edges directions).
  15672. *
  15673. * @memberof EdgeRing
  15674. * @returns {Feature<MultiPoint>} - Multipoint representation of the EdgeRing
  15675. */
  15676. EdgeRing.prototype.toMultiPoint = function toMultiPoint () {
  15677. return multiPoint(this.edges.map(function (edge) { return edge.from.coordinates; }));
  15678. };
  15679. /**
  15680. * Creates a Polygon representing the EdgeRing.
  15681. *
  15682. * @memberof EdgeRing
  15683. * @returns {Feature<Polygon>} - Polygon representation of the Edge Ring
  15684. */
  15685. EdgeRing.prototype.toPolygon = function toPolygon () {
  15686. if (this.polygon)
  15687. { return this.polygon; }
  15688. var coordinates = this.edges.map(function (edge) { return edge.from.coordinates; });
  15689. coordinates.push(this.edges[0].from.coordinates);
  15690. return (this.polygon = polygon([coordinates]));
  15691. };
  15692. /**
  15693. * Calculates the envelope of the EdgeRing.
  15694. *
  15695. * @memberof EdgeRing
  15696. * @returns {Feature<Polygon>} - envelope
  15697. */
  15698. EdgeRing.prototype.getEnvelope = function getEnvelope () {
  15699. if (this.envelope)
  15700. { return this.envelope; }
  15701. return (this.envelope = envelope(this.toPolygon()));
  15702. };
  15703. /**
  15704. * `geos::operation::polygonize::EdgeRing::findEdgeRingContaining`
  15705. *
  15706. * @param {EdgeRing} testEdgeRing - EdgeRing to look in the list
  15707. * @param {EdgeRing[]} shellList - List of EdgeRing in which to search
  15708. *
  15709. * @returns {EdgeRing} - EdgeRing which contains the testEdgeRing
  15710. */
  15711. EdgeRing.findEdgeRingContaining = function findEdgeRingContaining (testEdgeRing, shellList) {
  15712. var testEnvelope = testEdgeRing.getEnvelope();
  15713. var minEnvelope,
  15714. minShell;
  15715. shellList.forEach(function (shell) {
  15716. var tryEnvelope = shell.getEnvelope();
  15717. if (minShell)
  15718. { minEnvelope = minShell.getEnvelope(); }
  15719. // the hole envelope cannot equal the shell envelope
  15720. if (envelopeIsEqual(tryEnvelope, testEnvelope))
  15721. { return; }
  15722. if (envelopeContains(tryEnvelope, testEnvelope)) {
  15723. var testPoint = testEdgeRing.map(function (edge) { return edge.from.coordinates; })
  15724. .find(function (pt) { return !shell.some(function (edge) { return coordinatesEqual(pt, edge.from.coordinates); }); });
  15725. if (testPoint && shell.inside(point(testPoint))) {
  15726. if (!minShell || envelopeContains(minEnvelope, tryEnvelope))
  15727. { minShell = shell; }
  15728. }
  15729. }
  15730. });
  15731. return minShell;
  15732. };
  15733. /**
  15734. * Checks if the point is inside the edgeRing
  15735. *
  15736. * @param {Feature<Point>} pt - Point to check if it is inside the edgeRing
  15737. * @returns {boolean} - True if it is inside, False otherwise
  15738. */
  15739. EdgeRing.prototype.inside = function inside (pt) {
  15740. return booleanPointInPolygon(pt, this.toPolygon());
  15741. };
  15742. Object.defineProperties( EdgeRing.prototype, prototypeAccessors );
  15743. /**
  15744. * Validates the geoJson.
  15745. *
  15746. * @param {GeoJSON} geoJson - input geoJson.
  15747. * @throws {Error} if geoJson is invalid.
  15748. */
  15749. function validateGeoJson(geoJson) {
  15750. if (!geoJson)
  15751. { throw new Error('No geojson passed'); }
  15752. if (geoJson.type !== 'FeatureCollection' &&
  15753. geoJson.type !== 'GeometryCollection' &&
  15754. geoJson.type !== 'MultiLineString' &&
  15755. geoJson.type !== 'LineString' &&
  15756. geoJson.type !== 'Feature'
  15757. )
  15758. { throw new Error(("Invalid input type '" + (geoJson.type) + "'. Geojson must be FeatureCollection, GeometryCollection, LineString, MultiLineString or Feature")); }
  15759. }
  15760. /**
  15761. * Represents a planar graph of edges and nodes that can be used to compute a polygonization.
  15762. *
  15763. * Although, this class is inspired by GEOS's `geos::operation::polygonize::PolygonizeGraph`,
  15764. * it isn't a rewrite. As regards algorithm, this class implements the same logic, but it
  15765. * isn't a javascript transcription of the C++ source.
  15766. *
  15767. * This graph is directed (both directions are created)
  15768. */
  15769. var Graph = function Graph() {
  15770. this.edges = []; //< {Edge[]} dirEdges
  15771. // The key is the `id` of the Node (ie: coordinates.join(','))
  15772. this.nodes = {};
  15773. };
  15774. /**
  15775. * Removes Dangle Nodes (nodes with grade 1).
  15776. */
  15777. Graph.fromGeoJson = function fromGeoJson (geoJson) {
  15778. validateGeoJson(geoJson);
  15779. var graph = new Graph();
  15780. flattenEach(geoJson, function (feature$$1) {
  15781. featureOf(feature$$1, 'LineString', 'Graph::fromGeoJson');
  15782. // When a LineString if formed by many segments, split them
  15783. coordReduce(feature$$1, function (prev, cur) {
  15784. if (prev) {
  15785. var start = graph.getNode(prev),
  15786. end = graph.getNode(cur);
  15787. graph.addEdge(start, end);
  15788. }
  15789. return cur;
  15790. });
  15791. });
  15792. return graph;
  15793. };
  15794. /**
  15795. * Creates or get a Node.
  15796. *
  15797. * @param {number[]} coordinates - Coordinates of the node
  15798. * @returns {Node} - The created or stored node
  15799. */
  15800. Graph.prototype.getNode = function getNode (coordinates) {
  15801. var id = Node$1.buildId(coordinates);
  15802. var node = this.nodes[id];
  15803. if (!node)
  15804. { node = this.nodes[id] = new Node$1(coordinates); }
  15805. return node;
  15806. };
  15807. /**
  15808. * Adds an Edge and its symetricall.
  15809. *
  15810. * Edges are added symetrically, i.e.: we also add its symetric
  15811. *
  15812. * @param {Node} from - Node which starts the Edge
  15813. * @param {Node} to - Node which ends the Edge
  15814. */
  15815. Graph.prototype.addEdge = function addEdge (from, to) {
  15816. var edge = new Edge(from, to),
  15817. symetricEdge = edge.getSymetric();
  15818. this.edges.push(edge);
  15819. this.edges.push(symetricEdge);
  15820. };
  15821. Graph.prototype.deleteDangles = function deleteDangles () {
  15822. var this$1 = this;
  15823. Object.keys(this.nodes)
  15824. .map(function (id) { return this$1.nodes[id]; })
  15825. .forEach(function (node) { return this$1._removeIfDangle(node); });
  15826. };
  15827. /**
  15828. * Check if node is dangle, if so, remove it.
  15829. *
  15830. * It calls itself recursively, removing a dangling node might cause another dangling node
  15831. *
  15832. * @param {Node} node - Node to check if it's a dangle
  15833. */
  15834. Graph.prototype._removeIfDangle = function _removeIfDangle (node) {
  15835. var this$1 = this;
  15836. // As edges are directed and symetrical, we count only innerEdges
  15837. if (node.innerEdges.length <= 1) {
  15838. var outerNodes = node.getOuterEdges().map(function (e) { return e.to; });
  15839. this.removeNode(node);
  15840. outerNodes.forEach(function (n) { return this$1._removeIfDangle(n); });
  15841. }
  15842. };
  15843. /**
  15844. * Delete cut-edges (bridge edges).
  15845. *
  15846. * The graph will be traversed, all the edges will be labeled according the ring
  15847. * in which they are. (The label is a number incremented by 1). Edges with the same
  15848. * label are cut-edges.
  15849. */
  15850. Graph.prototype.deleteCutEdges = function deleteCutEdges () {
  15851. var this$1 = this;
  15852. this._computeNextCWEdges();
  15853. this._findLabeledEdgeRings();
  15854. // Cut-edges (bridges) are edges where both edges have the same label
  15855. this.edges.forEach(function (edge) {
  15856. if (edge.label === edge.symetric.label) {
  15857. this$1.removeEdge(edge.symetric);
  15858. this$1.removeEdge(edge);
  15859. }
  15860. });
  15861. };
  15862. /**
  15863. * Set the `next` property of each Edge.
  15864. *
  15865. * The graph will be transversed in a CW form, so, we set the next of the symetrical edge as the previous one.
  15866. * OuterEdges are sorted CCW.
  15867. *
  15868. * @param {Node} [node] - If no node is passed, the function calls itself for every node in the Graph
  15869. */
  15870. Graph.prototype._computeNextCWEdges = function _computeNextCWEdges (node) {
  15871. var this$1 = this;
  15872. if (typeof node === 'undefined') {
  15873. Object.keys(this.nodes)
  15874. .forEach(function (id) { return this$1._computeNextCWEdges(this$1.nodes[id]); });
  15875. } else {
  15876. node.getOuterEdges().forEach(function (edge, i) {
  15877. node.getOuterEdge((i === 0 ? node.getOuterEdges().length : i) - 1).symetric.next = edge;
  15878. });
  15879. }
  15880. };
  15881. /**
  15882. * Computes the next edge pointers going CCW around the given node, for the given edgering label.
  15883. *
  15884. * This algorithm has the effect of converting maximal edgerings into minimal edgerings
  15885. *
  15886. * XXX: method literally transcribed from `geos::operation::polygonize::PolygonizeGraph::computeNextCCWEdges`,
  15887. * could be written in a more javascript way.
  15888. *
  15889. * @param {Node} node - Node
  15890. * @param {number} label - Ring's label
  15891. */
  15892. Graph.prototype._computeNextCCWEdges = function _computeNextCCWEdges (node, label) {
  15893. var edges = node.getOuterEdges();
  15894. var firstOutDE,
  15895. prevInDE;
  15896. for (var i = edges.length - 1; i >= 0; --i) {
  15897. var de = edges[i],
  15898. sym = de.symetric,
  15899. outDE = (void 0),
  15900. inDE = (void 0);
  15901. if (de.label === label)
  15902. { outDE = de; }
  15903. if (sym.label === label)
  15904. { inDE = sym; }
  15905. if (!outDE || !inDE) // This edge is not in edgering
  15906. { continue; }
  15907. if (inDE)
  15908. { prevInDE = inDE; }
  15909. if (outDE) {
  15910. if (prevInDE) {
  15911. prevInDE.next = outDE;
  15912. prevInDE = undefined;
  15913. }
  15914. if (!firstOutDE)
  15915. { firstOutDE = outDE; }
  15916. }
  15917. }
  15918. if (prevInDE)
  15919. { prevInDE.next = firstOutDE; }
  15920. };
  15921. /**
  15922. * Finds rings and labels edges according to which rings are.
  15923. *
  15924. * The label is a number which is increased for each ring.
  15925. *
  15926. * @returns {Edge[]} edges that start rings
  15927. */
  15928. Graph.prototype._findLabeledEdgeRings = function _findLabeledEdgeRings () {
  15929. var edgeRingStarts = [];
  15930. var label = 0;
  15931. this.edges.forEach(function (edge) {
  15932. if (edge.label >= 0)
  15933. { return; }
  15934. edgeRingStarts.push(edge);
  15935. var e = edge;
  15936. do {
  15937. e.label = label;
  15938. e = e.next;
  15939. } while (!edge.isEqual(e));
  15940. label++;
  15941. });
  15942. return edgeRingStarts;
  15943. };
  15944. /**
  15945. * Computes the EdgeRings formed by the edges in this graph.
  15946. *
  15947. * @returns {EdgeRing[]} - A list of all the EdgeRings in the graph.
  15948. */
  15949. Graph.prototype.getEdgeRings = function getEdgeRings () {
  15950. var this$1 = this;
  15951. this._computeNextCWEdges();
  15952. // Clear labels
  15953. this.edges.forEach(function (edge) {
  15954. edge.label = undefined;
  15955. });
  15956. this._findLabeledEdgeRings().forEach(function (edge) {
  15957. // convertMaximalToMinimalEdgeRings
  15958. this$1._findIntersectionNodes(edge).forEach(function (node) {
  15959. this$1._computeNextCCWEdges(node, edge.label);
  15960. });
  15961. });
  15962. var edgeRingList = [];
  15963. // find all edgerings
  15964. this.edges.forEach(function (edge) {
  15965. if (edge.ring)
  15966. { return; }
  15967. edgeRingList.push(this$1._findEdgeRing(edge));
  15968. });
  15969. return edgeRingList;
  15970. };
  15971. /**
  15972. * Find all nodes in a Maxima EdgeRing which are self-intersection nodes.
  15973. *
  15974. * @param {Node} startEdge - Start Edge of the Ring
  15975. * @returns {Node[]} - intersection nodes
  15976. */
  15977. Graph.prototype._findIntersectionNodes = function _findIntersectionNodes (startEdge) {
  15978. var intersectionNodes = [];
  15979. var edge = startEdge;
  15980. var loop = function () {
  15981. // getDegree
  15982. var degree = 0;
  15983. edge.from.getOuterEdges().forEach(function (e) {
  15984. if (e.label === startEdge.label)
  15985. { ++degree; }
  15986. });
  15987. if (degree > 1)
  15988. { intersectionNodes.push(edge.from); }
  15989. edge = edge.next;
  15990. };
  15991. do {
  15992. loop();
  15993. } while (!startEdge.isEqual(edge));
  15994. return intersectionNodes;
  15995. };
  15996. /**
  15997. * Get the edge-ring which starts from the provided Edge.
  15998. *
  15999. * @param {Edge} startEdge - starting edge of the edge ring
  16000. * @returns {EdgeRing} - EdgeRing which start Edge is the provided one.
  16001. */
  16002. Graph.prototype._findEdgeRing = function _findEdgeRing (startEdge) {
  16003. var edge = startEdge;
  16004. var edgeRing = new EdgeRing();
  16005. do {
  16006. edgeRing.push(edge);
  16007. edge.ring = edgeRing;
  16008. edge = edge.next;
  16009. } while (!startEdge.isEqual(edge));
  16010. return edgeRing;
  16011. };
  16012. /**
  16013. * Removes a node from the Graph.
  16014. *
  16015. * It also removes edges asociated to that node
  16016. * @param {Node} node - Node to be removed
  16017. */
  16018. Graph.prototype.removeNode = function removeNode (node) {
  16019. var this$1 = this;
  16020. node.getOuterEdges().forEach(function (edge) { return this$1.removeEdge(edge); });
  16021. node.innerEdges.forEach(function (edge) { return this$1.removeEdge(edge); });
  16022. delete this.nodes[node.id];
  16023. };
  16024. /**
  16025. * Remove edge from the graph and deletes the edge.
  16026. *
  16027. * @param {Edge} edge - Edge to be removed
  16028. */
  16029. Graph.prototype.removeEdge = function removeEdge (edge) {
  16030. this.edges = this.edges.filter(function (e) { return !e.isEqual(edge); });
  16031. edge.deleteEdge();
  16032. };
  16033. /**
  16034. * Polygonizes {@link LineString|(Multi)LineString(s)} into {@link Polygons}.
  16035. *
  16036. * Implementation of GEOSPolygonize function (`geos::operation::polygonize::Polygonizer`).
  16037. *
  16038. * Polygonizes a set of lines that represents edges in a planar graph. Edges must be correctly
  16039. * noded, i.e., they must only meet at their endpoints.
  16040. *
  16041. * The implementation correctly handles:
  16042. *
  16043. * - Dangles: edges which have one or both ends which are not incident on another edge endpoint.
  16044. * - Cut Edges (bridges): edges that are connected at both ends but which do not form part of a polygon.
  16045. *
  16046. * @name polygonize
  16047. * @param {FeatureCollection|Geometry|Feature<LineString|MultiLineString>} geoJson Lines in order to polygonize
  16048. * @returns {FeatureCollection<Polygon>} Polygons created
  16049. * @throws {Error} if geoJson is invalid.
  16050. */
  16051. function polygonize$1(geoJson) {
  16052. var graph = Graph.fromGeoJson(geoJson);
  16053. // 1. Remove dangle node
  16054. graph.deleteDangles();
  16055. // 2. Remove cut-edges (bridge edges)
  16056. graph.deleteCutEdges();
  16057. // 3. Get all holes and shells
  16058. var holes = [],
  16059. shells = [];
  16060. graph.getEdgeRings()
  16061. .filter(function (edgeRing) { return edgeRing.isValid(); })
  16062. .forEach(function (edgeRing) {
  16063. if (edgeRing.isHole())
  16064. { holes.push(edgeRing); }
  16065. else
  16066. { shells.push(edgeRing); }
  16067. });
  16068. // 4. Assign Holes to Shells
  16069. holes.forEach(function (hole) {
  16070. if (EdgeRing.findEdgeRingContaining(hole, shells))
  16071. { shells.push(hole); }
  16072. });
  16073. // 5. EdgeRings to Polygons
  16074. return featureCollection(shells.map(function (shell) { return shell.toPolygon(); }));
  16075. }
  16076. /**
  16077. * Boolean-disjoint returns (TRUE) if the intersection of the two geometries is an empty set.
  16078. *
  16079. * @name booleanDisjoint
  16080. * @param {Geometry|Feature<any>} feature1 GeoJSON Feature or Geometry
  16081. * @param {Geometry|Feature<any>} feature2 GeoJSON Feature or Geometry
  16082. * @returns {boolean} true/false
  16083. * @example
  16084. * var point = turf.point([2, 2]);
  16085. * var line = turf.lineString([[1, 1], [1, 2], [1, 3], [1, 4]]);
  16086. *
  16087. * turf.booleanDisjoint(line, point);
  16088. * //=true
  16089. */
  16090. function booleanDisjoint(feature1, feature2) {
  16091. var boolean;
  16092. flattenEach(feature1, function (flatten1) {
  16093. flattenEach(feature2, function (flatten2) {
  16094. if (boolean === false) return false;
  16095. boolean = disjoint(flatten1.geometry, flatten2.geometry);
  16096. });
  16097. });
  16098. return boolean;
  16099. }
  16100. /**
  16101. * Disjoint operation for simple Geometries (Point/LineString/Polygon)
  16102. *
  16103. * @private
  16104. * @param {Geometry<any>} geom1 GeoJSON Geometry
  16105. * @param {Geometry<any>} geom2 GeoJSON Geometry
  16106. * @returns {boolean} true/false
  16107. */
  16108. function disjoint(geom1, geom2) {
  16109. switch (geom1.type) {
  16110. case 'Point':
  16111. switch (geom2.type) {
  16112. case 'Point':
  16113. return !compareCoords$1(geom1.coordinates, geom2.coordinates);
  16114. case 'LineString':
  16115. return !isPointOnLine$1(geom2, geom1);
  16116. case 'Polygon':
  16117. return !booleanPointInPolygon(geom1, geom2);
  16118. }
  16119. /* istanbul ignore next */
  16120. break;
  16121. case 'LineString':
  16122. switch (geom2.type) {
  16123. case 'Point':
  16124. return !isPointOnLine$1(geom1, geom2);
  16125. case 'LineString':
  16126. return !isLineOnLine$1(geom1, geom2);
  16127. case 'Polygon':
  16128. return !isLineInPoly$1(geom2, geom1);
  16129. }
  16130. /* istanbul ignore next */
  16131. break;
  16132. case 'Polygon':
  16133. switch (geom2.type) {
  16134. case 'Point':
  16135. return !booleanPointInPolygon(geom2, geom1);
  16136. case 'LineString':
  16137. return !isLineInPoly$1(geom1, geom2);
  16138. case 'Polygon':
  16139. return !isPolyInPoly$1(geom2, geom1);
  16140. }
  16141. }
  16142. }
  16143. // http://stackoverflow.com/a/11908158/1979085
  16144. function isPointOnLine$1(lineString, point) {
  16145. for (var i = 0; i < lineString.coordinates.length - 1; i++) {
  16146. if (isPointOnLineSegment$2(lineString.coordinates[i], lineString.coordinates[i + 1], point.coordinates)) {
  16147. return true;
  16148. }
  16149. }
  16150. return false;
  16151. }
  16152. function isLineOnLine$1(lineString1, lineString2) {
  16153. var doLinesIntersect = lineIntersect(lineString1, lineString2);
  16154. if (doLinesIntersect.features.length > 0) {
  16155. return true;
  16156. }
  16157. return false;
  16158. }
  16159. function isLineInPoly$1(polygon, lineString) {
  16160. var doLinesIntersect = lineIntersect(lineString, polygonToLine(polygon));
  16161. if (doLinesIntersect.features.length > 0) {
  16162. return true;
  16163. }
  16164. return false;
  16165. }
  16166. /**
  16167. * Is Polygon (geom1) in Polygon (geom2)
  16168. * Only takes into account outer rings
  16169. * See http://stackoverflow.com/a/4833823/1979085
  16170. *
  16171. * @private
  16172. * @param {Geometry|Feature<Polygon>} feature1 Polygon1
  16173. * @param {Geometry|Feature<Polygon>} feature2 Polygon2
  16174. * @returns {boolean} true/false
  16175. */
  16176. function isPolyInPoly$1(feature1, feature2) {
  16177. for (var i = 0; i < feature1.coordinates[0].length; i++) {
  16178. if (booleanPointInPolygon(feature1.coordinates[0][i], feature2)) {
  16179. return true;
  16180. }
  16181. }
  16182. for (var i2 = 0; i2 < feature2.coordinates[0].length; i2++) {
  16183. if (booleanPointInPolygon(feature2.coordinates[0][i2], feature1)) {
  16184. return true;
  16185. }
  16186. }
  16187. return false;
  16188. }
  16189. function isPointOnLineSegment$2(LineSegmentStart, LineSegmentEnd, Point) {
  16190. var dxc = Point[0] - LineSegmentStart[0];
  16191. var dyc = Point[1] - LineSegmentStart[1];
  16192. var dxl = LineSegmentEnd[0] - LineSegmentStart[0];
  16193. var dyl = LineSegmentEnd[1] - LineSegmentStart[1];
  16194. var cross = dxc * dyl - dyc * dxl;
  16195. if (cross !== 0) {
  16196. return false;
  16197. }
  16198. if (Math.abs(dxl) >= Math.abs(dyl)) {
  16199. if (dxl > 0) {
  16200. return LineSegmentStart[0] <= Point[0] && Point[0] <= LineSegmentEnd[0];
  16201. } else {
  16202. return LineSegmentEnd[0] <= Point[0] && Point[0] <= LineSegmentStart[0];
  16203. }
  16204. } else if (dyl > 0) {
  16205. return LineSegmentStart[1] <= Point[1] && Point[1] <= LineSegmentEnd[1];
  16206. } else {
  16207. return LineSegmentEnd[1] <= Point[1] && Point[1] <= LineSegmentStart[1];
  16208. }
  16209. }
  16210. /**
  16211. * compareCoords
  16212. *
  16213. * @private
  16214. * @param {Position} pair1 point [x,y]
  16215. * @param {Position} pair2 point [x,y]
  16216. * @returns {boolean} true/false if coord pairs match
  16217. */
  16218. function compareCoords$1(pair1, pair2) {
  16219. return pair1[0] === pair2[0] && pair1[1] === pair2[1];
  16220. }
  16221. /**
  16222. * Boolean-contains returns True if the second geometry is completely contained by the first geometry.
  16223. * The interiors of both geometries must intersect and, the interior and boundary of the secondary (geometry b)
  16224. * must not intersect the exterior of the primary (geometry a).
  16225. * Boolean-contains returns the exact opposite result of the `@turf/boolean-within`.
  16226. *
  16227. * @name booleanContains
  16228. * @param {Geometry|Feature<any>} feature1 GeoJSON Feature or Geometry
  16229. * @param {Geometry|Feature<any>} feature2 GeoJSON Feature or Geometry
  16230. * @returns {boolean} true/false
  16231. * @example
  16232. * var line = turf.lineString([[1, 1], [1, 2], [1, 3], [1, 4]]);
  16233. * var point = turf.point([1, 2]);
  16234. *
  16235. * turf.booleanContains(line, point);
  16236. * //=true
  16237. */
  16238. function booleanContains(feature1, feature2) {
  16239. var type1 = getType(feature1);
  16240. var type2 = getType(feature2);
  16241. var geom1 = getGeom(feature1);
  16242. var geom2 = getGeom(feature2);
  16243. var coords1 = getCoords(feature1);
  16244. var coords2 = getCoords(feature2);
  16245. switch (type1) {
  16246. case 'Point':
  16247. switch (type2) {
  16248. case 'Point':
  16249. return compareCoords$2(coords1, coords2);
  16250. default:
  16251. throw new Error('feature2 ' + type2 + ' geometry not supported');
  16252. }
  16253. case 'MultiPoint':
  16254. switch (type2) {
  16255. case 'Point':
  16256. return isPointInMultiPoint$1(geom1, geom2);
  16257. case 'MultiPoint':
  16258. return isMultiPointInMultiPoint$1(geom1, geom2);
  16259. default:
  16260. throw new Error('feature2 ' + type2 + ' geometry not supported');
  16261. }
  16262. case 'LineString':
  16263. switch (type2) {
  16264. case 'Point':
  16265. return booleanPointOnLine(geom2, geom1, {ignoreEndVertices: true});
  16266. case 'LineString':
  16267. return isLineOnLine$2(geom1, geom2);
  16268. case 'MultiPoint':
  16269. return isMultiPointOnLine$1(geom1, geom2);
  16270. default:
  16271. throw new Error('feature2 ' + type2 + ' geometry not supported');
  16272. }
  16273. case 'Polygon':
  16274. switch (type2) {
  16275. case 'Point':
  16276. return booleanPointInPolygon(geom2, geom1, {ignoreBoundary: true});
  16277. case 'LineString':
  16278. return isLineInPoly$2(geom1, geom2);
  16279. case 'Polygon':
  16280. return isPolyInPoly$2(geom1, geom2);
  16281. case 'MultiPoint':
  16282. return isMultiPointInPoly$1(geom1, geom2);
  16283. default:
  16284. throw new Error('feature2 ' + type2 + ' geometry not supported');
  16285. }
  16286. default:
  16287. throw new Error('feature1 ' + type1 + ' geometry not supported');
  16288. }
  16289. }
  16290. function isPointInMultiPoint$1(multiPoint, point) {
  16291. var i;
  16292. var output = false;
  16293. for (i = 0; i < multiPoint.coordinates.length; i++) {
  16294. if (compareCoords$2(multiPoint.coordinates[i], point.coordinates)) {
  16295. output = true;
  16296. break;
  16297. }
  16298. }
  16299. return output;
  16300. }
  16301. function isMultiPointInMultiPoint$1(multiPoint1, multiPoint2) {
  16302. for (var i = 0; i < multiPoint2.coordinates.length; i++) {
  16303. var matchFound = false;
  16304. for (var i2 = 0; i2 < multiPoint1.coordinates.length; i2++) {
  16305. if (compareCoords$2(multiPoint2.coordinates[i], multiPoint1.coordinates[i2])) {
  16306. matchFound = true;
  16307. break;
  16308. }
  16309. }
  16310. if (!matchFound) {
  16311. return false;
  16312. }
  16313. }
  16314. return true;
  16315. }
  16316. function isMultiPointOnLine$1(lineString, multiPoint) {
  16317. var haveFoundInteriorPoint = false;
  16318. for (var i = 0; i < multiPoint.coordinates.length; i++) {
  16319. if (booleanPointOnLine(multiPoint.coordinates[i], lineString, {ignoreEndVertices: true})) {
  16320. haveFoundInteriorPoint = true;
  16321. }
  16322. if (!booleanPointOnLine(multiPoint.coordinates[i], lineString)) {
  16323. return false;
  16324. }
  16325. }
  16326. if (haveFoundInteriorPoint) {
  16327. return true;
  16328. }
  16329. return false;
  16330. }
  16331. function isMultiPointInPoly$1(polygon, multiPoint) {
  16332. for (var i = 0; i < multiPoint.coordinates.length; i++) {
  16333. if (!booleanPointInPolygon(multiPoint.coordinates[i], polygon, {ignoreBoundary: true})) {
  16334. return false;
  16335. }
  16336. }
  16337. return true;
  16338. }
  16339. function isLineOnLine$2(lineString1, lineString2) {
  16340. var haveFoundInteriorPoint = false;
  16341. for (var i = 0; i < lineString2.coordinates.length; i++) {
  16342. if (booleanPointOnLine({type: 'Point', coordinates: lineString2.coordinates[i]}, lineString1, { ignoreEndVertices: true })) {
  16343. haveFoundInteriorPoint = true;
  16344. }
  16345. if (!booleanPointOnLine({type: 'Point', coordinates: lineString2.coordinates[i]}, lineString1, {ignoreEndVertices: false })) {
  16346. return false;
  16347. }
  16348. }
  16349. return haveFoundInteriorPoint;
  16350. }
  16351. function isLineInPoly$2(polygon, linestring) {
  16352. var output = false;
  16353. var i = 0;
  16354. var polyBbox = bbox(polygon);
  16355. var lineBbox = bbox(linestring);
  16356. if (!doBBoxOverlap$1(polyBbox, lineBbox)) {
  16357. return false;
  16358. }
  16359. for (i; i < linestring.coordinates.length - 1; i++) {
  16360. var midPoint = getMidpoint$1(linestring.coordinates[i], linestring.coordinates[i + 1]);
  16361. if (booleanPointInPolygon({type: 'Point', coordinates: midPoint}, polygon, { ignoreBoundary: true })) {
  16362. output = true;
  16363. break;
  16364. }
  16365. }
  16366. return output;
  16367. }
  16368. /**
  16369. * Is Polygon2 in Polygon1
  16370. * Only takes into account outer rings
  16371. *
  16372. * @private
  16373. * @param {Geometry|Feature<Polygon>} feature1 Polygon1
  16374. * @param {Geometry|Feature<Polygon>} feature2 Polygon2
  16375. * @returns {boolean} true/false
  16376. */
  16377. function isPolyInPoly$2(feature1, feature2) {
  16378. var poly1Bbox = bbox(feature1);
  16379. var poly2Bbox = bbox(feature2);
  16380. if (!doBBoxOverlap$1(poly1Bbox, poly2Bbox)) {
  16381. return false;
  16382. }
  16383. for (var i = 0; i < feature2.coordinates[0].length; i++) {
  16384. if (!booleanPointInPolygon(feature2.coordinates[0][i], feature1)) {
  16385. return false;
  16386. }
  16387. }
  16388. return true;
  16389. }
  16390. function doBBoxOverlap$1(bbox1, bbox2) {
  16391. if (bbox1[0] > bbox2[0]) return false;
  16392. if (bbox1[2] < bbox2[2]) return false;
  16393. if (bbox1[1] > bbox2[1]) return false;
  16394. if (bbox1[3] < bbox2[3]) return false;
  16395. return true;
  16396. }
  16397. /**
  16398. * compareCoords
  16399. *
  16400. * @private
  16401. * @param {Position} pair1 point [x,y]
  16402. * @param {Position} pair2 point [x,y]
  16403. * @returns {boolean} true/false if coord pairs match
  16404. */
  16405. function compareCoords$2(pair1, pair2) {
  16406. return pair1[0] === pair2[0] && pair1[1] === pair2[1];
  16407. }
  16408. function getMidpoint$1(pair1, pair2) {
  16409. return [(pair1[0] + pair2[0]) / 2, (pair1[1] + pair2[1]) / 2];
  16410. }
  16411. /**
  16412. * Boolean-Crosses returns True if the intersection results in a geometry whose dimension is one less than
  16413. * the maximum dimension of the two source geometries and the intersection set is interior to
  16414. * both source geometries.
  16415. *
  16416. * Boolean-Crosses returns t (TRUE) for only multipoint/polygon, multipoint/linestring, linestring/linestring, linestring/polygon, and linestring/multipolygon comparisons.
  16417. *
  16418. * @name booleanCrosses
  16419. * @param {Geometry|Feature<any>} feature1 GeoJSON Feature or Geometry
  16420. * @param {Geometry|Feature<any>} feature2 GeoJSON Feature or Geometry
  16421. * @returns {boolean} true/false
  16422. * @example
  16423. * var line1 = turf.lineString([[-2, 2], [4, 2]]);
  16424. * var line2 = turf.lineString([[1, 1], [1, 2], [1, 3], [1, 4]]);
  16425. *
  16426. * var cross = turf.booleanCrosses(line1, line2);
  16427. * //=true
  16428. */
  16429. function booleanCrosses(feature1, feature2) {
  16430. var type1 = getType(feature1);
  16431. var type2 = getType(feature2);
  16432. var geom1 = getGeom(feature1);
  16433. var geom2 = getGeom(feature2);
  16434. switch (type1) {
  16435. case 'MultiPoint':
  16436. switch (type2) {
  16437. case 'LineString':
  16438. return doMultiPointAndLineStringCross(geom1, geom2);
  16439. case 'Polygon':
  16440. return doesMultiPointCrossPoly(geom1, geom2);
  16441. default:
  16442. throw new Error('feature2 ' + type2 + ' geometry not supported');
  16443. }
  16444. case 'LineString':
  16445. switch (type2) {
  16446. case 'MultiPoint': // An inverse operation
  16447. return doMultiPointAndLineStringCross(geom2, geom1);
  16448. case 'LineString':
  16449. return doLineStringsCross(geom1, geom2);
  16450. case 'Polygon':
  16451. return doLineStringAndPolygonCross(geom1, geom2);
  16452. default:
  16453. throw new Error('feature2 ' + type2 + ' geometry not supported');
  16454. }
  16455. case 'Polygon':
  16456. switch (type2) {
  16457. case 'MultiPoint': // An inverse operation
  16458. return doesMultiPointCrossPoly(geom2, geom1);
  16459. case 'LineString': // An inverse operation
  16460. return doLineStringAndPolygonCross(geom2, geom1);
  16461. default:
  16462. throw new Error('feature2 ' + type2 + ' geometry not supported');
  16463. }
  16464. default:
  16465. throw new Error('feature1 ' + type1 + ' geometry not supported');
  16466. }
  16467. }
  16468. function doMultiPointAndLineStringCross(multiPoint$$1, lineString$$1) {
  16469. var foundIntPoint = false;
  16470. var foundExtPoint = false;
  16471. var pointLength = multiPoint$$1.coordinates.length;
  16472. var i = 0;
  16473. while (i < pointLength && !foundIntPoint && !foundExtPoint) {
  16474. for (var i2 = 0; i2 < lineString$$1.coordinates.length - 1; i2++) {
  16475. var incEndVertices = true;
  16476. if (i2 === 0 || i2 === lineString$$1.coordinates.length - 2) {
  16477. incEndVertices = false;
  16478. }
  16479. if (isPointOnLineSegment$3(lineString$$1.coordinates[i2], lineString$$1.coordinates[i2 + 1], multiPoint$$1.coordinates[i], incEndVertices)) {
  16480. foundIntPoint = true;
  16481. } else {
  16482. foundExtPoint = true;
  16483. }
  16484. }
  16485. i++;
  16486. }
  16487. return foundIntPoint && foundExtPoint;
  16488. }
  16489. function doLineStringsCross(lineString1, lineString2) {
  16490. var doLinesIntersect = lineIntersect(lineString1, lineString2);
  16491. if (doLinesIntersect.features.length > 0) {
  16492. for (var i = 0; i < lineString1.coordinates.length - 1; i++) {
  16493. for (var i2 = 0; i2 < lineString2.coordinates.length - 1; i2++) {
  16494. var incEndVertices = true;
  16495. if (i2 === 0 || i2 === lineString2.coordinates.length - 2) {
  16496. incEndVertices = false;
  16497. }
  16498. if (isPointOnLineSegment$3(lineString1.coordinates[i], lineString1.coordinates[i + 1], lineString2.coordinates[i2], incEndVertices)) {
  16499. return true;
  16500. }
  16501. }
  16502. }
  16503. }
  16504. return false;
  16505. }
  16506. function doLineStringAndPolygonCross(lineString$$1, polygon$$1) {
  16507. var doLinesIntersect = lineIntersect(lineString$$1, polygonToLine(polygon$$1));
  16508. if (doLinesIntersect.features.length > 0) {
  16509. return true;
  16510. }
  16511. return false;
  16512. }
  16513. function doesMultiPointCrossPoly(multiPoint$$1, polygon$$1) {
  16514. var foundIntPoint = false;
  16515. var foundExtPoint = false;
  16516. var pointLength = multiPoint$$1.coordinates[0].length;
  16517. var i = 0;
  16518. while (i < pointLength && foundIntPoint && foundExtPoint) {
  16519. if (booleanPointInPolygon(point(multiPoint$$1.coordinates[0][i]), polygon$$1)) {
  16520. foundIntPoint = true;
  16521. } else {
  16522. foundExtPoint = true;
  16523. }
  16524. i++;
  16525. }
  16526. return foundExtPoint && foundExtPoint;
  16527. }
  16528. /**
  16529. * Is a point on a line segment
  16530. * Only takes into account outer rings
  16531. * See http://stackoverflow.com/a/4833823/1979085
  16532. *
  16533. * @private
  16534. * @param {number[]} lineSegmentStart coord pair of start of line
  16535. * @param {number[]} lineSegmentEnd coord pair of end of line
  16536. * @param {number[]} pt coord pair of point to check
  16537. * @param {boolean} incEnd whether the point is allowed to fall on the line ends
  16538. * @returns {boolean} true/false
  16539. */
  16540. function isPointOnLineSegment$3(lineSegmentStart, lineSegmentEnd, pt, incEnd) {
  16541. var dxc = pt[0] - lineSegmentStart[0];
  16542. var dyc = pt[1] - lineSegmentStart[1];
  16543. var dxl = lineSegmentEnd[0] - lineSegmentStart[0];
  16544. var dyl = lineSegmentEnd[1] - lineSegmentStart[1];
  16545. var cross = dxc * dyl - dyc * dxl;
  16546. if (cross !== 0) {
  16547. return false;
  16548. }
  16549. if (incEnd) {
  16550. if (Math.abs(dxl) >= Math.abs(dyl)) {
  16551. return dxl > 0 ? lineSegmentStart[0] <= pt[0] && pt[0] <= lineSegmentEnd[0] : lineSegmentEnd[0] <= pt[0] && pt[0] <= lineSegmentStart[0];
  16552. }
  16553. return dyl > 0 ? lineSegmentStart[1] <= pt[1] && pt[1] <= lineSegmentEnd[1] : lineSegmentEnd[1] <= pt[1] && pt[1] <= lineSegmentStart[1];
  16554. } else {
  16555. if (Math.abs(dxl) >= Math.abs(dyl)) {
  16556. return dxl > 0 ? lineSegmentStart[0] < pt[0] && pt[0] < lineSegmentEnd[0] : lineSegmentEnd[0] < pt[0] && pt[0] < lineSegmentStart[0];
  16557. }
  16558. return dyl > 0 ? lineSegmentStart[1] < pt[1] && pt[1] < lineSegmentEnd[1] : lineSegmentEnd[1] < pt[1] && pt[1] < lineSegmentStart[1];
  16559. }
  16560. }
  16561. var keys = createCommonjsModule(function (module, exports) {
  16562. exports = module.exports = typeof Object.keys === 'function'
  16563. ? Object.keys : shim;
  16564. exports.shim = shim;
  16565. function shim (obj) {
  16566. var keys = [];
  16567. for (var key in obj) keys.push(key);
  16568. return keys;
  16569. }
  16570. });
  16571. var keys_1 = keys.shim;
  16572. var is_arguments = createCommonjsModule(function (module, exports) {
  16573. var supportsArgumentsClass = (function(){
  16574. return Object.prototype.toString.call(arguments)
  16575. })() == '[object Arguments]';
  16576. exports = module.exports = supportsArgumentsClass ? supported : unsupported;
  16577. exports.supported = supported;
  16578. function supported(object) {
  16579. return Object.prototype.toString.call(object) == '[object Arguments]';
  16580. }
  16581. exports.unsupported = unsupported;
  16582. function unsupported(object){
  16583. return object &&
  16584. typeof object == 'object' &&
  16585. typeof object.length == 'number' &&
  16586. Object.prototype.hasOwnProperty.call(object, 'callee') &&
  16587. !Object.prototype.propertyIsEnumerable.call(object, 'callee') ||
  16588. false;
  16589. }
  16590. });
  16591. var is_arguments_1 = is_arguments.supported;
  16592. var is_arguments_2 = is_arguments.unsupported;
  16593. var deepEqual_1 = createCommonjsModule(function (module) {
  16594. var pSlice = Array.prototype.slice;
  16595. var deepEqual = module.exports = function (actual, expected, opts) {
  16596. if (!opts) opts = {};
  16597. // 7.1. All identical values are equivalent, as determined by ===.
  16598. if (actual === expected) {
  16599. return true;
  16600. } else if (actual instanceof Date && expected instanceof Date) {
  16601. return actual.getTime() === expected.getTime();
  16602. // 7.3. Other pairs that do not both pass typeof value == 'object',
  16603. // equivalence is determined by ==.
  16604. } else if (!actual || !expected || typeof actual != 'object' && typeof expected != 'object') {
  16605. return opts.strict ? actual === expected : actual == expected;
  16606. // 7.4. For all other Object pairs, including Array objects, equivalence is
  16607. // determined by having the same number of owned properties (as verified
  16608. // with Object.prototype.hasOwnProperty.call), the same set of keys
  16609. // (although not necessarily the same order), equivalent values for every
  16610. // corresponding key, and an identical 'prototype' property. Note: this
  16611. // accounts for both named and indexed properties on Arrays.
  16612. } else {
  16613. return objEquiv(actual, expected, opts);
  16614. }
  16615. };
  16616. function isUndefinedOrNull(value) {
  16617. return value === null || value === undefined;
  16618. }
  16619. function isBuffer (x) {
  16620. if (!x || typeof x !== 'object' || typeof x.length !== 'number') return false;
  16621. if (typeof x.copy !== 'function' || typeof x.slice !== 'function') {
  16622. return false;
  16623. }
  16624. if (x.length > 0 && typeof x[0] !== 'number') return false;
  16625. return true;
  16626. }
  16627. function objEquiv(a, b, opts) {
  16628. var i, key;
  16629. if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
  16630. return false;
  16631. // an identical 'prototype' property.
  16632. if (a.prototype !== b.prototype) return false;
  16633. //~~~I've managed to break Object.keys through screwy arguments passing.
  16634. // Converting to array solves the problem.
  16635. if (is_arguments(a)) {
  16636. if (!is_arguments(b)) {
  16637. return false;
  16638. }
  16639. a = pSlice.call(a);
  16640. b = pSlice.call(b);
  16641. return deepEqual(a, b, opts);
  16642. }
  16643. if (isBuffer(a)) {
  16644. if (!isBuffer(b)) {
  16645. return false;
  16646. }
  16647. if (a.length !== b.length) return false;
  16648. for (i = 0; i < a.length; i++) {
  16649. if (a[i] !== b[i]) return false;
  16650. }
  16651. return true;
  16652. }
  16653. try {
  16654. var ka = keys(a),
  16655. kb = keys(b);
  16656. } catch (e) {//happens when one is a string literal and the other isn't
  16657. return false;
  16658. }
  16659. // having the same number of owned properties (keys incorporates
  16660. // hasOwnProperty)
  16661. if (ka.length != kb.length)
  16662. return false;
  16663. //the same set of keys (although not necessarily the same order),
  16664. ka.sort();
  16665. kb.sort();
  16666. //~~~cheap key test
  16667. for (i = ka.length - 1; i >= 0; i--) {
  16668. if (ka[i] != kb[i])
  16669. return false;
  16670. }
  16671. //equivalent values for every corresponding key, and
  16672. //~~~possibly expensive deep test
  16673. for (i = ka.length - 1; i >= 0; i--) {
  16674. key = ka[i];
  16675. if (!deepEqual(a[key], b[key], opts)) return false;
  16676. }
  16677. return typeof a === typeof b;
  16678. }
  16679. });
  16680. //index.js
  16681. var Equality = function(opt) {
  16682. this.precision = opt && opt.precision ? opt.precision : 17;
  16683. this.direction = opt && opt.direction ? opt.direction : false;
  16684. this.pseudoNode = opt && opt.pseudoNode ? opt.pseudoNode : false;
  16685. this.objectComparator = opt && opt.objectComparator ? opt.objectComparator : objectComparator;
  16686. };
  16687. Equality.prototype.compare = function(g1,g2) {
  16688. if (g1.type !== g2.type || !sameLength(g1,g2)) return false;
  16689. switch(g1.type) {
  16690. case 'Point':
  16691. return this.compareCoord(g1.coordinates, g2.coordinates);
  16692. break;
  16693. case 'LineString':
  16694. return this.compareLine(g1.coordinates, g2.coordinates,0,false);
  16695. break;
  16696. case 'Polygon':
  16697. return this.comparePolygon(g1,g2);
  16698. break;
  16699. case 'Feature':
  16700. return this.compareFeature(g1, g2);
  16701. default:
  16702. if (g1.type.indexOf('Multi') === 0) {
  16703. var context = this;
  16704. var g1s = explode$2(g1);
  16705. var g2s = explode$2(g2);
  16706. return g1s.every(function(g1part) {
  16707. return this.some(function(g2part) {
  16708. return context.compare(g1part,g2part);
  16709. });
  16710. },g2s);
  16711. }
  16712. }
  16713. return false;
  16714. };
  16715. function explode$2(g) {
  16716. return g.coordinates.map(function(part) {
  16717. return {
  16718. type: g.type.replace('Multi', ''),
  16719. coordinates: part}
  16720. });
  16721. }
  16722. //compare length of coordinates/array
  16723. function sameLength(g1,g2) {
  16724. return g1.hasOwnProperty('coordinates') ?
  16725. g1.coordinates.length === g2.coordinates.length
  16726. : g1.length === g2.length;
  16727. }
  16728. // compare the two coordinates [x,y]
  16729. Equality.prototype.compareCoord = function(c1,c2) {
  16730. if (c1.length !== c2.length) {
  16731. return false;
  16732. }
  16733. for (var i=0; i < c1.length; i++) {
  16734. if (c1[i].toFixed(this.precision) !== c2[i].toFixed(this.precision)) {
  16735. return false;
  16736. }
  16737. }
  16738. return true;
  16739. };
  16740. Equality.prototype.compareLine = function(path1,path2,ind,isPoly) {
  16741. if (!sameLength(path1,path2)) return false;
  16742. var p1 = this.pseudoNode ? path1 : this.removePseudo(path1);
  16743. var p2 = this.pseudoNode ? path2 : this.removePseudo(path2);
  16744. if (isPoly && !this.compareCoord(p1[0],p2[0])) {
  16745. // fix start index of both to same point
  16746. p2 = this.fixStartIndex(p2,p1);
  16747. if(!p2) return;
  16748. }
  16749. // for linestring ind =0 and for polygon ind =1
  16750. var sameDirection = this.compareCoord(p1[ind],p2[ind]);
  16751. if (this.direction || sameDirection
  16752. ) {
  16753. return this.comparePath(p1, p2);
  16754. } else {
  16755. if (this.compareCoord(p1[ind],p2[p2.length - (1+ind)])
  16756. ) {
  16757. return this.comparePath(p1.slice().reverse(), p2);
  16758. }
  16759. return false;
  16760. }
  16761. };
  16762. Equality.prototype.fixStartIndex = function(sourcePath,targetPath) {
  16763. //make sourcePath first point same as of targetPath
  16764. var correctPath,ind = -1;
  16765. for (var i=0; i< sourcePath.length; i++) {
  16766. if(this.compareCoord(sourcePath[i],targetPath[0])) {
  16767. ind = i;
  16768. break;
  16769. }
  16770. }
  16771. if (ind >= 0) {
  16772. correctPath = [].concat(
  16773. sourcePath.slice(ind,sourcePath.length),
  16774. sourcePath.slice(1,ind+1));
  16775. }
  16776. return correctPath;
  16777. };
  16778. Equality.prototype.comparePath = function (p1,p2) {
  16779. var cont = this;
  16780. return p1.every(function(c,i) {
  16781. return cont.compareCoord(c,this[i]);
  16782. },p2);
  16783. };
  16784. Equality.prototype.comparePolygon = function(g1,g2) {
  16785. if (this.compareLine(g1.coordinates[0],g2.coordinates[0],1,true)) {
  16786. var holes1 = g1.coordinates.slice(1,g1.coordinates.length);
  16787. var holes2 = g2.coordinates.slice(1,g2.coordinates.length);
  16788. var cont = this;
  16789. return holes1.every(function(h1) {
  16790. return this.some(function(h2) {
  16791. return cont.compareLine(h1,h2,1,true);
  16792. });
  16793. },holes2);
  16794. } else {
  16795. return false;
  16796. }
  16797. };
  16798. Equality.prototype.compareFeature = function(g1,g2) {
  16799. if (
  16800. g1.id !== g2.id ||
  16801. !this.objectComparator(g1.properties, g2.properties) ||
  16802. !this.compareBBox(g1,g2)
  16803. ) {
  16804. return false;
  16805. }
  16806. return this.compare(g1.geometry, g2.geometry);
  16807. };
  16808. Equality.prototype.compareBBox = function(g1,g2) {
  16809. if (
  16810. (!g1.bbox && !g2.bbox) ||
  16811. (
  16812. g1.bbox && g2.bbox &&
  16813. this.compareCoord(g1.bbox, g2.bbox)
  16814. )
  16815. ) {
  16816. return true;
  16817. }
  16818. return false;
  16819. };
  16820. Equality.prototype.removePseudo = function(path) {
  16821. //TODO to be implement
  16822. return path;
  16823. };
  16824. function objectComparator(obj1, obj2) {
  16825. return deepEqual_1(obj1, obj2, {strict: true});
  16826. }
  16827. var geojsonEquality = Equality;
  16828. /**
  16829. * Compares two geometries of the same dimension and returns true if their intersection set results in a geometry
  16830. * different from both but of the same dimension. It applies to Polygon/Polygon, LineString/LineString,
  16831. * Multipoint/Multipoint, MultiLineString/MultiLineString and MultiPolygon/MultiPolygon.
  16832. *
  16833. * @name booleanOverlap
  16834. * @param {Geometry|Feature<LineString|MultiLineString|Polygon|MultiPolygon>} feature1 input
  16835. * @param {Geometry|Feature<LineString|MultiLineString|Polygon|MultiPolygon>} feature2 input
  16836. * @returns {boolean} true/false
  16837. * @example
  16838. * var poly1 = turf.polygon([[[0,0],[0,5],[5,5],[5,0],[0,0]]]);
  16839. * var poly2 = turf.polygon([[[1,1],[1,6],[6,6],[6,1],[1,1]]]);
  16840. * var poly3 = turf.polygon([[[10,10],[10,15],[15,15],[15,10],[10,10]]]);
  16841. *
  16842. * turf.booleanOverlap(poly1, poly2)
  16843. * //=true
  16844. * turf.booleanOverlap(poly2, poly3)
  16845. * //=false
  16846. */
  16847. function booleanOverlap(feature1, feature2) {
  16848. // validation
  16849. if (!feature1) throw new Error('feature1 is required');
  16850. if (!feature2) throw new Error('feature2 is required');
  16851. var type1 = getType(feature1);
  16852. var type2 = getType(feature2);
  16853. if (type1 !== type2) throw new Error('features must be of the same type');
  16854. if (type1 === 'Point') throw new Error('Point geometry not supported');
  16855. // features must be not equal
  16856. var equality = new geojsonEquality({precision: 6});
  16857. if (equality.compare(feature1, feature2)) return false;
  16858. var overlap = 0;
  16859. switch (type1) {
  16860. case 'MultiPoint':
  16861. var coords1 = coordAll(feature1);
  16862. var coords2 = coordAll(feature2);
  16863. coords1.forEach(function (coord1) {
  16864. coords2.forEach(function (coord2) {
  16865. if (coord1[0] === coord2[0] && coord1[1] === coord2[1]) overlap++;
  16866. });
  16867. });
  16868. break;
  16869. case 'LineString':
  16870. case 'MultiLineString':
  16871. segmentEach(feature1, function (segment1) {
  16872. segmentEach(feature2, function (segment2) {
  16873. if (lineOverlap(segment1, segment2).features.length) overlap++;
  16874. });
  16875. });
  16876. break;
  16877. case 'Polygon':
  16878. case 'MultiPolygon':
  16879. segmentEach(feature1, function (segment1) {
  16880. segmentEach(feature2, function (segment2) {
  16881. if (lineIntersect(segment1, segment2).features.length) overlap++;
  16882. });
  16883. });
  16884. break;
  16885. }
  16886. return overlap > 0;
  16887. }
  16888. /**
  16889. * Determine whether two geometries of the same type have identical X,Y coordinate values.
  16890. * See http://edndoc.esri.com/arcsde/9.0/general_topics/understand_spatial_relations.htm
  16891. *
  16892. * @name booleanEqual
  16893. * @param {Geometry|Feature} feature1 GeoJSON input
  16894. * @param {Geometry|Feature} feature2 GeoJSON input
  16895. * @returns {boolean} true if the objects are equal, false otherwise
  16896. * @example
  16897. * var pt1 = turf.point([0, 0]);
  16898. * var pt2 = turf.point([0, 0]);
  16899. * var pt3 = turf.point([1, 1]);
  16900. *
  16901. * turf.booleanEqual(pt1, pt2);
  16902. * //= true
  16903. * turf.booleanEqual(pt2, pt3);
  16904. * //= false
  16905. */
  16906. function booleanEqual(feature1, feature2) {
  16907. // validation
  16908. if (!feature1) throw new Error('feature1 is required');
  16909. if (!feature2) throw new Error('feature2 is required');
  16910. var type1 = getType(feature1);
  16911. var type2 = getType(feature2);
  16912. if (type1 !== type2) return false;
  16913. var equality = new geojsonEquality({precision: 6});
  16914. return equality.compare(cleanCoords(feature1), cleanCoords(feature2));
  16915. }
  16916. var DBSCAN_1 = createCommonjsModule(function (module) {
  16917. /**
  16918. * DBSCAN - Density based clustering
  16919. *
  16920. * @author Lukasz Krawczyk <contact@lukaszkrawczyk.eu>
  16921. * @copyright MIT
  16922. */
  16923. /**
  16924. * DBSCAN class construcotr
  16925. * @constructor
  16926. *
  16927. * @param {Array} dataset
  16928. * @param {number} epsilon
  16929. * @param {number} minPts
  16930. * @param {function} distanceFunction
  16931. * @returns {DBSCAN}
  16932. */
  16933. function DBSCAN(dataset, epsilon, minPts, distanceFunction) {
  16934. /** @type {Array} */
  16935. this.dataset = [];
  16936. /** @type {number} */
  16937. this.epsilon = 1;
  16938. /** @type {number} */
  16939. this.minPts = 2;
  16940. /** @type {function} */
  16941. this.distance = this._euclideanDistance;
  16942. /** @type {Array} */
  16943. this.clusters = [];
  16944. /** @type {Array} */
  16945. this.noise = [];
  16946. // temporary variables used during computation
  16947. /** @type {Array} */
  16948. this._visited = [];
  16949. /** @type {Array} */
  16950. this._assigned = [];
  16951. /** @type {number} */
  16952. this._datasetLength = 0;
  16953. this._init(dataset, epsilon, minPts, distanceFunction);
  16954. }
  16955. /******************************************************************************/
  16956. // public functions
  16957. /**
  16958. * Start clustering
  16959. *
  16960. * @param {Array} dataset
  16961. * @param {number} epsilon
  16962. * @param {number} minPts
  16963. * @param {function} distanceFunction
  16964. * @returns {undefined}
  16965. * @access public
  16966. */
  16967. DBSCAN.prototype.run = function(dataset, epsilon, minPts, distanceFunction) {
  16968. this._init(dataset, epsilon, minPts, distanceFunction);
  16969. for (var pointId = 0; pointId < this._datasetLength; pointId++) {
  16970. // if point is not visited, check if it forms a cluster
  16971. if (this._visited[pointId] !== 1) {
  16972. this._visited[pointId] = 1;
  16973. // if closest neighborhood is too small to form a cluster, mark as noise
  16974. var neighbors = this._regionQuery(pointId);
  16975. if (neighbors.length < this.minPts) {
  16976. this.noise.push(pointId);
  16977. } else {
  16978. // create new cluster and add point
  16979. var clusterId = this.clusters.length;
  16980. this.clusters.push([]);
  16981. this._addToCluster(pointId, clusterId);
  16982. this._expandCluster(clusterId, neighbors);
  16983. }
  16984. }
  16985. }
  16986. return this.clusters;
  16987. };
  16988. /******************************************************************************/
  16989. // protected functions
  16990. /**
  16991. * Set object properties
  16992. *
  16993. * @param {Array} dataset
  16994. * @param {number} epsilon
  16995. * @param {number} minPts
  16996. * @param {function} distance
  16997. * @returns {undefined}
  16998. * @access protected
  16999. */
  17000. DBSCAN.prototype._init = function(dataset, epsilon, minPts, distance) {
  17001. if (dataset) {
  17002. if (!(dataset instanceof Array)) {
  17003. throw Error('Dataset must be of type array, ' +
  17004. typeof dataset + ' given');
  17005. }
  17006. this.dataset = dataset;
  17007. this.clusters = [];
  17008. this.noise = [];
  17009. this._datasetLength = dataset.length;
  17010. this._visited = new Array(this._datasetLength);
  17011. this._assigned = new Array(this._datasetLength);
  17012. }
  17013. if (epsilon) {
  17014. this.epsilon = epsilon;
  17015. }
  17016. if (minPts) {
  17017. this.minPts = minPts;
  17018. }
  17019. if (distance) {
  17020. this.distance = distance;
  17021. }
  17022. };
  17023. /**
  17024. * Expand cluster to closest points of given neighborhood
  17025. *
  17026. * @param {number} clusterId
  17027. * @param {Array} neighbors
  17028. * @returns {undefined}
  17029. * @access protected
  17030. */
  17031. DBSCAN.prototype._expandCluster = function(clusterId, neighbors) {
  17032. /**
  17033. * It's very important to calculate length of neighbors array each time,
  17034. * as the number of elements changes over time
  17035. */
  17036. for (var i = 0; i < neighbors.length; i++) {
  17037. var pointId2 = neighbors[i];
  17038. if (this._visited[pointId2] !== 1) {
  17039. this._visited[pointId2] = 1;
  17040. var neighbors2 = this._regionQuery(pointId2);
  17041. if (neighbors2.length >= this.minPts) {
  17042. neighbors = this._mergeArrays(neighbors, neighbors2);
  17043. }
  17044. }
  17045. // add to cluster
  17046. if (this._assigned[pointId2] !== 1) {
  17047. this._addToCluster(pointId2, clusterId);
  17048. }
  17049. }
  17050. };
  17051. /**
  17052. * Add new point to cluster
  17053. *
  17054. * @param {number} pointId
  17055. * @param {number} clusterId
  17056. */
  17057. DBSCAN.prototype._addToCluster = function(pointId, clusterId) {
  17058. this.clusters[clusterId].push(pointId);
  17059. this._assigned[pointId] = 1;
  17060. };
  17061. /**
  17062. * Find all neighbors around given point
  17063. *
  17064. * @param {number} pointId,
  17065. * @param {number} epsilon
  17066. * @returns {Array}
  17067. * @access protected
  17068. */
  17069. DBSCAN.prototype._regionQuery = function(pointId) {
  17070. var neighbors = [];
  17071. for (var id = 0; id < this._datasetLength; id++) {
  17072. var dist = this.distance(this.dataset[pointId], this.dataset[id]);
  17073. if (dist < this.epsilon) {
  17074. neighbors.push(id);
  17075. }
  17076. }
  17077. return neighbors;
  17078. };
  17079. /******************************************************************************/
  17080. // helpers
  17081. /**
  17082. * @param {Array} a
  17083. * @param {Array} b
  17084. * @returns {Array}
  17085. * @access protected
  17086. */
  17087. DBSCAN.prototype._mergeArrays = function(a, b) {
  17088. var len = b.length;
  17089. for (var i = 0; i < len; i++) {
  17090. var P = b[i];
  17091. if (a.indexOf(P) < 0) {
  17092. a.push(P);
  17093. }
  17094. }
  17095. return a;
  17096. };
  17097. /**
  17098. * Calculate euclidean distance in multidimensional space
  17099. *
  17100. * @param {Array} p
  17101. * @param {Array} q
  17102. * @returns {number}
  17103. * @access protected
  17104. */
  17105. DBSCAN.prototype._euclideanDistance = function(p, q) {
  17106. var sum = 0;
  17107. var i = Math.min(p.length, q.length);
  17108. while (i--) {
  17109. sum += (p[i] - q[i]) * (p[i] - q[i]);
  17110. }
  17111. return Math.sqrt(sum);
  17112. };
  17113. if ('object' !== 'undefined' && module.exports) {
  17114. module.exports = DBSCAN;
  17115. }
  17116. });
  17117. var KMEANS_1 = createCommonjsModule(function (module) {
  17118. /**
  17119. * KMEANS clustering
  17120. *
  17121. * @author Lukasz Krawczyk <contact@lukaszkrawczyk.eu>
  17122. * @copyright MIT
  17123. */
  17124. /**
  17125. * KMEANS class constructor
  17126. * @constructor
  17127. *
  17128. * @param {Array} dataset
  17129. * @param {number} k - number of clusters
  17130. * @param {function} distance - distance function
  17131. * @returns {KMEANS}
  17132. */
  17133. function KMEANS(dataset, k, distance) {
  17134. this.k = 3; // number of clusters
  17135. this.dataset = []; // set of feature vectors
  17136. this.assignments = []; // set of associated clusters for each feature vector
  17137. this.centroids = []; // vectors for our clusters
  17138. this.init(dataset, k, distance);
  17139. }
  17140. /**
  17141. * @returns {undefined}
  17142. */
  17143. KMEANS.prototype.init = function(dataset, k, distance) {
  17144. this.assignments = [];
  17145. this.centroids = [];
  17146. if (typeof dataset !== 'undefined') {
  17147. this.dataset = dataset;
  17148. }
  17149. if (typeof k !== 'undefined') {
  17150. this.k = k;
  17151. }
  17152. if (typeof distance !== 'undefined') {
  17153. this.distance = distance;
  17154. }
  17155. };
  17156. /**
  17157. * @returns {undefined}
  17158. */
  17159. KMEANS.prototype.run = function(dataset, k) {
  17160. this.init(dataset, k);
  17161. var len = this.dataset.length;
  17162. // initialize centroids
  17163. for (var i = 0; i < this.k; i++) {
  17164. this.centroids[i] = this.randomCentroid();
  17165. }
  17166. var change = true;
  17167. while(change) {
  17168. // assign feature vectors to clusters
  17169. change = this.assign();
  17170. // adjust location of centroids
  17171. for (var centroidId = 0; centroidId < this.k; centroidId++) {
  17172. var mean = new Array(maxDim);
  17173. var count = 0;
  17174. // init mean vector
  17175. for (var dim = 0; dim < maxDim; dim++) {
  17176. mean[dim] = 0;
  17177. }
  17178. for (var j = 0; j < len; j++) {
  17179. var maxDim = this.dataset[j].length;
  17180. // if current cluster id is assigned to point
  17181. if (centroidId === this.assignments[j]) {
  17182. for (var dim = 0; dim < maxDim; dim++) {
  17183. mean[dim] += this.dataset[j][dim];
  17184. }
  17185. count++;
  17186. }
  17187. }
  17188. if (count > 0) {
  17189. // if cluster contain points, adjust centroid position
  17190. for (var dim = 0; dim < maxDim; dim++) {
  17191. mean[dim] /= count;
  17192. }
  17193. this.centroids[centroidId] = mean;
  17194. } else {
  17195. // if cluster is empty, generate new random centroid
  17196. this.centroids[centroidId] = this.randomCentroid();
  17197. change = true;
  17198. }
  17199. }
  17200. }
  17201. return this.getClusters();
  17202. };
  17203. /**
  17204. * Generate random centroid
  17205. *
  17206. * @returns {Array}
  17207. */
  17208. KMEANS.prototype.randomCentroid = function() {
  17209. var maxId = this.dataset.length -1;
  17210. var centroid;
  17211. var id;
  17212. do {
  17213. id = Math.round(Math.random() * maxId);
  17214. centroid = this.dataset[id];
  17215. } while (this.centroids.indexOf(centroid) >= 0);
  17216. return centroid;
  17217. };
  17218. /**
  17219. * Assign points to clusters
  17220. *
  17221. * @returns {boolean}
  17222. */
  17223. KMEANS.prototype.assign = function() {
  17224. var change = false;
  17225. var len = this.dataset.length;
  17226. var closestCentroid;
  17227. for (var i = 0; i < len; i++) {
  17228. closestCentroid = this.argmin(this.dataset[i], this.centroids, this.distance);
  17229. if (closestCentroid != this.assignments[i]) {
  17230. this.assignments[i] = closestCentroid;
  17231. change = true;
  17232. }
  17233. }
  17234. return change;
  17235. };
  17236. /**
  17237. * Extract information about clusters
  17238. *
  17239. * @returns {undefined}
  17240. */
  17241. KMEANS.prototype.getClusters = function() {
  17242. var clusters = new Array(this.k);
  17243. var centroidId;
  17244. for (var pointId = 0; pointId < this.assignments.length; pointId++) {
  17245. centroidId = this.assignments[pointId];
  17246. // init empty cluster
  17247. if (typeof clusters[centroidId] === 'undefined') {
  17248. clusters[centroidId] = [];
  17249. }
  17250. clusters[centroidId].push(pointId);
  17251. }
  17252. return clusters;
  17253. };
  17254. // utils
  17255. /**
  17256. * @params {Array} point
  17257. * @params {Array.<Array>} set
  17258. * @params {Function} f
  17259. * @returns {number}
  17260. */
  17261. KMEANS.prototype.argmin = function(point, set, f) {
  17262. var min = Number.MAX_VALUE;
  17263. var arg = 0;
  17264. var len = set.length;
  17265. var d;
  17266. for (var i = 0; i < len; i++) {
  17267. d = f(point, set[i]);
  17268. if (d < min) {
  17269. min = d;
  17270. arg = i;
  17271. }
  17272. }
  17273. return arg;
  17274. };
  17275. /**
  17276. * Euclidean distance
  17277. *
  17278. * @params {number} p
  17279. * @params {number} q
  17280. * @returns {number}
  17281. */
  17282. KMEANS.prototype.distance = function(p, q) {
  17283. var sum = 0;
  17284. var i = Math.min(p.length, q.length);
  17285. while (i--) {
  17286. var diff = p[i] - q[i];
  17287. sum += diff * diff;
  17288. }
  17289. return Math.sqrt(sum);
  17290. };
  17291. if ('object' !== 'undefined' && module.exports) {
  17292. module.exports = KMEANS;
  17293. }
  17294. });
  17295. var PriorityQueue_1 = createCommonjsModule(function (module) {
  17296. /**
  17297. * PriorityQueue
  17298. * Elements in this queue are sorted according to their value
  17299. *
  17300. * @author Lukasz Krawczyk <contact@lukaszkrawczyk.eu>
  17301. * @copyright MIT
  17302. */
  17303. /**
  17304. * PriorityQueue class construcotr
  17305. * @constructor
  17306. *
  17307. * @example
  17308. * queue: [1,2,3,4]
  17309. * priorities: [4,1,2,3]
  17310. * > result = [1,4,2,3]
  17311. *
  17312. * @param {Array} elements
  17313. * @param {Array} priorities
  17314. * @param {string} sorting - asc / desc
  17315. * @returns {PriorityQueue}
  17316. */
  17317. function PriorityQueue(elements, priorities, sorting) {
  17318. /** @type {Array} */
  17319. this._queue = [];
  17320. /** @type {Array} */
  17321. this._priorities = [];
  17322. /** @type {string} */
  17323. this._sorting = 'desc';
  17324. this._init(elements, priorities, sorting);
  17325. }
  17326. /**
  17327. * Insert element
  17328. *
  17329. * @param {Object} ele
  17330. * @param {Object} priority
  17331. * @returns {undefined}
  17332. * @access public
  17333. */
  17334. PriorityQueue.prototype.insert = function(ele, priority) {
  17335. var indexToInsert = this._queue.length;
  17336. var index = indexToInsert;
  17337. while (index--) {
  17338. var priority2 = this._priorities[index];
  17339. if (this._sorting === 'desc') {
  17340. if (priority > priority2) {
  17341. indexToInsert = index;
  17342. }
  17343. } else {
  17344. if (priority < priority2) {
  17345. indexToInsert = index;
  17346. }
  17347. }
  17348. }
  17349. this._insertAt(ele, priority, indexToInsert);
  17350. };
  17351. /**
  17352. * Remove element
  17353. *
  17354. * @param {Object} ele
  17355. * @returns {undefined}
  17356. * @access public
  17357. */
  17358. PriorityQueue.prototype.remove = function(ele) {
  17359. var index = this._queue.length;
  17360. while (index--) {
  17361. var ele2 = this._queue[index];
  17362. if (ele === ele2) {
  17363. this._queue.splice(index, 1);
  17364. this._priorities.splice(index, 1);
  17365. break;
  17366. }
  17367. }
  17368. };
  17369. /**
  17370. * For each loop wrapper
  17371. *
  17372. * @param {function} func
  17373. * @returs {undefined}
  17374. * @access public
  17375. */
  17376. PriorityQueue.prototype.forEach = function(func) {
  17377. this._queue.forEach(func);
  17378. };
  17379. /**
  17380. * @returns {Array}
  17381. * @access public
  17382. */
  17383. PriorityQueue.prototype.getElements = function() {
  17384. return this._queue;
  17385. };
  17386. /**
  17387. * @param {number} index
  17388. * @returns {Object}
  17389. * @access public
  17390. */
  17391. PriorityQueue.prototype.getElementPriority = function(index) {
  17392. return this._priorities[index];
  17393. };
  17394. /**
  17395. * @returns {Array}
  17396. * @access public
  17397. */
  17398. PriorityQueue.prototype.getPriorities = function() {
  17399. return this._priorities;
  17400. };
  17401. /**
  17402. * @returns {Array}
  17403. * @access public
  17404. */
  17405. PriorityQueue.prototype.getElementsWithPriorities = function() {
  17406. var result = [];
  17407. for (var i = 0, l = this._queue.length; i < l; i++) {
  17408. result.push([this._queue[i], this._priorities[i]]);
  17409. }
  17410. return result;
  17411. };
  17412. /**
  17413. * Set object properties
  17414. *
  17415. * @param {Array} elements
  17416. * @param {Array} priorities
  17417. * @returns {undefined}
  17418. * @access protected
  17419. */
  17420. PriorityQueue.prototype._init = function(elements, priorities, sorting) {
  17421. if (elements && priorities) {
  17422. this._queue = [];
  17423. this._priorities = [];
  17424. if (elements.length !== priorities.length) {
  17425. throw new Error('Arrays must have the same length');
  17426. }
  17427. for (var i = 0; i < elements.length; i++) {
  17428. this.insert(elements[i], priorities[i]);
  17429. }
  17430. }
  17431. if (sorting) {
  17432. this._sorting = sorting;
  17433. }
  17434. };
  17435. /**
  17436. * Insert element at given position
  17437. *
  17438. * @param {Object} ele
  17439. * @param {number} index
  17440. * @returns {undefined}
  17441. * @access protected
  17442. */
  17443. PriorityQueue.prototype._insertAt = function(ele, priority, index) {
  17444. if (this._queue.length === index) {
  17445. this._queue.push(ele);
  17446. this._priorities.push(priority);
  17447. } else {
  17448. this._queue.splice(index, 0, ele);
  17449. this._priorities.splice(index, 0, priority);
  17450. }
  17451. };
  17452. if ('object' !== 'undefined' && module.exports) {
  17453. module.exports = PriorityQueue;
  17454. }
  17455. });
  17456. var OPTICS_1 = createCommonjsModule(function (module) {
  17457. /**
  17458. * @requires ./PriorityQueue.js
  17459. */
  17460. if ('object' !== 'undefined' && module.exports) {
  17461. var PriorityQueue = PriorityQueue_1;
  17462. }
  17463. /**
  17464. * OPTICS - Ordering points to identify the clustering structure
  17465. *
  17466. * @author Lukasz Krawczyk <contact@lukaszkrawczyk.eu>
  17467. * @copyright MIT
  17468. */
  17469. /**
  17470. * OPTICS class constructor
  17471. * @constructor
  17472. *
  17473. * @param {Array} dataset
  17474. * @param {number} epsilon
  17475. * @param {number} minPts
  17476. * @param {function} distanceFunction
  17477. * @returns {OPTICS}
  17478. */
  17479. function OPTICS(dataset, epsilon, minPts, distanceFunction) {
  17480. /** @type {number} */
  17481. this.epsilon = 1;
  17482. /** @type {number} */
  17483. this.minPts = 1;
  17484. /** @type {function} */
  17485. this.distance = this._euclideanDistance;
  17486. // temporary variables used during computation
  17487. /** @type {Array} */
  17488. this._reachability = [];
  17489. /** @type {Array} */
  17490. this._processed = [];
  17491. /** @type {number} */
  17492. this._coreDistance = 0;
  17493. /** @type {Array} */
  17494. this._orderedList = [];
  17495. this._init(dataset, epsilon, minPts, distanceFunction);
  17496. }
  17497. /******************************************************************************/
  17498. // pulic functions
  17499. /**
  17500. * Start clustering
  17501. *
  17502. * @param {Array} dataset
  17503. * @returns {undefined}
  17504. * @access public
  17505. */
  17506. OPTICS.prototype.run = function(dataset, epsilon, minPts, distanceFunction) {
  17507. this._init(dataset, epsilon, minPts, distanceFunction);
  17508. for (var pointId = 0, l = this.dataset.length; pointId < l; pointId++) {
  17509. if (this._processed[pointId] !== 1) {
  17510. this._processed[pointId] = 1;
  17511. this.clusters.push([pointId]);
  17512. var clusterId = this.clusters.length - 1;
  17513. this._orderedList.push(pointId);
  17514. var priorityQueue = new PriorityQueue(null, null, 'asc');
  17515. var neighbors = this._regionQuery(pointId);
  17516. // using priority queue assign elements to new cluster
  17517. if (this._distanceToCore(pointId) !== undefined) {
  17518. this._updateQueue(pointId, neighbors, priorityQueue);
  17519. this._expandCluster(clusterId, priorityQueue);
  17520. }
  17521. }
  17522. }
  17523. return this.clusters;
  17524. };
  17525. /**
  17526. * Generate reachability plot for all points
  17527. *
  17528. * @returns {array}
  17529. * @access public
  17530. */
  17531. OPTICS.prototype.getReachabilityPlot = function() {
  17532. var reachabilityPlot = [];
  17533. for (var i = 0, l = this._orderedList.length; i < l; i++) {
  17534. var pointId = this._orderedList[i];
  17535. var distance = this._reachability[pointId];
  17536. reachabilityPlot.push([pointId, distance]);
  17537. }
  17538. return reachabilityPlot;
  17539. };
  17540. /******************************************************************************/
  17541. // protected functions
  17542. /**
  17543. * Set object properties
  17544. *
  17545. * @param {Array} dataset
  17546. * @param {number} epsilon
  17547. * @param {number} minPts
  17548. * @param {function} distance
  17549. * @returns {undefined}
  17550. * @access protected
  17551. */
  17552. OPTICS.prototype._init = function(dataset, epsilon, minPts, distance) {
  17553. if (dataset) {
  17554. if (!(dataset instanceof Array)) {
  17555. throw Error('Dataset must be of type array, ' +
  17556. typeof dataset + ' given');
  17557. }
  17558. this.dataset = dataset;
  17559. this.clusters = [];
  17560. this._reachability = new Array(this.dataset.length);
  17561. this._processed = new Array(this.dataset.length);
  17562. this._coreDistance = 0;
  17563. this._orderedList = [];
  17564. }
  17565. if (epsilon) {
  17566. this.epsilon = epsilon;
  17567. }
  17568. if (minPts) {
  17569. this.minPts = minPts;
  17570. }
  17571. if (distance) {
  17572. this.distance = distance;
  17573. }
  17574. };
  17575. /**
  17576. * Update information in queue
  17577. *
  17578. * @param {number} pointId
  17579. * @param {Array} neighbors
  17580. * @param {PriorityQueue} queue
  17581. * @returns {undefined}
  17582. * @access protected
  17583. */
  17584. OPTICS.prototype._updateQueue = function(pointId, neighbors, queue) {
  17585. var self = this;
  17586. this._coreDistance = this._distanceToCore(pointId);
  17587. neighbors.forEach(function(pointId2) {
  17588. if (self._processed[pointId2] === undefined) {
  17589. var dist = self.distance(self.dataset[pointId], self.dataset[pointId2]);
  17590. var newReachableDistance = Math.max(self._coreDistance, dist);
  17591. if (self._reachability[pointId2] === undefined) {
  17592. self._reachability[pointId2] = newReachableDistance;
  17593. queue.insert(pointId2, newReachableDistance);
  17594. } else {
  17595. if (newReachableDistance < self._reachability[pointId2]) {
  17596. self._reachability[pointId2] = newReachableDistance;
  17597. queue.remove(pointId2);
  17598. queue.insert(pointId2, newReachableDistance);
  17599. }
  17600. }
  17601. }
  17602. });
  17603. };
  17604. /**
  17605. * Expand cluster
  17606. *
  17607. * @param {number} clusterId
  17608. * @param {PriorityQueue} queue
  17609. * @returns {undefined}
  17610. * @access protected
  17611. */
  17612. OPTICS.prototype._expandCluster = function(clusterId, queue) {
  17613. var queueElements = queue.getElements();
  17614. for (var p = 0, l = queueElements.length; p < l; p++) {
  17615. var pointId = queueElements[p];
  17616. if (this._processed[pointId] === undefined) {
  17617. var neighbors = this._regionQuery(pointId);
  17618. this._processed[pointId] = 1;
  17619. this.clusters[clusterId].push(pointId);
  17620. this._orderedList.push(pointId);
  17621. if (this._distanceToCore(pointId) !== undefined) {
  17622. this._updateQueue(pointId, neighbors, queue);
  17623. this._expandCluster(clusterId, queue);
  17624. }
  17625. }
  17626. }
  17627. };
  17628. /**
  17629. * Calculating distance to cluster core
  17630. *
  17631. * @param {number} pointId
  17632. * @returns {number}
  17633. * @access protected
  17634. */
  17635. OPTICS.prototype._distanceToCore = function(pointId) {
  17636. var l = this.epsilon;
  17637. for (var coreDistCand = 0; coreDistCand < l; coreDistCand++) {
  17638. var neighbors = this._regionQuery(pointId, coreDistCand);
  17639. if (neighbors.length >= this.minPts) {
  17640. return coreDistCand;
  17641. }
  17642. }
  17643. return;
  17644. };
  17645. /**
  17646. * Find all neighbors around given point
  17647. *
  17648. * @param {number} pointId
  17649. * @param {number} epsilon
  17650. * @returns {Array}
  17651. * @access protected
  17652. */
  17653. OPTICS.prototype._regionQuery = function(pointId, epsilon) {
  17654. epsilon = epsilon || this.epsilon;
  17655. var neighbors = [];
  17656. for (var id = 0, l = this.dataset.length; id < l; id++) {
  17657. if (this.distance(this.dataset[pointId], this.dataset[id]) < epsilon) {
  17658. neighbors.push(id);
  17659. }
  17660. }
  17661. return neighbors;
  17662. };
  17663. /******************************************************************************/
  17664. // helpers
  17665. /**
  17666. * Calculate euclidean distance in multidimensional space
  17667. *
  17668. * @param {Array} p
  17669. * @param {Array} q
  17670. * @returns {number}
  17671. * @access protected
  17672. */
  17673. OPTICS.prototype._euclideanDistance = function(p, q) {
  17674. var sum = 0;
  17675. var i = Math.min(p.length, q.length);
  17676. while (i--) {
  17677. sum += (p[i] - q[i]) * (p[i] - q[i]);
  17678. }
  17679. return Math.sqrt(sum);
  17680. };
  17681. if ('object' !== 'undefined' && module.exports) {
  17682. module.exports = OPTICS;
  17683. }
  17684. });
  17685. var lib = createCommonjsModule(function (module) {
  17686. if ('object' !== 'undefined' && module.exports) {
  17687. module.exports = {
  17688. DBSCAN: DBSCAN_1,
  17689. KMEANS: KMEANS_1,
  17690. OPTICS: OPTICS_1,
  17691. PriorityQueue: PriorityQueue_1
  17692. };
  17693. }
  17694. });
  17695. var lib_1 = lib.DBSCAN;
  17696. var lib_2 = lib.KMEANS;
  17697. var lib_3 = lib.OPTICS;
  17698. var lib_4 = lib.PriorityQueue;
  17699. /**
  17700. * Takes a set of {@link Point|points} and partition them into clusters according to {@link DBSCAN's|https://en.wikipedia.org/wiki/DBSCAN} data clustering algorithm.
  17701. *
  17702. * @name clustersDbscan
  17703. * @param {FeatureCollection<Point>} points to be clustered
  17704. * @param {number} maxDistance Maximum Distance between any point of the cluster to generate the clusters (kilometers only)
  17705. * @param {Object} [options={}] Optional parameters
  17706. * @param {string} [options.units=kilometers] in which `maxDistance` is expressed, can be degrees, radians, miles, or kilometers
  17707. * @param {number} [options.minPoints=3] Minimum number of points to generate a single cluster,
  17708. * points which do not meet this requirement will be classified as an 'edge' or 'noise'.
  17709. * @returns {FeatureCollection<Point>} Clustered Points with an additional two properties associated to each Feature:
  17710. * - {number} cluster - the associated clusterId
  17711. * - {string} dbscan - type of point it has been classified as ('core'|'edge'|'noise')
  17712. * @example
  17713. * // create random points with random z-values in their properties
  17714. * var points = turf.randomPoint(100, {bbox: [0, 30, 20, 50]});
  17715. * var maxDistance = 100;
  17716. * var clustered = turf.clustersDbscan(points, maxDistance);
  17717. *
  17718. * //addToMap
  17719. * var addToMap = [clustered];
  17720. */
  17721. function clustersDbscan(points$$1, maxDistance, options) {
  17722. // Optional parameters
  17723. options = options || {};
  17724. if (typeof options !== 'object') throw new Error('options is invalid');
  17725. var minPoints = options.minPoints;
  17726. var units = options.units;
  17727. // Input validation
  17728. collectionOf(points$$1, 'Point', 'Input must contain Points');
  17729. if (maxDistance === null || maxDistance === undefined) throw new Error('maxDistance is required');
  17730. if (!(Math.sign(maxDistance) > 0)) throw new Error('Invalid maxDistance');
  17731. if (!(minPoints === undefined || minPoints === null || Math.sign(minPoints) > 0)) throw new Error('Invalid minPoints');
  17732. // Clone points to prevent any mutations
  17733. points$$1 = clone(points$$1, true);
  17734. // Defaults
  17735. minPoints = minPoints || 3;
  17736. // create clustered ids
  17737. var dbscan = new lib.DBSCAN();
  17738. var clusteredIds = dbscan.run(coordAll(points$$1), convertLength(maxDistance, units), minPoints, distance);
  17739. // Tag points to Clusters ID
  17740. var clusterId = -1;
  17741. clusteredIds.forEach(function (clusterIds) {
  17742. clusterId++;
  17743. // assign cluster ids to input points
  17744. clusterIds.forEach(function (idx) {
  17745. var clusterPoint = points$$1.features[idx];
  17746. if (!clusterPoint.properties) clusterPoint.properties = {};
  17747. clusterPoint.properties.cluster = clusterId;
  17748. clusterPoint.properties.dbscan = 'core';
  17749. });
  17750. });
  17751. // handle noise points, if any
  17752. // edges points are tagged by DBSCAN as both 'noise' and 'cluster' as they can "reach" less than 'minPoints' number of points
  17753. dbscan.noise.forEach(function (noiseId) {
  17754. var noisePoint = points$$1.features[noiseId];
  17755. if (!noisePoint.properties) noisePoint.properties = {};
  17756. if (noisePoint.properties.cluster) noisePoint.properties.dbscan = 'edge';
  17757. else noisePoint.properties.dbscan = 'noise';
  17758. });
  17759. return points$$1;
  17760. }
  17761. var distance$2 = {
  17762. /**
  17763. * Euclidean distance
  17764. */
  17765. eudist: function eudist(v1, v2, sqrt) {
  17766. var len = v1.length;
  17767. var sum = 0;
  17768. for (var i = 0; i < len; i++) {
  17769. var d = (v1[i] || 0) - (v2[i] || 0);
  17770. sum += d * d;
  17771. }
  17772. // Square root not really needed
  17773. return sqrt ? Math.sqrt(sum) : sum;
  17774. },
  17775. mandist: function mandist(v1, v2, sqrt) {
  17776. var len = v1.length;
  17777. var sum = 0;
  17778. for (var i = 0; i < len; i++) {
  17779. sum += Math.abs((v1[i] || 0) - (v2[i] || 0));
  17780. }
  17781. // Square root not really needed
  17782. return sqrt ? Math.sqrt(sum) : sum;
  17783. },
  17784. /**
  17785. * Unidimensional distance
  17786. */
  17787. dist: function dist(v1, v2, sqrt) {
  17788. var d = Math.abs(v1 - v2);
  17789. return sqrt ? d : d * d;
  17790. }
  17791. };
  17792. var eudist$1 = distance$2.eudist;
  17793. var dist$1 = distance$2.dist;
  17794. var kinit = {
  17795. kmrand: function kmrand(data, k) {
  17796. var map = {},
  17797. ks = [],
  17798. t = k << 2;
  17799. var len = data.length;
  17800. var multi = data[0].length > 0;
  17801. while (ks.length < k && t-- > 0) {
  17802. var d = data[Math.floor(Math.random() * len)];
  17803. var key = multi ? d.join("_") : "" + d;
  17804. if (!map[key]) {
  17805. map[key] = true;
  17806. ks.push(d);
  17807. }
  17808. }
  17809. if (ks.length < k) throw new Error("Error initializating clusters");else return ks;
  17810. },
  17811. /**
  17812. * K-means++ initial centroid selection
  17813. */
  17814. kmpp: function kmpp(data, k) {
  17815. var distance = data[0].length ? eudist$1 : dist$1;
  17816. var ks = [],
  17817. len = data.length;
  17818. var multi = data[0].length > 0;
  17819. var c = data[Math.floor(Math.random() * len)];
  17820. var key = multi ? c.join("_") : "" + c;
  17821. ks.push(c);
  17822. while (ks.length < k) {
  17823. // Min Distances between current centroids and data points
  17824. var dists = [],
  17825. lk = ks.length;
  17826. var dsum = 0,
  17827. prs = [];
  17828. for (var i = 0; i < len; i++) {
  17829. var min = Infinity;
  17830. for (var j = 0; j < lk; j++) {
  17831. var _dist = distance(data[i], ks[j]);
  17832. if (_dist <= min) min = _dist;
  17833. }
  17834. dists[i] = min;
  17835. }
  17836. // Sum all min distances
  17837. for (var _i = 0; _i < len; _i++) {
  17838. dsum += dists[_i];
  17839. }
  17840. // Probabilities and cummulative prob (cumsum)
  17841. for (var _i2 = 0; _i2 < len; _i2++) {
  17842. prs[_i2] = { i: _i2, v: data[_i2], pr: dists[_i2] / dsum, cs: 0 };
  17843. }
  17844. // Sort Probabilities
  17845. prs.sort(function (a, b) {
  17846. return a.pr - b.pr;
  17847. });
  17848. // Cummulative Probabilities
  17849. prs[0].cs = prs[0].pr;
  17850. for (var _i3 = 1; _i3 < len; _i3++) {
  17851. prs[_i3].cs = prs[_i3 - 1].cs + prs[_i3].pr;
  17852. }
  17853. // Randomize
  17854. var rnd = Math.random();
  17855. // Gets only the items whose cumsum >= rnd
  17856. var idx = 0;
  17857. while (idx < len - 1 && prs[idx++].cs < rnd) {}
  17858. ks.push(prs[idx - 1].v);
  17859. /*
  17860. let done = false;
  17861. while(!done) {
  17862. // this is our new centroid
  17863. c = prs[idx-1].v
  17864. key = multi? c.join("_") : `${c}`;
  17865. if(!map[key]) {
  17866. map[key] = true;
  17867. ks.push(c);
  17868. done = true;
  17869. }
  17870. else {
  17871. idx++;
  17872. }
  17873. }
  17874. */
  17875. }
  17876. return ks;
  17877. }
  17878. };
  17879. /*jshint esversion: 6 */
  17880. var eudist = distance$2.eudist;
  17881. var kmrand = kinit.kmrand;
  17882. var kmpp = kinit.kmpp;
  17883. var MAX = 10000;
  17884. /**
  17885. * Inits an array with values
  17886. */
  17887. function init(len, val, v) {
  17888. v = v || [];
  17889. for (var i = 0; i < len; i++) {
  17890. v[i] = val;
  17891. }return v;
  17892. }
  17893. function skmeans(data, k, initial, maxit) {
  17894. var ks = [],
  17895. old = [],
  17896. idxs = [],
  17897. dist = [];
  17898. var conv = false,
  17899. it = maxit || MAX;
  17900. var len = data.length,
  17901. vlen = data[0].length,
  17902. multi = vlen > 0;
  17903. var count = [];
  17904. if (!initial) {
  17905. var _idxs = {};
  17906. while (ks.length < k) {
  17907. var idx = Math.floor(Math.random() * len);
  17908. if (!_idxs[idx]) {
  17909. _idxs[idx] = true;
  17910. ks.push(data[idx]);
  17911. }
  17912. }
  17913. } else if (initial == "kmrand") {
  17914. ks = kmrand(data, k);
  17915. } else if (initial == "kmpp") {
  17916. ks = kmpp(data, k);
  17917. } else {
  17918. ks = initial;
  17919. }
  17920. do {
  17921. // Reset k count
  17922. init(k, 0, count);
  17923. // For each value in data, find the nearest centroid
  17924. for (var i = 0; i < len; i++) {
  17925. var min = Infinity,
  17926. _idx = 0;
  17927. for (var j = 0; j < k; j++) {
  17928. // Multidimensional or unidimensional
  17929. var dist = multi ? eudist(data[i], ks[j]) : Math.abs(data[i] - ks[j]);
  17930. if (dist <= min) {
  17931. min = dist;
  17932. _idx = j;
  17933. }
  17934. }
  17935. idxs[i] = _idx; // Index of the selected centroid for that value
  17936. count[_idx]++; // Number of values for this centroid
  17937. }
  17938. // Recalculate centroids
  17939. var sum = [],
  17940. old = [];
  17941. for (var _j = 0; _j < k; _j++) {
  17942. // Multidimensional or unidimensional
  17943. sum[_j] = multi ? init(vlen, 0, sum[_j]) : 0;
  17944. old[_j] = ks[_j];
  17945. }
  17946. // If multidimensional
  17947. if (multi) {
  17948. for (var _j2 = 0; _j2 < k; _j2++) {
  17949. ks[_j2] = [];
  17950. } // Sum values and count for each centroid
  17951. for (var _i = 0; _i < len; _i++) {
  17952. var _idx2 = idxs[_i],
  17953. // Centroid for that item
  17954. vsum = sum[_idx2],
  17955. // Sum values for this centroid
  17956. vect = data[_i]; // Current vector
  17957. // Accumulate value on the centroid for current vector
  17958. for (var h = 0; h < vlen; h++) {
  17959. vsum[h] += vect[h];
  17960. }
  17961. }
  17962. // Calculate the average for each centroid
  17963. conv = true;
  17964. for (var _j3 = 0; _j3 < k; _j3++) {
  17965. var ksj = ks[_j3],
  17966. // Current centroid
  17967. sumj = sum[_j3],
  17968. // Accumulated centroid values
  17969. oldj = old[_j3],
  17970. // Old centroid value
  17971. cj = count[_j3]; // Number of elements for this centroid
  17972. // New average
  17973. for (var _h = 0; _h < vlen; _h++) {
  17974. ksj[_h] = sumj[_h] / cj || 0; // New centroid
  17975. }
  17976. // Find if centroids have moved
  17977. if (conv) {
  17978. for (var _h2 = 0; _h2 < vlen; _h2++) {
  17979. if (oldj[_h2] != ksj[_h2]) {
  17980. conv = false;
  17981. break;
  17982. }
  17983. }
  17984. }
  17985. }
  17986. }
  17987. // If unidimensional
  17988. else {
  17989. // Sum values and count for each centroid
  17990. for (var _i2 = 0; _i2 < len; _i2++) {
  17991. var _idx3 = idxs[_i2];
  17992. sum[_idx3] += data[_i2];
  17993. }
  17994. // Calculate the average for each centroid
  17995. for (var _j4 = 0; _j4 < k; _j4++) {
  17996. ks[_j4] = sum[_j4] / count[_j4] || 0; // New centroid
  17997. }
  17998. // Find if centroids have moved
  17999. conv = true;
  18000. for (var _j5 = 0; _j5 < k; _j5++) {
  18001. if (old[_j5] != ks[_j5]) {
  18002. conv = false;
  18003. break;
  18004. }
  18005. }
  18006. }
  18007. conv = conv || --it <= 0;
  18008. } while (!conv);
  18009. return {
  18010. it: MAX - it,
  18011. k: k,
  18012. idxs: idxs,
  18013. centroids: ks
  18014. };
  18015. }
  18016. var main = skmeans;
  18017. /**
  18018. * Takes a set of {@link Point|points} and partition them into clusters using the k-mean .
  18019. * It uses the [k-means algorithm](https://en.wikipedia.org/wiki/K-means_clustering)
  18020. *
  18021. * @name clustersKmeans
  18022. * @param {FeatureCollection<Point>} points to be clustered
  18023. * @param {Object} [options={}] Optional parameters
  18024. * @param {number} [options.numberOfClusters=Math.sqrt(numberOfPoints/2)] numberOfClusters that will be generated
  18025. * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
  18026. * @returns {FeatureCollection<Point>} Clustered Points with an additional two properties associated to each Feature:
  18027. * - {number} cluster - the associated clusterId
  18028. * - {[number, number]} centroid - Centroid of the cluster [Longitude, Latitude]
  18029. * @example
  18030. * // create random points with random z-values in their properties
  18031. * var points = turf.randomPoint(100, {bbox: [0, 30, 20, 50]});
  18032. * var options = {numberOfClusters: 7};
  18033. * var clustered = turf.clustersKmeans(points, options);
  18034. *
  18035. * //addToMap
  18036. * var addToMap = [clustered];
  18037. */
  18038. function clustersKmeans(points, options) {
  18039. // Optional parameters
  18040. options = options || {};
  18041. if (typeof options !== 'object') throw new Error('options is invalid');
  18042. var numberOfClusters = options.numberOfClusters;
  18043. var mutate = options.mutate;
  18044. // Input validation
  18045. collectionOf(points, 'Point', 'Input must contain Points');
  18046. // Default Params
  18047. var count = points.features.length;
  18048. numberOfClusters = numberOfClusters || Math.round(Math.sqrt(count / 2));
  18049. // numberOfClusters can't be greater than the number of points
  18050. // fallbacks to count
  18051. if (numberOfClusters > count) numberOfClusters = count;
  18052. // Clone points to prevent any mutations (enabled by default)
  18053. if (mutate === false || mutate === undefined) points = clone(points, true);
  18054. // collect points coordinates
  18055. var data = coordAll(points);
  18056. // create seed to avoid skmeans to drift
  18057. var initialCentroids = data.slice(0, numberOfClusters);
  18058. // create skmeans clusters
  18059. var skmeansResult = main(data, numberOfClusters, initialCentroids);
  18060. // store centroids {clusterId: [number, number]}
  18061. var centroids = {};
  18062. skmeansResult.centroids.forEach(function (coord, idx) {
  18063. centroids[idx] = coord;
  18064. });
  18065. // add associated cluster number
  18066. featureEach(points, function (point, index) {
  18067. var clusterId = skmeansResult.idxs[index];
  18068. point.properties.cluster = clusterId;
  18069. point.properties.centroid = centroids[clusterId];
  18070. });
  18071. return points;
  18072. }
  18073. /**
  18074. * Boolean-Parallel returns True if each segment of `line1` is parallel to the correspondent segment of `line2`
  18075. *
  18076. * @name booleanParallel
  18077. * @param {Geometry|Feature<LineString>} line1 GeoJSON Feature or Geometry
  18078. * @param {Geometry|Feature<LineString>} line2 GeoJSON Feature or Geometry
  18079. * @returns {boolean} true/false if the lines are parallel
  18080. * @example
  18081. * var line1 = turf.lineString([[0, 0], [0, 1]]);
  18082. * var line2 = turf.lineString([[1, 0], [1, 1]]);
  18083. *
  18084. * turf.booleanParallel(line1, line2);
  18085. * //=true
  18086. */
  18087. function booleanParallel(line1, line2) {
  18088. // validation
  18089. if (!line1) throw new Error('line1 is required');
  18090. if (!line2) throw new Error('line2 is required');
  18091. var type1 = getType$1(line1, 'line1');
  18092. if (type1 !== 'LineString') throw new Error('line1 must be a LineString');
  18093. var type2 = getType$1(line2, 'line2');
  18094. if (type2 !== 'LineString') throw new Error('line2 must be a LineString');
  18095. var segments1 = lineSegment(cleanCoords(line1)).features;
  18096. var segments2 = lineSegment(cleanCoords(line2)).features;
  18097. for (var i = 0; i < segments1.length; i++) {
  18098. var segment1 = segments1[i].geometry.coordinates;
  18099. if (!segments2[i]) break;
  18100. var segment2 = segments2[i].geometry.coordinates;
  18101. if (!isParallel$1(segment1, segment2)) return false;
  18102. }
  18103. return true;
  18104. }
  18105. /**
  18106. * Compares slopes and return result
  18107. *
  18108. * @private
  18109. * @param {Geometry|Feature<LineString>} segment1 Geometry or Feature
  18110. * @param {Geometry|Feature<LineString>} segment2 Geometry or Feature
  18111. * @returns {boolean} if slopes are equal
  18112. */
  18113. function isParallel$1(segment1, segment2) {
  18114. var slope1 = bearingToAzimuth(rhumbBearing(segment1[0], segment1[1]));
  18115. var slope2 = bearingToAzimuth(rhumbBearing(segment2[0], segment2[1]));
  18116. return slope1 === slope2;
  18117. }
  18118. /**
  18119. * Returns Feature's type
  18120. *
  18121. * @private
  18122. * @param {Geometry|Feature<any>} geojson Geometry or Feature
  18123. * @param {string} name of the variable
  18124. * @returns {string} Feature's type
  18125. */
  18126. function getType$1(geojson, name) {
  18127. if (geojson.geometry && geojson.geometry.type) return geojson.geometry.type;
  18128. if (geojson.type) return geojson.type; // if GeoJSON geometry
  18129. throw new Error('Invalid GeoJSON object for ' + name);
  18130. }
  18131. // javascript-astar 0.4.1
  18132. // http://github.com/bgrins/javascript-astar
  18133. // Freely distributable under the MIT License.
  18134. // Implements the astar search algorithm in javascript using a Binary Heap.
  18135. // Includes Binary Heap (with modifications) from Marijn Haverbeke.
  18136. // http://eloquentjavascript.net/appendix2.html
  18137. function pathTo(node) {
  18138. var curr = node,
  18139. path = [];
  18140. while (curr.parent) {
  18141. path.unshift(curr);
  18142. curr = curr.parent;
  18143. }
  18144. return path;
  18145. }
  18146. function getHeap() {
  18147. return new BinaryHeap(function (node) {
  18148. return node.f;
  18149. });
  18150. }
  18151. /**
  18152. * Astar
  18153. * @private
  18154. */
  18155. var astar = {
  18156. /**
  18157. * Perform an A* Search on a graph given a start and end node.
  18158. *
  18159. * @private
  18160. * @memberof astar
  18161. * @param {Graph} graph Graph
  18162. * @param {GridNode} start Start
  18163. * @param {GridNode} end End
  18164. * @param {Object} [options] Options
  18165. * @param {bool} [options.closest] Specifies whether to return the path to the closest node if the target is unreachable.
  18166. * @param {Function} [options.heuristic] Heuristic function (see astar.heuristics).
  18167. * @returns {Object} Search
  18168. */
  18169. search: function (graph, start, end, options) {
  18170. graph.cleanDirty();
  18171. options = options || {};
  18172. var heuristic = options.heuristic || astar.heuristics.manhattan,
  18173. closest = options.closest || false;
  18174. var openHeap = getHeap(),
  18175. closestNode = start; // set the start node to be the closest if required
  18176. start.h = heuristic(start, end);
  18177. openHeap.push(start);
  18178. while (openHeap.size() > 0) {
  18179. // Grab the lowest f(x) to process next. Heap keeps this sorted for us.
  18180. var currentNode = openHeap.pop();
  18181. // End case -- result has been found, return the traced path.
  18182. if (currentNode === end) {
  18183. return pathTo(currentNode);
  18184. }
  18185. // Normal case -- move currentNode from open to closed, process each of its neighbors.
  18186. currentNode.closed = true;
  18187. // Find all neighbors for the current node.
  18188. var neighbors = graph.neighbors(currentNode);
  18189. for (var i = 0, il = neighbors.length; i < il; ++i) {
  18190. var neighbor = neighbors[i];
  18191. if (neighbor.closed || neighbor.isWall()) {
  18192. // Not a valid node to process, skip to next neighbor.
  18193. continue;
  18194. }
  18195. // The g score is the shortest distance from start to current node.
  18196. // We need to check if the path we have arrived at this neighbor is the shortest one we have seen yet.
  18197. var gScore = currentNode.g + neighbor.getCost(currentNode),
  18198. beenVisited = neighbor.visited;
  18199. if (!beenVisited || gScore < neighbor.g) {
  18200. // Found an optimal (so far) path to this node. Take score for node to see how good it is.
  18201. neighbor.visited = true;
  18202. neighbor.parent = currentNode;
  18203. neighbor.h = neighbor.h || heuristic(neighbor, end);
  18204. neighbor.g = gScore;
  18205. neighbor.f = neighbor.g + neighbor.h;
  18206. graph.markDirty(neighbor);
  18207. if (closest) {
  18208. // If the neighbour is closer than the current closestNode or if it's equally close but has
  18209. // a cheaper path than the current closest node then it becomes the closest node
  18210. if (neighbor.h < closestNode.h || (neighbor.h === closestNode.h && neighbor.g < closestNode.g)) {
  18211. closestNode = neighbor;
  18212. }
  18213. }
  18214. if (!beenVisited) {
  18215. // Pushing to heap will put it in proper place based on the 'f' value.
  18216. openHeap.push(neighbor);
  18217. } else {
  18218. // Already seen the node, but since it has been rescored we need to reorder it in the heap
  18219. openHeap.rescoreElement(neighbor);
  18220. }
  18221. }
  18222. }
  18223. }
  18224. if (closest) {
  18225. return pathTo(closestNode);
  18226. }
  18227. // No result was found - empty array signifies failure to find path.
  18228. return [];
  18229. },
  18230. // See list of heuristics: http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html
  18231. heuristics: {
  18232. manhattan: function (pos0, pos1) {
  18233. var d1 = Math.abs(pos1.x - pos0.x);
  18234. var d2 = Math.abs(pos1.y - pos0.y);
  18235. return d1 + d2;
  18236. },
  18237. diagonal: function (pos0, pos1) {
  18238. var D = 1;
  18239. var D2 = Math.sqrt(2);
  18240. var d1 = Math.abs(pos1.x - pos0.x);
  18241. var d2 = Math.abs(pos1.y - pos0.y);
  18242. return (D * (d1 + d2)) + ((D2 - (2 * D)) * Math.min(d1, d2));
  18243. }
  18244. },
  18245. cleanNode: function (node) {
  18246. node.f = 0;
  18247. node.g = 0;
  18248. node.h = 0;
  18249. node.visited = false;
  18250. node.closed = false;
  18251. node.parent = null;
  18252. }
  18253. };
  18254. /**
  18255. * A graph memory structure
  18256. *
  18257. * @private
  18258. * @param {Array} gridIn 2D array of input weights
  18259. * @param {Object} [options] Options
  18260. * @param {boolean} [options.diagonal] Specifies whether diagonal moves are allowed
  18261. * @returns {void} Graph
  18262. */
  18263. function Graph$1(gridIn, options) {
  18264. options = options || {};
  18265. this.nodes = [];
  18266. this.diagonal = !!options.diagonal;
  18267. this.grid = [];
  18268. for (var x = 0; x < gridIn.length; x++) {
  18269. this.grid[x] = [];
  18270. for (var y = 0, row = gridIn[x]; y < row.length; y++) {
  18271. var node = new GridNode(x, y, row[y]);
  18272. this.grid[x][y] = node;
  18273. this.nodes.push(node);
  18274. }
  18275. }
  18276. this.init();
  18277. }
  18278. Graph$1.prototype.init = function () {
  18279. this.dirtyNodes = [];
  18280. for (var i = 0; i < this.nodes.length; i++) {
  18281. astar.cleanNode(this.nodes[i]);
  18282. }
  18283. };
  18284. Graph$1.prototype.cleanDirty = function () {
  18285. for (var i = 0; i < this.dirtyNodes.length; i++) {
  18286. astar.cleanNode(this.dirtyNodes[i]);
  18287. }
  18288. this.dirtyNodes = [];
  18289. };
  18290. Graph$1.prototype.markDirty = function (node) {
  18291. this.dirtyNodes.push(node);
  18292. };
  18293. Graph$1.prototype.neighbors = function (node) {
  18294. var ret = [],
  18295. x = node.x,
  18296. y = node.y,
  18297. grid = this.grid;
  18298. // West
  18299. if (grid[x - 1] && grid[x - 1][y]) {
  18300. ret.push(grid[x - 1][y]);
  18301. }
  18302. // East
  18303. if (grid[x + 1] && grid[x + 1][y]) {
  18304. ret.push(grid[x + 1][y]);
  18305. }
  18306. // South
  18307. if (grid[x] && grid[x][y - 1]) {
  18308. ret.push(grid[x][y - 1]);
  18309. }
  18310. // North
  18311. if (grid[x] && grid[x][y + 1]) {
  18312. ret.push(grid[x][y + 1]);
  18313. }
  18314. if (this.diagonal) {
  18315. // Southwest
  18316. if (grid[x - 1] && grid[x - 1][y - 1]) {
  18317. ret.push(grid[x - 1][y - 1]);
  18318. }
  18319. // Southeast
  18320. if (grid[x + 1] && grid[x + 1][y - 1]) {
  18321. ret.push(grid[x + 1][y - 1]);
  18322. }
  18323. // Northwest
  18324. if (grid[x - 1] && grid[x - 1][y + 1]) {
  18325. ret.push(grid[x - 1][y + 1]);
  18326. }
  18327. // Northeast
  18328. if (grid[x + 1] && grid[x + 1][y + 1]) {
  18329. ret.push(grid[x + 1][y + 1]);
  18330. }
  18331. }
  18332. return ret;
  18333. };
  18334. Graph$1.prototype.toString = function () {
  18335. var graphString = [],
  18336. nodes = this.grid, // when using grid
  18337. rowDebug, row, y, l;
  18338. for (var x = 0, len = nodes.length; x < len; x++) {
  18339. rowDebug = [];
  18340. row = nodes[x];
  18341. for (y = 0, l = row.length; y < l; y++) {
  18342. rowDebug.push(row[y].weight);
  18343. }
  18344. graphString.push(rowDebug.join(' '));
  18345. }
  18346. return graphString.join('\n');
  18347. };
  18348. function GridNode(x, y, weight) {
  18349. this.x = x;
  18350. this.y = y;
  18351. this.weight = weight;
  18352. }
  18353. GridNode.prototype.toString = function () {
  18354. return '[' + this.x + ' ' + this.y + ']';
  18355. };
  18356. GridNode.prototype.getCost = function (fromNeighbor) {
  18357. // Take diagonal weight into consideration.
  18358. if (fromNeighbor && fromNeighbor.x !== this.x && fromNeighbor.y !== this.y) {
  18359. return this.weight * 1.41421;
  18360. }
  18361. return this.weight;
  18362. };
  18363. GridNode.prototype.isWall = function () {
  18364. return this.weight === 0;
  18365. };
  18366. function BinaryHeap(scoreFunction) {
  18367. this.content = [];
  18368. this.scoreFunction = scoreFunction;
  18369. }
  18370. BinaryHeap.prototype = {
  18371. push: function (element) {
  18372. // Add the new element to the end of the array.
  18373. this.content.push(element);
  18374. // Allow it to sink down.
  18375. this.sinkDown(this.content.length - 1);
  18376. },
  18377. pop: function () {
  18378. // Store the first element so we can return it later.
  18379. var result = this.content[0];
  18380. // Get the element at the end of the array.
  18381. var end = this.content.pop();
  18382. // If there are any elements left, put the end element at the
  18383. // start, and let it bubble up.
  18384. if (this.content.length > 0) {
  18385. this.content[0] = end;
  18386. this.bubbleUp(0);
  18387. }
  18388. return result;
  18389. },
  18390. remove: function (node) {
  18391. var i = this.content.indexOf(node);
  18392. // When it is found, the process seen in 'pop' is repeated
  18393. // to fill up the hole.
  18394. var end = this.content.pop();
  18395. if (i !== this.content.length - 1) {
  18396. this.content[i] = end;
  18397. if (this.scoreFunction(end) < this.scoreFunction(node)) {
  18398. this.sinkDown(i);
  18399. } else {
  18400. this.bubbleUp(i);
  18401. }
  18402. }
  18403. },
  18404. size: function () {
  18405. return this.content.length;
  18406. },
  18407. rescoreElement: function (node) {
  18408. this.sinkDown(this.content.indexOf(node));
  18409. },
  18410. sinkDown: function (n) {
  18411. // Fetch the element that has to be sunk.
  18412. var element = this.content[n];
  18413. // When at 0, an element can not sink any further.
  18414. while (n > 0) {
  18415. // Compute the parent element's index, and fetch it.
  18416. var parentN = ((n + 1) >> 1) - 1,
  18417. parent = this.content[parentN];
  18418. // Swap the elements if the parent is greater.
  18419. if (this.scoreFunction(element) < this.scoreFunction(parent)) {
  18420. this.content[parentN] = element;
  18421. this.content[n] = parent;
  18422. // Update 'n' to continue at the new position.
  18423. n = parentN;
  18424. // Found a parent that is less, no need to sink any further.
  18425. } else {
  18426. break;
  18427. }
  18428. }
  18429. },
  18430. bubbleUp: function (n) {
  18431. // Look up the target element and its score.
  18432. var length = this.content.length,
  18433. element = this.content[n],
  18434. elemScore = this.scoreFunction(element);
  18435. while (true) {
  18436. // Compute the indices of the child elements.
  18437. var child2N = (n + 1) << 1,
  18438. child1N = child2N - 1;
  18439. // This is used to store the new position of the element, if any.
  18440. var swap = null,
  18441. child1Score;
  18442. // If the first child exists (is inside the array)...
  18443. if (child1N < length) {
  18444. // Look it up and compute its score.
  18445. var child1 = this.content[child1N];
  18446. child1Score = this.scoreFunction(child1);
  18447. // If the score is less than our element's, we need to swap.
  18448. if (child1Score < elemScore) {
  18449. swap = child1N;
  18450. }
  18451. }
  18452. // Do the same checks for the other child.
  18453. if (child2N < length) {
  18454. var child2 = this.content[child2N],
  18455. child2Score = this.scoreFunction(child2);
  18456. if (child2Score < (swap === null ? elemScore : child1Score)) {
  18457. swap = child2N;
  18458. }
  18459. }
  18460. // If the element needs to be moved, swap it, and continue.
  18461. if (swap !== null) {
  18462. this.content[n] = this.content[swap];
  18463. this.content[swap] = element;
  18464. n = swap;
  18465. // Otherwise, we are done.
  18466. } else {
  18467. break;
  18468. }
  18469. }
  18470. }
  18471. };
  18472. /**
  18473. * Returns the shortest {@link LineString|path} from {@link Point|start} to {@link Point|end} without colliding with
  18474. * any {@link Feature} in {@link FeatureCollection<Polygon>| obstacles}
  18475. *
  18476. * @name shortestPath
  18477. * @param {Coord} start point
  18478. * @param {Coord} end point
  18479. * @param {Object} [options={}] optional parameters
  18480. * @param {Geometry|Feature|FeatureCollection<Polygon>} [options.obstacles] areas which path cannot travel
  18481. * @param {number} [options.minDistance] minimum distance between shortest path and obstacles
  18482. * @param {string} [options.units='kilometers'] unit in which resolution & minimum distance will be expressed in; it can be degrees, radians, miles, kilometers, ...
  18483. * @param {number} [options.resolution=100] distance between matrix points on which the path will be calculated
  18484. * @returns {Feature<LineString>} shortest path between start and end
  18485. * @example
  18486. * var start = [-5, -6];
  18487. * var end = [9, -6];
  18488. * var options = {
  18489. * obstacles: turf.polygon([[[0, -7], [5, -7], [5, -3], [0, -3], [0, -7]]])
  18490. * };
  18491. *
  18492. * var path = turf.shortestPath(start, end, options);
  18493. *
  18494. * //addToMap
  18495. * var addToMap = [start, end, options.obstacles, path];
  18496. */
  18497. function shortestPath(start, end, options) {
  18498. // Optional parameters
  18499. options = options || {};
  18500. if (!isObject(options)) throw new Error('options is invalid');
  18501. var resolution = options.resolution;
  18502. var minDistance = options.minDistance;
  18503. var obstacles = options.obstacles || featureCollection([]);
  18504. // validation
  18505. if (!start) throw new Error('start is required');
  18506. if (!end) throw new Error('end is required');
  18507. if (resolution && !isNumber(resolution) || resolution <= 0) throw new Error('options.resolution must be a number, greater than 0');
  18508. if (minDistance) throw new Error('options.minDistance is not yet implemented');
  18509. // Normalize Inputs
  18510. var startCoord = getCoord(start);
  18511. var endCoord = getCoord(end);
  18512. start = point(startCoord);
  18513. end = point(endCoord);
  18514. // Handle obstacles
  18515. switch (getType(obstacles)) {
  18516. case 'FeatureCollection':
  18517. if (obstacles.features.length === 0) return lineString([startCoord, endCoord]);
  18518. break;
  18519. case 'Polygon':
  18520. obstacles = featureCollection([feature(getGeom(obstacles))]);
  18521. break;
  18522. default:
  18523. throw new Error('invalid obstacles');
  18524. }
  18525. // define path grid area
  18526. var collection = obstacles;
  18527. collection.features.push(start);
  18528. collection.features.push(end);
  18529. var box = bbox(transformScale(bboxPolygon(bbox(collection)), 1.15)); // extend 15%
  18530. if (!resolution) {
  18531. var width = distance([box[0], box[1]], [box[2], box[1]], options);
  18532. resolution = width / 100;
  18533. }
  18534. collection.features.pop();
  18535. collection.features.pop();
  18536. var west = box[0];
  18537. var south = box[1];
  18538. var east = box[2];
  18539. var north = box[3];
  18540. var xFraction = resolution / (distance([west, south], [east, south], options));
  18541. var cellWidth = xFraction * (east - west);
  18542. var yFraction = resolution / (distance([west, south], [west, north], options));
  18543. var cellHeight = yFraction * (north - south);
  18544. var bboxHorizontalSide = (east - west);
  18545. var bboxVerticalSide = (north - south);
  18546. var columns = Math.floor(bboxHorizontalSide / cellWidth);
  18547. var rows = Math.floor(bboxVerticalSide / cellHeight);
  18548. // adjust origin of the grid
  18549. var deltaX = (bboxHorizontalSide - columns * cellWidth) / 2;
  18550. var deltaY = (bboxVerticalSide - rows * cellHeight) / 2;
  18551. // loop through points only once to speed up process
  18552. // define matrix grid for A-star algorithm
  18553. var pointMatrix = [];
  18554. var matrix = [];
  18555. var closestToStart = [];
  18556. var closestToEnd = [];
  18557. var minDistStart = Infinity;
  18558. var minDistEnd = Infinity;
  18559. var currentY = north - deltaY;
  18560. var r = 0;
  18561. while (currentY >= south) {
  18562. // var currentY = south + deltaY;
  18563. var matrixRow = [];
  18564. var pointMatrixRow = [];
  18565. var currentX = west + deltaX;
  18566. var c = 0;
  18567. while (currentX <= east) {
  18568. var pt = point([currentX, currentY]);
  18569. var isInsideObstacle = isInside$1(pt, obstacles);
  18570. // feed obstacles matrix
  18571. matrixRow.push(isInsideObstacle ? 0 : 1); // with javascript-astar
  18572. // matrixRow.push(isInsideObstacle ? 1 : 0); // with astar-andrea
  18573. // map point's coords
  18574. pointMatrixRow.push(currentX + '|' + currentY);
  18575. // set closest points
  18576. var distStart = distance(pt, start);
  18577. // if (distStart < minDistStart) {
  18578. if (!isInsideObstacle && distStart < minDistStart) {
  18579. minDistStart = distStart;
  18580. closestToStart = {x: c, y: r};
  18581. }
  18582. var distEnd = distance(pt, end);
  18583. // if (distEnd < minDistEnd) {
  18584. if (!isInsideObstacle && distEnd < minDistEnd) {
  18585. minDistEnd = distEnd;
  18586. closestToEnd = {x: c, y: r};
  18587. }
  18588. currentX += cellWidth;
  18589. c++;
  18590. }
  18591. matrix.push(matrixRow);
  18592. pointMatrix.push(pointMatrixRow);
  18593. currentY -= cellHeight;
  18594. r++;
  18595. }
  18596. // find path on matrix grid
  18597. // javascript-astar ----------------------
  18598. var graph = new Graph$1(matrix, {diagonal: true});
  18599. var startOnMatrix = graph.grid[closestToStart.y][closestToStart.x];
  18600. var endOnMatrix = graph.grid[closestToEnd.y][closestToEnd.x];
  18601. var result = astar.search(graph, startOnMatrix, endOnMatrix);
  18602. var path = [startCoord];
  18603. result.forEach(function (coord) {
  18604. var coords = pointMatrix[coord.x][coord.y].split('|');
  18605. path.push([+coords[0], +coords[1]]); // make sure coords are numbers
  18606. });
  18607. path.push(endCoord);
  18608. // ---------------------------------------
  18609. // astar-andrea ------------------------
  18610. // var result = aStar(matrix, [closestToStart.x, closestToStart.y], [closestToEnd.x, closestToEnd.y], 'DiagonalFree');
  18611. // var path = [start.geometry.coordinates];
  18612. // result.forEach(function (coord) {
  18613. // var coords = pointMatrix[coord[1]][coord[0]].split('|');
  18614. // path.push([+coords[0], +coords[1]]); // make sure coords are numbers
  18615. // });
  18616. // path.push(end.geometry.coordinates);
  18617. // ---------------------------------------
  18618. return cleanCoords(lineString(path));
  18619. }
  18620. /**
  18621. * Checks if Point is inside any of the Polygons
  18622. *
  18623. * @private
  18624. * @param {Feature<Point>} pt to check
  18625. * @param {FeatureCollection<Polygon>} polygons features
  18626. * @returns {boolean} if inside or not
  18627. */
  18628. function isInside$1(pt, polygons$$1) {
  18629. for (var i = 0; i < polygons$$1.features.length; i++) {
  18630. if (booleanPointInPolygon(pt, polygons$$1.features[i])) {
  18631. return true;
  18632. }
  18633. }
  18634. return false;
  18635. }
  18636. var constant = function(x) {
  18637. return function() {
  18638. return x;
  18639. };
  18640. };
  18641. function x(d) {
  18642. return d[0];
  18643. }
  18644. function y(d) {
  18645. return d[1];
  18646. }
  18647. function RedBlackTree() {
  18648. this._ = null; // root node
  18649. }
  18650. function RedBlackNode(node) {
  18651. node.U = // parent node
  18652. node.C = // color - true for red, false for black
  18653. node.L = // left node
  18654. node.R = // right node
  18655. node.P = // previous node
  18656. node.N = null; // next node
  18657. }
  18658. RedBlackTree.prototype = {
  18659. constructor: RedBlackTree,
  18660. insert: function(after, node) {
  18661. var parent, grandpa, uncle;
  18662. if (after) {
  18663. node.P = after;
  18664. node.N = after.N;
  18665. if (after.N) after.N.P = node;
  18666. after.N = node;
  18667. if (after.R) {
  18668. after = after.R;
  18669. while (after.L) after = after.L;
  18670. after.L = node;
  18671. } else {
  18672. after.R = node;
  18673. }
  18674. parent = after;
  18675. } else if (this._) {
  18676. after = RedBlackFirst(this._);
  18677. node.P = null;
  18678. node.N = after;
  18679. after.P = after.L = node;
  18680. parent = after;
  18681. } else {
  18682. node.P = node.N = null;
  18683. this._ = node;
  18684. parent = null;
  18685. }
  18686. node.L = node.R = null;
  18687. node.U = parent;
  18688. node.C = true;
  18689. after = node;
  18690. while (parent && parent.C) {
  18691. grandpa = parent.U;
  18692. if (parent === grandpa.L) {
  18693. uncle = grandpa.R;
  18694. if (uncle && uncle.C) {
  18695. parent.C = uncle.C = false;
  18696. grandpa.C = true;
  18697. after = grandpa;
  18698. } else {
  18699. if (after === parent.R) {
  18700. RedBlackRotateLeft(this, parent);
  18701. after = parent;
  18702. parent = after.U;
  18703. }
  18704. parent.C = false;
  18705. grandpa.C = true;
  18706. RedBlackRotateRight(this, grandpa);
  18707. }
  18708. } else {
  18709. uncle = grandpa.L;
  18710. if (uncle && uncle.C) {
  18711. parent.C = uncle.C = false;
  18712. grandpa.C = true;
  18713. after = grandpa;
  18714. } else {
  18715. if (after === parent.L) {
  18716. RedBlackRotateRight(this, parent);
  18717. after = parent;
  18718. parent = after.U;
  18719. }
  18720. parent.C = false;
  18721. grandpa.C = true;
  18722. RedBlackRotateLeft(this, grandpa);
  18723. }
  18724. }
  18725. parent = after.U;
  18726. }
  18727. this._.C = false;
  18728. },
  18729. remove: function(node) {
  18730. if (node.N) node.N.P = node.P;
  18731. if (node.P) node.P.N = node.N;
  18732. node.N = node.P = null;
  18733. var parent = node.U,
  18734. sibling,
  18735. left = node.L,
  18736. right = node.R,
  18737. next,
  18738. red;
  18739. if (!left) next = right;
  18740. else if (!right) next = left;
  18741. else next = RedBlackFirst(right);
  18742. if (parent) {
  18743. if (parent.L === node) parent.L = next;
  18744. else parent.R = next;
  18745. } else {
  18746. this._ = next;
  18747. }
  18748. if (left && right) {
  18749. red = next.C;
  18750. next.C = node.C;
  18751. next.L = left;
  18752. left.U = next;
  18753. if (next !== right) {
  18754. parent = next.U;
  18755. next.U = node.U;
  18756. node = next.R;
  18757. parent.L = node;
  18758. next.R = right;
  18759. right.U = next;
  18760. } else {
  18761. next.U = parent;
  18762. parent = next;
  18763. node = next.R;
  18764. }
  18765. } else {
  18766. red = node.C;
  18767. node = next;
  18768. }
  18769. if (node) node.U = parent;
  18770. if (red) return;
  18771. if (node && node.C) { node.C = false; return; }
  18772. do {
  18773. if (node === this._) break;
  18774. if (node === parent.L) {
  18775. sibling = parent.R;
  18776. if (sibling.C) {
  18777. sibling.C = false;
  18778. parent.C = true;
  18779. RedBlackRotateLeft(this, parent);
  18780. sibling = parent.R;
  18781. }
  18782. if ((sibling.L && sibling.L.C)
  18783. || (sibling.R && sibling.R.C)) {
  18784. if (!sibling.R || !sibling.R.C) {
  18785. sibling.L.C = false;
  18786. sibling.C = true;
  18787. RedBlackRotateRight(this, sibling);
  18788. sibling = parent.R;
  18789. }
  18790. sibling.C = parent.C;
  18791. parent.C = sibling.R.C = false;
  18792. RedBlackRotateLeft(this, parent);
  18793. node = this._;
  18794. break;
  18795. }
  18796. } else {
  18797. sibling = parent.L;
  18798. if (sibling.C) {
  18799. sibling.C = false;
  18800. parent.C = true;
  18801. RedBlackRotateRight(this, parent);
  18802. sibling = parent.L;
  18803. }
  18804. if ((sibling.L && sibling.L.C)
  18805. || (sibling.R && sibling.R.C)) {
  18806. if (!sibling.L || !sibling.L.C) {
  18807. sibling.R.C = false;
  18808. sibling.C = true;
  18809. RedBlackRotateLeft(this, sibling);
  18810. sibling = parent.L;
  18811. }
  18812. sibling.C = parent.C;
  18813. parent.C = sibling.L.C = false;
  18814. RedBlackRotateRight(this, parent);
  18815. node = this._;
  18816. break;
  18817. }
  18818. }
  18819. sibling.C = true;
  18820. node = parent;
  18821. parent = parent.U;
  18822. } while (!node.C);
  18823. if (node) node.C = false;
  18824. }
  18825. };
  18826. function RedBlackRotateLeft(tree, node) {
  18827. var p = node,
  18828. q = node.R,
  18829. parent = p.U;
  18830. if (parent) {
  18831. if (parent.L === p) parent.L = q;
  18832. else parent.R = q;
  18833. } else {
  18834. tree._ = q;
  18835. }
  18836. q.U = parent;
  18837. p.U = q;
  18838. p.R = q.L;
  18839. if (p.R) p.R.U = p;
  18840. q.L = p;
  18841. }
  18842. function RedBlackRotateRight(tree, node) {
  18843. var p = node,
  18844. q = node.L,
  18845. parent = p.U;
  18846. if (parent) {
  18847. if (parent.L === p) parent.L = q;
  18848. else parent.R = q;
  18849. } else {
  18850. tree._ = q;
  18851. }
  18852. q.U = parent;
  18853. p.U = q;
  18854. p.L = q.R;
  18855. if (p.L) p.L.U = p;
  18856. q.R = p;
  18857. }
  18858. function RedBlackFirst(node) {
  18859. while (node.L) node = node.L;
  18860. return node;
  18861. }
  18862. function createEdge(left, right, v0, v1) {
  18863. var edge = [null, null],
  18864. index = edges.push(edge) - 1;
  18865. edge.left = left;
  18866. edge.right = right;
  18867. if (v0) setEdgeEnd(edge, left, right, v0);
  18868. if (v1) setEdgeEnd(edge, right, left, v1);
  18869. cells[left.index].halfedges.push(index);
  18870. cells[right.index].halfedges.push(index);
  18871. return edge;
  18872. }
  18873. function createBorderEdge(left, v0, v1) {
  18874. var edge = [v0, v1];
  18875. edge.left = left;
  18876. return edge;
  18877. }
  18878. function setEdgeEnd(edge, left, right, vertex) {
  18879. if (!edge[0] && !edge[1]) {
  18880. edge[0] = vertex;
  18881. edge.left = left;
  18882. edge.right = right;
  18883. } else if (edge.left === right) {
  18884. edge[1] = vertex;
  18885. } else {
  18886. edge[0] = vertex;
  18887. }
  18888. }
  18889. // Liang–Barsky line clipping.
  18890. function clipEdge(edge, x0, y0, x1, y1) {
  18891. var a = edge[0],
  18892. b = edge[1],
  18893. ax = a[0],
  18894. ay = a[1],
  18895. bx = b[0],
  18896. by = b[1],
  18897. t0 = 0,
  18898. t1 = 1,
  18899. dx = bx - ax,
  18900. dy = by - ay,
  18901. r;
  18902. r = x0 - ax;
  18903. if (!dx && r > 0) return;
  18904. r /= dx;
  18905. if (dx < 0) {
  18906. if (r < t0) return;
  18907. if (r < t1) t1 = r;
  18908. } else if (dx > 0) {
  18909. if (r > t1) return;
  18910. if (r > t0) t0 = r;
  18911. }
  18912. r = x1 - ax;
  18913. if (!dx && r < 0) return;
  18914. r /= dx;
  18915. if (dx < 0) {
  18916. if (r > t1) return;
  18917. if (r > t0) t0 = r;
  18918. } else if (dx > 0) {
  18919. if (r < t0) return;
  18920. if (r < t1) t1 = r;
  18921. }
  18922. r = y0 - ay;
  18923. if (!dy && r > 0) return;
  18924. r /= dy;
  18925. if (dy < 0) {
  18926. if (r < t0) return;
  18927. if (r < t1) t1 = r;
  18928. } else if (dy > 0) {
  18929. if (r > t1) return;
  18930. if (r > t0) t0 = r;
  18931. }
  18932. r = y1 - ay;
  18933. if (!dy && r < 0) return;
  18934. r /= dy;
  18935. if (dy < 0) {
  18936. if (r > t1) return;
  18937. if (r > t0) t0 = r;
  18938. } else if (dy > 0) {
  18939. if (r < t0) return;
  18940. if (r < t1) t1 = r;
  18941. }
  18942. if (!(t0 > 0) && !(t1 < 1)) return true; // TODO Better check?
  18943. if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy];
  18944. if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy];
  18945. return true;
  18946. }
  18947. function connectEdge(edge, x0, y0, x1, y1) {
  18948. var v1 = edge[1];
  18949. if (v1) return true;
  18950. var v0 = edge[0],
  18951. left = edge.left,
  18952. right = edge.right,
  18953. lx = left[0],
  18954. ly = left[1],
  18955. rx = right[0],
  18956. ry = right[1],
  18957. fx = (lx + rx) / 2,
  18958. fy = (ly + ry) / 2,
  18959. fm,
  18960. fb;
  18961. if (ry === ly) {
  18962. if (fx < x0 || fx >= x1) return;
  18963. if (lx > rx) {
  18964. if (!v0) v0 = [fx, y0];
  18965. else if (v0[1] >= y1) return;
  18966. v1 = [fx, y1];
  18967. } else {
  18968. if (!v0) v0 = [fx, y1];
  18969. else if (v0[1] < y0) return;
  18970. v1 = [fx, y0];
  18971. }
  18972. } else {
  18973. fm = (lx - rx) / (ry - ly);
  18974. fb = fy - fm * fx;
  18975. if (fm < -1 || fm > 1) {
  18976. if (lx > rx) {
  18977. if (!v0) v0 = [(y0 - fb) / fm, y0];
  18978. else if (v0[1] >= y1) return;
  18979. v1 = [(y1 - fb) / fm, y1];
  18980. } else {
  18981. if (!v0) v0 = [(y1 - fb) / fm, y1];
  18982. else if (v0[1] < y0) return;
  18983. v1 = [(y0 - fb) / fm, y0];
  18984. }
  18985. } else {
  18986. if (ly < ry) {
  18987. if (!v0) v0 = [x0, fm * x0 + fb];
  18988. else if (v0[0] >= x1) return;
  18989. v1 = [x1, fm * x1 + fb];
  18990. } else {
  18991. if (!v0) v0 = [x1, fm * x1 + fb];
  18992. else if (v0[0] < x0) return;
  18993. v1 = [x0, fm * x0 + fb];
  18994. }
  18995. }
  18996. }
  18997. edge[0] = v0;
  18998. edge[1] = v1;
  18999. return true;
  19000. }
  19001. function clipEdges(x0, y0, x1, y1) {
  19002. var i = edges.length,
  19003. edge;
  19004. while (i--) {
  19005. if (!connectEdge(edge = edges[i], x0, y0, x1, y1)
  19006. || !clipEdge(edge, x0, y0, x1, y1)
  19007. || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon
  19008. || Math.abs(edge[0][1] - edge[1][1]) > epsilon)) {
  19009. delete edges[i];
  19010. }
  19011. }
  19012. }
  19013. function createCell(site) {
  19014. return cells[site.index] = {
  19015. site: site,
  19016. halfedges: []
  19017. };
  19018. }
  19019. function cellHalfedgeAngle(cell, edge) {
  19020. var site = cell.site,
  19021. va = edge.left,
  19022. vb = edge.right;
  19023. if (site === vb) vb = va, va = site;
  19024. if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]);
  19025. if (site === va) va = edge[1], vb = edge[0];
  19026. else va = edge[0], vb = edge[1];
  19027. return Math.atan2(va[0] - vb[0], vb[1] - va[1]);
  19028. }
  19029. function cellHalfedgeStart(cell, edge) {
  19030. return edge[+(edge.left !== cell.site)];
  19031. }
  19032. function cellHalfedgeEnd(cell, edge) {
  19033. return edge[+(edge.left === cell.site)];
  19034. }
  19035. function sortCellHalfedges() {
  19036. for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) {
  19037. if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) {
  19038. var index = new Array(m),
  19039. array = new Array(m);
  19040. for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]);
  19041. index.sort(function(i, j) { return array[j] - array[i]; });
  19042. for (j = 0; j < m; ++j) array[j] = halfedges[index[j]];
  19043. for (j = 0; j < m; ++j) halfedges[j] = array[j];
  19044. }
  19045. }
  19046. }
  19047. function clipCells(x0, y0, x1, y1) {
  19048. var nCells = cells.length,
  19049. iCell,
  19050. cell,
  19051. site,
  19052. iHalfedge,
  19053. halfedges,
  19054. nHalfedges,
  19055. start,
  19056. startX,
  19057. startY,
  19058. end,
  19059. endX,
  19060. endY,
  19061. cover = true;
  19062. for (iCell = 0; iCell < nCells; ++iCell) {
  19063. if (cell = cells[iCell]) {
  19064. site = cell.site;
  19065. halfedges = cell.halfedges;
  19066. iHalfedge = halfedges.length;
  19067. // Remove any dangling clipped edges.
  19068. while (iHalfedge--) {
  19069. if (!edges[halfedges[iHalfedge]]) {
  19070. halfedges.splice(iHalfedge, 1);
  19071. }
  19072. }
  19073. // Insert any border edges as necessary.
  19074. iHalfedge = 0, nHalfedges = halfedges.length;
  19075. while (iHalfedge < nHalfedges) {
  19076. end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1];
  19077. start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1];
  19078. if (Math.abs(endX - startX) > epsilon || Math.abs(endY - startY) > epsilon) {
  19079. halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end,
  19080. Math.abs(endX - x0) < epsilon && y1 - endY > epsilon ? [x0, Math.abs(startX - x0) < epsilon ? startY : y1]
  19081. : Math.abs(endY - y1) < epsilon && x1 - endX > epsilon ? [Math.abs(startY - y1) < epsilon ? startX : x1, y1]
  19082. : Math.abs(endX - x1) < epsilon && endY - y0 > epsilon ? [x1, Math.abs(startX - x1) < epsilon ? startY : y0]
  19083. : Math.abs(endY - y0) < epsilon && endX - x0 > epsilon ? [Math.abs(startY - y0) < epsilon ? startX : x0, y0]
  19084. : null)) - 1);
  19085. ++nHalfedges;
  19086. }
  19087. }
  19088. if (nHalfedges) cover = false;
  19089. }
  19090. }
  19091. // If there weren’t any edges, have the closest site cover the extent.
  19092. // It doesn’t matter which corner of the extent we measure!
  19093. if (cover) {
  19094. var dx, dy, d2, dc = Infinity;
  19095. for (iCell = 0, cover = null; iCell < nCells; ++iCell) {
  19096. if (cell = cells[iCell]) {
  19097. site = cell.site;
  19098. dx = site[0] - x0;
  19099. dy = site[1] - y0;
  19100. d2 = dx * dx + dy * dy;
  19101. if (d2 < dc) dc = d2, cover = cell;
  19102. }
  19103. }
  19104. if (cover) {
  19105. var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0];
  19106. cover.halfedges.push(
  19107. edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1,
  19108. edges.push(createBorderEdge(site, v01, v11)) - 1,
  19109. edges.push(createBorderEdge(site, v11, v10)) - 1,
  19110. edges.push(createBorderEdge(site, v10, v00)) - 1
  19111. );
  19112. }
  19113. }
  19114. // Lastly delete any cells with no edges; these were entirely clipped.
  19115. for (iCell = 0; iCell < nCells; ++iCell) {
  19116. if (cell = cells[iCell]) {
  19117. if (!cell.halfedges.length) {
  19118. delete cells[iCell];
  19119. }
  19120. }
  19121. }
  19122. }
  19123. var circlePool = [];
  19124. var firstCircle;
  19125. function Circle() {
  19126. RedBlackNode(this);
  19127. this.x =
  19128. this.y =
  19129. this.arc =
  19130. this.site =
  19131. this.cy = null;
  19132. }
  19133. function attachCircle(arc) {
  19134. var lArc = arc.P,
  19135. rArc = arc.N;
  19136. if (!lArc || !rArc) return;
  19137. var lSite = lArc.site,
  19138. cSite = arc.site,
  19139. rSite = rArc.site;
  19140. if (lSite === rSite) return;
  19141. var bx = cSite[0],
  19142. by = cSite[1],
  19143. ax = lSite[0] - bx,
  19144. ay = lSite[1] - by,
  19145. cx = rSite[0] - bx,
  19146. cy = rSite[1] - by;
  19147. var d = 2 * (ax * cy - ay * cx);
  19148. if (d >= -epsilon2) return;
  19149. var ha = ax * ax + ay * ay,
  19150. hc = cx * cx + cy * cy,
  19151. x = (cy * ha - ay * hc) / d,
  19152. y = (ax * hc - cx * ha) / d;
  19153. var circle = circlePool.pop() || new Circle;
  19154. circle.arc = arc;
  19155. circle.site = cSite;
  19156. circle.x = x + bx;
  19157. circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom
  19158. arc.circle = circle;
  19159. var before = null,
  19160. node = circles._;
  19161. while (node) {
  19162. if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) {
  19163. if (node.L) node = node.L;
  19164. else { before = node.P; break; }
  19165. } else {
  19166. if (node.R) node = node.R;
  19167. else { before = node; break; }
  19168. }
  19169. }
  19170. circles.insert(before, circle);
  19171. if (!before) firstCircle = circle;
  19172. }
  19173. function detachCircle(arc) {
  19174. var circle = arc.circle;
  19175. if (circle) {
  19176. if (!circle.P) firstCircle = circle.N;
  19177. circles.remove(circle);
  19178. circlePool.push(circle);
  19179. RedBlackNode(circle);
  19180. arc.circle = null;
  19181. }
  19182. }
  19183. var beachPool = [];
  19184. function Beach() {
  19185. RedBlackNode(this);
  19186. this.edge =
  19187. this.site =
  19188. this.circle = null;
  19189. }
  19190. function createBeach(site) {
  19191. var beach = beachPool.pop() || new Beach;
  19192. beach.site = site;
  19193. return beach;
  19194. }
  19195. function detachBeach(beach) {
  19196. detachCircle(beach);
  19197. beaches.remove(beach);
  19198. beachPool.push(beach);
  19199. RedBlackNode(beach);
  19200. }
  19201. function removeBeach(beach) {
  19202. var circle = beach.circle,
  19203. x = circle.x,
  19204. y = circle.cy,
  19205. vertex = [x, y],
  19206. previous = beach.P,
  19207. next = beach.N,
  19208. disappearing = [beach];
  19209. detachBeach(beach);
  19210. var lArc = previous;
  19211. while (lArc.circle
  19212. && Math.abs(x - lArc.circle.x) < epsilon
  19213. && Math.abs(y - lArc.circle.cy) < epsilon) {
  19214. previous = lArc.P;
  19215. disappearing.unshift(lArc);
  19216. detachBeach(lArc);
  19217. lArc = previous;
  19218. }
  19219. disappearing.unshift(lArc);
  19220. detachCircle(lArc);
  19221. var rArc = next;
  19222. while (rArc.circle
  19223. && Math.abs(x - rArc.circle.x) < epsilon
  19224. && Math.abs(y - rArc.circle.cy) < epsilon) {
  19225. next = rArc.N;
  19226. disappearing.push(rArc);
  19227. detachBeach(rArc);
  19228. rArc = next;
  19229. }
  19230. disappearing.push(rArc);
  19231. detachCircle(rArc);
  19232. var nArcs = disappearing.length,
  19233. iArc;
  19234. for (iArc = 1; iArc < nArcs; ++iArc) {
  19235. rArc = disappearing[iArc];
  19236. lArc = disappearing[iArc - 1];
  19237. setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
  19238. }
  19239. lArc = disappearing[0];
  19240. rArc = disappearing[nArcs - 1];
  19241. rArc.edge = createEdge(lArc.site, rArc.site, null, vertex);
  19242. attachCircle(lArc);
  19243. attachCircle(rArc);
  19244. }
  19245. function addBeach(site) {
  19246. var x = site[0],
  19247. directrix = site[1],
  19248. lArc,
  19249. rArc,
  19250. dxl,
  19251. dxr,
  19252. node = beaches._;
  19253. while (node) {
  19254. dxl = leftBreakPoint(node, directrix) - x;
  19255. if (dxl > epsilon) node = node.L; else {
  19256. dxr = x - rightBreakPoint(node, directrix);
  19257. if (dxr > epsilon) {
  19258. if (!node.R) {
  19259. lArc = node;
  19260. break;
  19261. }
  19262. node = node.R;
  19263. } else {
  19264. if (dxl > -epsilon) {
  19265. lArc = node.P;
  19266. rArc = node;
  19267. } else if (dxr > -epsilon) {
  19268. lArc = node;
  19269. rArc = node.N;
  19270. } else {
  19271. lArc = rArc = node;
  19272. }
  19273. break;
  19274. }
  19275. }
  19276. }
  19277. createCell(site);
  19278. var newArc = createBeach(site);
  19279. beaches.insert(lArc, newArc);
  19280. if (!lArc && !rArc) return;
  19281. if (lArc === rArc) {
  19282. detachCircle(lArc);
  19283. rArc = createBeach(lArc.site);
  19284. beaches.insert(newArc, rArc);
  19285. newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site);
  19286. attachCircle(lArc);
  19287. attachCircle(rArc);
  19288. return;
  19289. }
  19290. if (!rArc) { // && lArc
  19291. newArc.edge = createEdge(lArc.site, newArc.site);
  19292. return;
  19293. }
  19294. // else lArc !== rArc
  19295. detachCircle(lArc);
  19296. detachCircle(rArc);
  19297. var lSite = lArc.site,
  19298. ax = lSite[0],
  19299. ay = lSite[1],
  19300. bx = site[0] - ax,
  19301. by = site[1] - ay,
  19302. rSite = rArc.site,
  19303. cx = rSite[0] - ax,
  19304. cy = rSite[1] - ay,
  19305. d = 2 * (bx * cy - by * cx),
  19306. hb = bx * bx + by * by,
  19307. hc = cx * cx + cy * cy,
  19308. vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay];
  19309. setEdgeEnd(rArc.edge, lSite, rSite, vertex);
  19310. newArc.edge = createEdge(lSite, site, null, vertex);
  19311. rArc.edge = createEdge(site, rSite, null, vertex);
  19312. attachCircle(lArc);
  19313. attachCircle(rArc);
  19314. }
  19315. function leftBreakPoint(arc, directrix) {
  19316. var site = arc.site,
  19317. rfocx = site[0],
  19318. rfocy = site[1],
  19319. pby2 = rfocy - directrix;
  19320. if (!pby2) return rfocx;
  19321. var lArc = arc.P;
  19322. if (!lArc) return -Infinity;
  19323. site = lArc.site;
  19324. var lfocx = site[0],
  19325. lfocy = site[1],
  19326. plby2 = lfocy - directrix;
  19327. if (!plby2) return lfocx;
  19328. var hl = lfocx - rfocx,
  19329. aby2 = 1 / pby2 - 1 / plby2,
  19330. b = hl / plby2;
  19331. if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
  19332. return (rfocx + lfocx) / 2;
  19333. }
  19334. function rightBreakPoint(arc, directrix) {
  19335. var rArc = arc.N;
  19336. if (rArc) return leftBreakPoint(rArc, directrix);
  19337. var site = arc.site;
  19338. return site[1] === directrix ? site[0] : Infinity;
  19339. }
  19340. var epsilon = 1e-6;
  19341. var epsilon2 = 1e-12;
  19342. var beaches;
  19343. var cells;
  19344. var circles;
  19345. var edges;
  19346. function triangleArea(a, b, c) {
  19347. return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]);
  19348. }
  19349. function lexicographic(a, b) {
  19350. return b[1] - a[1]
  19351. || b[0] - a[0];
  19352. }
  19353. function Diagram(sites, extent) {
  19354. var site = sites.sort(lexicographic).pop(),
  19355. x,
  19356. y,
  19357. circle;
  19358. edges = [];
  19359. cells = new Array(sites.length);
  19360. beaches = new RedBlackTree;
  19361. circles = new RedBlackTree;
  19362. while (true) {
  19363. circle = firstCircle;
  19364. if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) {
  19365. if (site[0] !== x || site[1] !== y) {
  19366. addBeach(site);
  19367. x = site[0], y = site[1];
  19368. }
  19369. site = sites.pop();
  19370. } else if (circle) {
  19371. removeBeach(circle.arc);
  19372. } else {
  19373. break;
  19374. }
  19375. }
  19376. sortCellHalfedges();
  19377. if (extent) {
  19378. var x0 = +extent[0][0],
  19379. y0 = +extent[0][1],
  19380. x1 = +extent[1][0],
  19381. y1 = +extent[1][1];
  19382. clipEdges(x0, y0, x1, y1);
  19383. clipCells(x0, y0, x1, y1);
  19384. }
  19385. this.edges = edges;
  19386. this.cells = cells;
  19387. beaches =
  19388. circles =
  19389. edges =
  19390. cells = null;
  19391. }
  19392. Diagram.prototype = {
  19393. constructor: Diagram,
  19394. polygons: function() {
  19395. var edges = this.edges;
  19396. return this.cells.map(function(cell) {
  19397. var polygon = cell.halfedges.map(function(i) { return cellHalfedgeStart(cell, edges[i]); });
  19398. polygon.data = cell.site.data;
  19399. return polygon;
  19400. });
  19401. },
  19402. triangles: function() {
  19403. var triangles = [],
  19404. edges = this.edges;
  19405. this.cells.forEach(function(cell, i) {
  19406. if (!(m = (halfedges = cell.halfedges).length)) return;
  19407. var site = cell.site,
  19408. halfedges,
  19409. j = -1,
  19410. m,
  19411. s0,
  19412. e1 = edges[halfedges[m - 1]],
  19413. s1 = e1.left === site ? e1.right : e1.left;
  19414. while (++j < m) {
  19415. s0 = s1;
  19416. e1 = edges[halfedges[j]];
  19417. s1 = e1.left === site ? e1.right : e1.left;
  19418. if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) {
  19419. triangles.push([site.data, s0.data, s1.data]);
  19420. }
  19421. }
  19422. });
  19423. return triangles;
  19424. },
  19425. links: function() {
  19426. return this.edges.filter(function(edge) {
  19427. return edge.right;
  19428. }).map(function(edge) {
  19429. return {
  19430. source: edge.left.data,
  19431. target: edge.right.data
  19432. };
  19433. });
  19434. },
  19435. find: function(x, y, radius) {
  19436. var that = this, i0, i1 = that._found || 0, n = that.cells.length, cell;
  19437. // Use the previously-found cell, or start with an arbitrary one.
  19438. while (!(cell = that.cells[i1])) if (++i1 >= n) return null;
  19439. var dx = x - cell.site[0], dy = y - cell.site[1], d2 = dx * dx + dy * dy;
  19440. // Traverse the half-edges to find a closer cell, if any.
  19441. do {
  19442. cell = that.cells[i0 = i1], i1 = null;
  19443. cell.halfedges.forEach(function(e) {
  19444. var edge = that.edges[e], v = edge.left;
  19445. if ((v === cell.site || !v) && !(v = edge.right)) return;
  19446. var vx = x - v[0], vy = y - v[1], v2 = vx * vx + vy * vy;
  19447. if (v2 < d2) d2 = v2, i1 = v.index;
  19448. });
  19449. } while (i1 !== null);
  19450. that._found = i0;
  19451. return radius == null || d2 <= radius * radius ? cell.site : null;
  19452. }
  19453. };
  19454. var voronoi = function() {
  19455. var x$$1 = x,
  19456. y$$1 = y,
  19457. extent = null;
  19458. function voronoi(data) {
  19459. return new Diagram(data.map(function(d, i) {
  19460. var s = [Math.round(x$$1(d, i, data) / epsilon) * epsilon, Math.round(y$$1(d, i, data) / epsilon) * epsilon];
  19461. s.index = i;
  19462. s.data = d;
  19463. return s;
  19464. }), extent);
  19465. }
  19466. voronoi.polygons = function(data) {
  19467. return voronoi(data).polygons();
  19468. };
  19469. voronoi.links = function(data) {
  19470. return voronoi(data).links();
  19471. };
  19472. voronoi.triangles = function(data) {
  19473. return voronoi(data).triangles();
  19474. };
  19475. voronoi.x = function(_) {
  19476. return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant(+_), voronoi) : x$$1;
  19477. };
  19478. voronoi.y = function(_) {
  19479. return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant(+_), voronoi) : y$$1;
  19480. };
  19481. voronoi.extent = function(_) {
  19482. return arguments.length ? (extent = _ == null ? null : [[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]], voronoi) : extent && [[extent[0][0], extent[0][1]], [extent[1][0], extent[1][1]]];
  19483. };
  19484. voronoi.size = function(_) {
  19485. return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]];
  19486. };
  19487. return voronoi;
  19488. };
  19489. /**
  19490. * @private
  19491. * @param {Array<Array<number>>} coords representing a polygon
  19492. * @returns {Feature<Polygon>} polygon
  19493. */
  19494. function coordsToPolygon(coords) {
  19495. coords = coords.slice();
  19496. coords.push(coords[0]);
  19497. return polygon([coords]);
  19498. }
  19499. /**
  19500. * Takes a FeatureCollection of points, and a bounding box, and returns a FeatureCollection
  19501. * of Voronoi polygons.
  19502. *
  19503. * The Voronoi algorithim used comes from the d3-voronoi package.
  19504. *
  19505. * @name voronoi
  19506. * @param {FeatureCollection<Point>} points to find the Voronoi polygons around.
  19507. * @param {Object} [options={}] Optional parameters
  19508. * @param {number[]} [options.bbox=[-180, -85, 180, -85]] clipping rectangle, in [minX, minY, maxX, MaxY] order.
  19509. * @returns {FeatureCollection<Polygon>} a set of polygons, one per input point.
  19510. * @example
  19511. * var options = {
  19512. * bbox: [-70, 40, -60, 60]
  19513. * };
  19514. * var points = turf.randomPoint(100, options);
  19515. * var voronoiPolygons = turf.voronoi(points, options);
  19516. *
  19517. * //addToMap
  19518. * var addToMap = [voronoiPolygons, points];
  19519. */
  19520. function voronoi$1(points$$1, options) {
  19521. // Optional params
  19522. options = options || {};
  19523. if (!isObject(options)) throw new Error('options is invalid');
  19524. var bbox = options.bbox || [-180, -85, 180, 85];
  19525. // Input Validation
  19526. if (!points$$1) throw new Error('points is required');
  19527. if (!Array.isArray(bbox)) throw new Error('bbox is invalid');
  19528. collectionOf(points$$1, 'Point', 'points');
  19529. // Main
  19530. return featureCollection(
  19531. voronoi()
  19532. .x(function (feature$$1) { return feature$$1.geometry.coordinates[0]; })
  19533. .y(function (feature$$1) { return feature$$1.geometry.coordinates[1]; })
  19534. .extent([[bbox[0], bbox[1]], [bbox[2], bbox[3]]])
  19535. .polygons(points$$1.features)
  19536. .map(coordsToPolygon)
  19537. );
  19538. }
  19539. /**
  19540. * Takes a {@link Point} and calculates the ellipse polygon given two semi-axes expressed in variable units and steps for precision.
  19541. *
  19542. * @param {Coord} center center point
  19543. * @param {number} xSemiAxis semi (major) axis of the ellipse along the x-axis
  19544. * @param {number} ySemiAxis semi (minor) axis of the ellipse along the y-axis
  19545. * @param {Object} [options={}] Optional parameters
  19546. * @param {number} [options.angle=0] angle of rotation (along the vertical axis), from North in decimal degrees, negative clockwise
  19547. * @param {Coord} [options.pivot='origin'] point around which the rotation will be performed
  19548. * @param {number} [options.steps=64] number of steps
  19549. * @param {string} [options.units='kilometers'] unit of measurement for axes
  19550. * @param {Object} [options.properties={}] properties
  19551. * @returns {Feature<Polygon>} ellipse polygon
  19552. * @example
  19553. * var center = [-75, 40];
  19554. * var xSemiAxis = 5;
  19555. * var ySemiAxis = 2;
  19556. * var ellipse = turf.ellipse(center, xSemiAxis, ySemiAxis);
  19557. *
  19558. * //addToMap
  19559. * var addToMap = [turf.point(center), ellipse]
  19560. */
  19561. function ellipse(center, xSemiAxis, ySemiAxis, options) {
  19562. // Optional params
  19563. options = options || {};
  19564. var steps = options.steps || 64;
  19565. var units = options.units || 'kilometers';
  19566. var angle = options.angle || 0;
  19567. var pivot = options.pivot || center;
  19568. var properties = options.properties || center.properties || {};
  19569. // validation
  19570. if (!center) throw new Error('center is required');
  19571. if (!xSemiAxis) throw new Error('xSemiAxis is required');
  19572. if (!ySemiAxis) throw new Error('ySemiAxis is required');
  19573. if (!isObject(options)) throw new Error('options must be an object');
  19574. if (!isNumber(steps)) throw new Error('steps must be a number');
  19575. if (!isNumber(angle)) throw new Error('angle must be a number');
  19576. var centerCoords = getCoord(center);
  19577. if (units === 'degrees') {
  19578. var angleRad = degreesToRadians(angle);
  19579. } else {
  19580. xSemiAxis = rhumbDestination(center, xSemiAxis, 90, {units: units});
  19581. ySemiAxis = rhumbDestination(center, ySemiAxis, 0, {units: units});
  19582. xSemiAxis = getCoord(xSemiAxis)[0] - centerCoords[0];
  19583. ySemiAxis = getCoord(ySemiAxis)[1] - centerCoords[1];
  19584. }
  19585. var coordinates = [];
  19586. for (var i = 0; i < steps; i += 1) {
  19587. var stepAngle = i * -360 / steps;
  19588. var x = ((xSemiAxis * ySemiAxis) / Math.sqrt(Math.pow(ySemiAxis, 2) + (Math.pow(xSemiAxis, 2) * Math.pow(getTanDeg(stepAngle), 2))));
  19589. var y = ((xSemiAxis * ySemiAxis) / Math.sqrt(Math.pow(xSemiAxis, 2) + (Math.pow(ySemiAxis, 2) / Math.pow(getTanDeg(stepAngle), 2))));
  19590. if (stepAngle < -90 && stepAngle >= -270) x = -x;
  19591. if (stepAngle < -180 && stepAngle >= -360) y = -y;
  19592. if (units === 'degrees') {
  19593. var newx = x * Math.cos(angleRad) + y * Math.sin(angleRad);
  19594. var newy = y * Math.cos(angleRad) - x * Math.sin(angleRad);
  19595. x = newx;
  19596. y = newy;
  19597. }
  19598. coordinates.push([x + centerCoords[0], y + centerCoords[1]]);
  19599. }
  19600. coordinates.push(coordinates[0]);
  19601. if (units === 'degrees') {
  19602. return polygon([coordinates], properties);
  19603. } else {
  19604. return transformRotate(polygon([coordinates], properties), angle, { pivot: pivot });
  19605. }
  19606. }
  19607. /**
  19608. * Get Tan Degrees
  19609. *
  19610. * @private
  19611. * @param {number} deg Degrees
  19612. * @returns {number} Tan Degrees
  19613. */
  19614. function getTanDeg(deg) {
  19615. var rad = deg * Math.PI / 180;
  19616. return Math.tan(rad);
  19617. }
  19618. /**
  19619. * Takes a {@link Feature} or {@link FeatureCollection} and returns the mean center. Can be weighted.
  19620. *
  19621. * @name centerMean
  19622. * @param {GeoJSON} geojson GeoJSON to be centered
  19623. * @param {Object} [options={}] Optional parameters
  19624. * @param {Object} [options.properties={}] an Object that is used as the {@link Feature}'s properties
  19625. * @param {number} [options.weight] the property name used to weight the center
  19626. * @returns {Feature<Point>} a Point feature at the mean center point of all input features
  19627. * @example
  19628. * var features = turf.featureCollection([
  19629. * turf.point([-97.522259, 35.4691], {weight: 10}),
  19630. * turf.point([-97.502754, 35.463455], {weight: 3}),
  19631. * turf.point([-97.508269, 35.463245], {weight: 5})
  19632. * ]);
  19633. *
  19634. * var options = {weight: "weight"}
  19635. * var mean = turf.centerMean(features, options);
  19636. *
  19637. * //addToMap
  19638. * var addToMap = [features, mean]
  19639. * mean.properties['marker-size'] = 'large';
  19640. * mean.properties['marker-color'] = '#000';
  19641. */
  19642. function centerMean(geojson, options) {
  19643. // Optional parameters
  19644. options = options || {};
  19645. if (!isObject(options)) throw new Error('options is invalid');
  19646. var properties = options.properties;
  19647. var weightTerm = options.weight;
  19648. // Input validation
  19649. if (!geojson) throw new Error('geojson is required');
  19650. var sumXs = 0;
  19651. var sumYs = 0;
  19652. var sumNs = 0;
  19653. geomEach(geojson, function (geom, featureIndex, properties) {
  19654. var weight = properties[weightTerm];
  19655. weight = (weight === undefined || weight === null) ? 1 : weight;
  19656. if (!isNumber(weight)) throw new Error('weight value must be a number for feature index ' + featureIndex);
  19657. weight = Number(weight);
  19658. if (weight > 0) {
  19659. coordEach(geom, function (coord) {
  19660. sumXs += coord[0] * weight;
  19661. sumYs += coord[1] * weight;
  19662. sumNs += weight;
  19663. });
  19664. }
  19665. });
  19666. return point([sumXs / sumNs, sumYs / sumNs], properties);
  19667. }
  19668. /**
  19669. * Takes a {@link FeatureCollection} of points and calculates the median center,
  19670. * algorithimically. The median center is understood as the point that is
  19671. * requires the least total travel from all other points.
  19672. *
  19673. * Turfjs has four different functions for calculating the center of a set of
  19674. * data. Each is useful depending on circumstance.
  19675. *
  19676. * `@turf/center` finds the simple center of a dataset, by finding the
  19677. * midpoint between the extents of the data. That is, it divides in half the
  19678. * farthest east and farthest west point as well as the farthest north and
  19679. * farthest south.
  19680. *
  19681. * `@turf/center-of-mass` imagines that the dataset is a sheet of paper.
  19682. * The center of mass is where the sheet would balance on a fingertip.
  19683. *
  19684. * `@turf/center-mean` takes the averages of all the coordinates and
  19685. * produces a value that respects that. Unlike `@turf/center`, it is
  19686. * sensitive to clusters and outliers. It lands in the statistical middle of a
  19687. * dataset, not the geographical. It can also be weighted, meaning certain
  19688. * points are more important than others.
  19689. *
  19690. * `@turf/center-median` takes the mean center and tries to find, iteratively,
  19691. * a new point that requires the least amount of travel from all the points in
  19692. * the dataset. It is not as sensitive to outliers as `@turf/center`, but it is
  19693. * attracted to clustered data. It, too, can be weighted.
  19694. *
  19695. * **Bibliography**
  19696. *
  19697. * Harold W. Kuhn and Robert E. Kuenne, “An Efficient Algorithm for the
  19698. * Numerical Solution of the Generalized Weber Problem in Spatial
  19699. * Economics,” _Journal of Regional Science_ 4, no. 2 (1962): 21–33,
  19700. * doi:{@link https://doi.org/10.1111/j.1467-9787.1962.tb00902.x}.
  19701. *
  19702. * James E. Burt, Gerald M. Barber, and David L. Rigby, _Elementary
  19703. * Statistics for Geographers_, 3rd ed., New York: The Guilford
  19704. * Press, 2009, 150–151.
  19705. *
  19706. * @name centerMedian
  19707. * @param {FeatureCollection<any>} features Any GeoJSON Feature Collection
  19708. * @param {Object} [options={}] Optional parameters
  19709. * @param {string} [options.weight] the property name used to weight the center
  19710. * @param {number} [options.tolerance=0.001] the difference in distance between candidate medians at which point the algorighim stops iterating.
  19711. * @param {number} [options.counter=10] how many attempts to find the median, should the tolerance be insufficient.
  19712. * @returns {Feature<Point>} The median center of the collection
  19713. * @example
  19714. * var points = turf.points([[0, 0], [1, 0], [0, 1], [5, 8]]);
  19715. * var medianCenter = turf.centerMedian(points);
  19716. *
  19717. * //addToMap
  19718. * var addToMap = [points, medianCenter]
  19719. */
  19720. function centerMedian(features, options) {
  19721. // Optional params
  19722. options = options || {};
  19723. if (!isObject(options)) throw new Error('options is invalid');
  19724. var counter = options.counter || 10;
  19725. if (!isNumber(counter)) throw new Error('counter must be a number');
  19726. var weightTerm = options.weight;
  19727. // Calculate mean center:
  19728. var meanCenter = centerMean(features, {weight: options.weight});
  19729. // Calculate center of every feature:
  19730. var centroids = featureCollection([]);
  19731. featureEach(features, function (feature$$1) {
  19732. centroids.features.push(centroid(feature$$1, {weight: feature$$1.properties[weightTerm]}));
  19733. });
  19734. centroids.properties = {
  19735. tolerance: options.tolerance,
  19736. medianCandidates: []
  19737. };
  19738. return findMedian(meanCenter.geometry.coordinates, [0, 0], centroids, counter);
  19739. }
  19740. /**
  19741. * Recursive function to find new candidate medians.
  19742. *
  19743. * @private
  19744. * @param {Position} candidateMedian current candidate median
  19745. * @param {Position} previousCandidate the previous candidate median
  19746. * @param {FeatureCollection<Point>} centroids the collection of centroids whose median we are determining
  19747. * @param {number} counter how many attempts to try before quitting.
  19748. * @returns {Feature<Point>} the median center of the dataset.
  19749. */
  19750. function findMedian(candidateMedian, previousCandidate, centroids, counter) {
  19751. var tolerance = centroids.properties.tolerance || 0.001;
  19752. var candidateXsum = 0;
  19753. var candidateYsum = 0;
  19754. var kSum = 0;
  19755. var centroidCount = 0;
  19756. featureEach(centroids, function (theCentroid) {
  19757. var weightValue = theCentroid.properties.weight;
  19758. var weight = (weightValue === undefined || weightValue === null) ? 1 : weightValue;
  19759. weight = Number(weight);
  19760. if (!isNumber(weight)) throw new Error('weight value must be a number');
  19761. if (weight > 0) {
  19762. centroidCount += 1;
  19763. var distanceFromCandidate = weight * distance(theCentroid, candidateMedian);
  19764. if (distanceFromCandidate === 0) distanceFromCandidate = 1;
  19765. var k = weight / distanceFromCandidate;
  19766. candidateXsum += theCentroid.geometry.coordinates[0] * k;
  19767. candidateYsum += theCentroid.geometry.coordinates[1] * k;
  19768. kSum += k;
  19769. }
  19770. });
  19771. if (centroidCount < 1) throw new Error('no features to measure');
  19772. var candidateX = candidateXsum / kSum;
  19773. var candidateY = candidateYsum / kSum;
  19774. if (centroidCount === 1 || counter === 0 || (Math.abs(candidateX - previousCandidate[0]) < tolerance && Math.abs(candidateY - previousCandidate[1]) < tolerance)) {
  19775. return point([candidateX, candidateY], {medianCandidates: centroids.properties.medianCandidates});
  19776. } else {
  19777. centroids.properties.medianCandidates.push([candidateX, candidateY]);
  19778. return findMedian([candidateX, candidateY], candidateMedian, centroids, counter - 1);
  19779. }
  19780. }
  19781. /**
  19782. * Takes a {@link FeatureCollection} and returns a standard deviational ellipse,
  19783. * also known as a “directional distribution.” The standard deviational ellipse
  19784. * aims to show the direction and the distribution of a dataset by drawing
  19785. * an ellipse that contains about one standard deviation’s worth (~ 70%) of the
  19786. * data.
  19787. *
  19788. * This module mirrors the functionality of [Directional Distribution](http://desktop.arcgis.com/en/arcmap/10.3/tools/spatial-statistics-toolbox/directional-distribution.htm)
  19789. * in ArcGIS and the [QGIS Standard Deviational Ellipse Plugin](http://arken.nmbu.no/~havatv/gis/qgisplugins/SDEllipse/)
  19790. *
  19791. * **Bibliography**
  19792. *
  19793. * • Robert S. Yuill, “The Standard Deviational Ellipse; An Updated Tool for
  19794. * Spatial Description,” _Geografiska Annaler_ 53, no. 1 (1971): 28–39,
  19795. * doi:{@link https://doi.org/10.2307/490885|10.2307/490885}.
  19796. *
  19797. * • Paul Hanly Furfey, “A Note on Lefever’s “Standard Deviational Ellipse,”
  19798. * _American Journal of Sociology_ 33, no. 1 (1927): 94—98,
  19799. * doi:{@link https://doi.org/10.1086/214336|10.1086/214336}.
  19800. *
  19801. *
  19802. * @name standardDeviationalEllipse
  19803. * @param {FeatureCollection<Point>} points GeoJSON points
  19804. * @param {Object} [options={}] Optional parameters
  19805. * @param {string} [options.weight] the property name used to weight the center
  19806. * @param {number} [options.steps=64] number of steps for the polygon
  19807. * @param {Object} [options.properties={}] properties to pass to the resulting ellipse
  19808. * @returns {Feature<Polygon>} an elliptical Polygon that includes approximately 1 SD of the dataset within it.
  19809. * @example
  19810. *
  19811. * var bbox = [-74, 40.72, -73.98, 40.74];
  19812. * var points = turf.randomPoint(400, {bbox: bbox});
  19813. * var sdEllipse = turf.standardDeviationalEllipse(points);
  19814. *
  19815. * //addToMap
  19816. * var addToMap = [points, sdEllipse];
  19817. *
  19818. */
  19819. function standardDeviationalEllipse(points$$1, options) {
  19820. // Optional params
  19821. options = options || {};
  19822. if (!isObject(options)) throw new Error('options is invalid');
  19823. var steps = options.steps || 64;
  19824. var weightTerm = options.weight;
  19825. var properties = options.properties || {};
  19826. // Validation:
  19827. if (!isNumber(steps)) throw new Error('steps must be a number');
  19828. if (!isObject(properties)) throw new Error('properties must be a number');
  19829. // Calculate mean center & number of features:
  19830. var numberOfFeatures = coordAll(points$$1).length;
  19831. var meanCenter = centerMean(points$$1, {weight: weightTerm});
  19832. // Calculate angle of rotation:
  19833. // [X, Y] = mean center of all [x, y].
  19834. // theta = arctan( (A + B) / C )
  19835. // A = sum((x - X)^2) - sum((y - Y)^2)
  19836. // B = sqrt(A^2 + 4(sum((x - X)(y - Y))^2))
  19837. // C = 2(sum((x - X)(y - Y)))
  19838. var xDeviationSquaredSum = 0;
  19839. var yDeviationSquaredSum = 0;
  19840. var xyDeviationSum = 0;
  19841. featureEach(points$$1, function (point$$1) {
  19842. var weight = point$$1.properties[weightTerm] || 1;
  19843. var deviation = getDeviations(getCoords(point$$1), getCoords(meanCenter));
  19844. xDeviationSquaredSum += Math.pow(deviation.x, 2) * weight;
  19845. yDeviationSquaredSum += Math.pow(deviation.y, 2) * weight;
  19846. xyDeviationSum += deviation.x * deviation.y * weight;
  19847. });
  19848. var bigA = xDeviationSquaredSum - yDeviationSquaredSum;
  19849. var bigB = Math.sqrt(Math.pow(bigA, 2) + 4 * Math.pow(xyDeviationSum, 2));
  19850. var bigC = 2 * xyDeviationSum;
  19851. var theta = Math.atan((bigA + bigB) / bigC);
  19852. var thetaDeg = theta * 180 / Math.PI;
  19853. // Calculate axes:
  19854. // sigmaX = sqrt((1 / n - 2) * sum((((x - X) * cos(theta)) - ((y - Y) * sin(theta)))^2))
  19855. // sigmaY = sqrt((1 / n - 2) * sum((((x - X) * sin(theta)) - ((y - Y) * cos(theta)))^2))
  19856. var sigmaXsum = 0;
  19857. var sigmaYsum = 0;
  19858. var weightsum = 0;
  19859. featureEach(points$$1, function (point$$1) {
  19860. var weight = point$$1.properties[weightTerm] || 1;
  19861. var deviation = getDeviations(getCoords(point$$1), getCoords(meanCenter));
  19862. sigmaXsum += Math.pow((deviation.x * Math.cos(theta)) - (deviation.y * Math.sin(theta)), 2) * weight;
  19863. sigmaYsum += Math.pow((deviation.x * Math.sin(theta)) + (deviation.y * Math.cos(theta)), 2) * weight;
  19864. weightsum += weight;
  19865. });
  19866. var sigmaX = Math.sqrt(2 * sigmaXsum / weightsum);
  19867. var sigmaY = Math.sqrt(2 * sigmaYsum / weightsum);
  19868. var theEllipse = ellipse(meanCenter, sigmaX, sigmaY, {units: 'degrees', angle: thetaDeg, steps: steps, properties: properties});
  19869. var pointsWithinEllipse = pointsWithinPolygon(points$$1, featureCollection([theEllipse]));
  19870. var standardDeviationalEllipseProperties = {
  19871. meanCenterCoordinates: getCoords(meanCenter),
  19872. semiMajorAxis: sigmaX,
  19873. semiMinorAxis: sigmaY,
  19874. numberOfFeatures: numberOfFeatures,
  19875. angle: thetaDeg,
  19876. percentageWithinEllipse: 100 * coordAll(pointsWithinEllipse).length / numberOfFeatures
  19877. };
  19878. theEllipse.properties.standardDeviationalEllipse = standardDeviationalEllipseProperties;
  19879. return theEllipse;
  19880. }
  19881. /**
  19882. * Get x_i - X and y_i - Y
  19883. *
  19884. * @private
  19885. * @param {Array} coordinates Array of [x_i, y_i]
  19886. * @param {Array} center Array of [X, Y]
  19887. * @returns {Object} { x: n, y: m }
  19888. */
  19889. function getDeviations(coordinates, center) {
  19890. return {
  19891. x: coordinates[0] - center[0],
  19892. y: coordinates[1] - center[1]
  19893. };
  19894. }
  19895. /**
  19896. * Returns a random position within a {@link bounding box}.
  19897. *
  19898. * @name randomPosition
  19899. * @param {Array<number>} [bbox=[-180, -90, 180, 90]] a bounding box inside of which positions are placed.
  19900. * @returns {Array<number>} Position [longitude, latitude]
  19901. * @example
  19902. * var position = turf.randomPosition([-180, -90, 180, 90])
  19903. * //=position
  19904. */
  19905. function randomPosition(bbox) {
  19906. if (isObject(bbox)) bbox = bbox.bbox;
  19907. if (bbox && !Array.isArray(bbox)) throw new Error('bbox is invalid');
  19908. if (bbox) return coordInBBox(bbox);
  19909. else return [lon(), lat()];
  19910. }
  19911. /**
  19912. * Returns a random {@link point}.
  19913. *
  19914. * @name randomPoint
  19915. * @param {number} [count=1] how many geometries will be generated
  19916. * @param {Object} [options={}] Optional parameters
  19917. * @param {Array<number>} [options.bbox=[-180, -90, 180, 90]] a bounding box inside of which geometries are placed.
  19918. * @returns {FeatureCollection<Point>} GeoJSON FeatureCollection of points
  19919. * @example
  19920. * var points = turf.randomPoint(25, {bbox: [-180, -90, 180, 90]})
  19921. * //=points
  19922. */
  19923. function randomPoint(count, options) {
  19924. // Optional parameters
  19925. options = options || {};
  19926. if (!isObject(options)) throw new Error('options is invalid');
  19927. var bbox = options.bbox;
  19928. if (count === undefined || count === null) count = 1;
  19929. var features = [];
  19930. for (var i = 0; i < count; i++) {
  19931. features.push(point(randomPosition(bbox)));
  19932. }
  19933. return featureCollection(features);
  19934. }
  19935. /**
  19936. * Returns a random {@link polygon}.
  19937. *
  19938. * @name randomPolygon
  19939. * @param {number} [count=1] how many geometries will be generated
  19940. * @param {Object} [options={}] Optional parameters
  19941. * @param {Array<number>} [options.bbox=[-180, -90, 180, 90]] a bounding box inside of which geometries are placed.
  19942. * @param {number} [options.num_vertices=10] is how many coordinates each LineString will contain.
  19943. * @param {number} [options.max_radial_length=10] is the maximum number of decimal degrees latitude or longitude that a vertex can reach out of the center of the Polygon.
  19944. * @returns {FeatureCollection<Point>} GeoJSON FeatureCollection of points
  19945. * @example
  19946. * var polygons = turf.randomPolygon(25, {bbox: [-180, -90, 180, 90]})
  19947. * //=polygons
  19948. */
  19949. function randomPolygon(count, options) {
  19950. // Optional parameters
  19951. options = options || {};
  19952. if (!isObject(options)) throw new Error('options is invalid');
  19953. var bbox = options.bbox;
  19954. var num_vertices = options.num_vertices;
  19955. var max_radial_length = options.max_radial_length;
  19956. if (count === undefined || count === null) count = 1;
  19957. // Validation
  19958. if (!isNumber(num_vertices)) num_vertices = 10;
  19959. if (!isNumber(max_radial_length)) max_radial_length = 10;
  19960. var features = [];
  19961. for (var i = 0; i < count; i++) {
  19962. var vertices = [],
  19963. circle_offsets = Array.apply(null,
  19964. new Array(num_vertices + 1)).map(Math.random);
  19965. circle_offsets.forEach(sumOffsets);
  19966. circle_offsets.forEach(scaleOffsets);
  19967. vertices[vertices.length - 1] = vertices[0]; // close the ring
  19968. // center the polygon around something
  19969. vertices = vertices.map(vertexToCoordinate(randomPosition(bbox)));
  19970. features.push(polygon([vertices]));
  19971. }
  19972. function sumOffsets(cur, index, arr) {
  19973. arr[index] = (index > 0) ? cur + arr[index - 1] : cur;
  19974. }
  19975. function scaleOffsets(cur) {
  19976. cur = cur * 2 * Math.PI / circle_offsets[circle_offsets.length - 1];
  19977. var radial_scaler = Math.random();
  19978. vertices.push([
  19979. radial_scaler * max_radial_length * Math.sin(cur),
  19980. radial_scaler * max_radial_length * Math.cos(cur)
  19981. ]);
  19982. }
  19983. return featureCollection(features);
  19984. }
  19985. /**
  19986. * Returns a random {@link linestring}.
  19987. *
  19988. * @name randomLineString
  19989. * @param {number} [count=1] how many geometries will be generated
  19990. * @param {Object} [options={}] Optional parameters
  19991. * @param {Array<number>} [options.bbox=[-180, -90, 180, 90]] a bounding box inside of which geometries are placed.
  19992. * @param {number} [options.num_vertices=10] is how many coordinates each LineString will contain.
  19993. * @param {number} [options.max_length=0.0001] is the maximum number of decimal degrees that a vertex can be from its predecessor
  19994. * @param {number} [options.max_rotation=Math.PI / 8] is the maximum number of radians that a line segment can turn from the previous segment.
  19995. * @returns {FeatureCollection<Point>} GeoJSON FeatureCollection of points
  19996. * @example
  19997. * var lineStrings = turf.randomLineString(25, {bbox: [-180, -90, 180, 90]})
  19998. * //=lineStrings
  19999. */
  20000. function randomLineString(count, options) {
  20001. // Optional parameters
  20002. options = options || {};
  20003. if (!isObject(options)) throw new Error('options is invalid');
  20004. var bbox = options.bbox;
  20005. var num_vertices = options.num_vertices;
  20006. var max_length = options.max_length;
  20007. var max_rotation = options.max_rotation;
  20008. if (count === undefined || count === null) count = 1;
  20009. // Default parameters
  20010. if (!isNumber(num_vertices) || num_vertices < 2) num_vertices = 10;
  20011. if (!isNumber(max_length)) max_length = 0.0001;
  20012. if (!isNumber(max_rotation)) max_rotation = Math.PI / 8;
  20013. var features = [];
  20014. for (var i = 0; i < count; i++) {
  20015. var startingPoint = randomPosition(bbox);
  20016. var vertices = [startingPoint];
  20017. for (var j = 0; j < num_vertices - 1; j++) {
  20018. var priorAngle = (j === 0) ?
  20019. Math.random() * 2 * Math.PI :
  20020. Math.tan(
  20021. (vertices[j][1] - vertices[j - 1][1]) /
  20022. (vertices[j][0] - vertices[j - 1][0])
  20023. );
  20024. var angle = priorAngle + (Math.random() - 0.5) * max_rotation * 2;
  20025. var distance = Math.random() * max_length;
  20026. vertices.push([
  20027. vertices[j][0] + distance * Math.cos(angle),
  20028. vertices[j][1] + distance * Math.sin(angle)
  20029. ]);
  20030. }
  20031. features.push(lineString(vertices));
  20032. }
  20033. return featureCollection(features);
  20034. }
  20035. function vertexToCoordinate(hub) {
  20036. return function (cur) { return [cur[0] + hub[0], cur[1] + hub[1]]; };
  20037. }
  20038. function rnd() { return Math.random() - 0.5; }
  20039. function lon() { return rnd() * 360; }
  20040. function lat() { return rnd() * 180; }
  20041. function coordInBBox(bbox) {
  20042. return [
  20043. (Math.random() * (bbox[2] - bbox[0])) + bbox[0],
  20044. (Math.random() * (bbox[3] - bbox[1])) + bbox[1]];
  20045. }
  20046. var main_es$4 = Object.freeze({
  20047. randomPosition: randomPosition,
  20048. randomPoint: randomPoint,
  20049. randomPolygon: randomPolygon,
  20050. randomLineString: randomLineString
  20051. });
  20052. /**
  20053. * Get Cluster
  20054. *
  20055. * @name getCluster
  20056. * @param {FeatureCollection} geojson GeoJSON Features
  20057. * @param {*} filter Filter used on GeoJSON properties to get Cluster
  20058. * @returns {FeatureCollection} Single Cluster filtered by GeoJSON Properties
  20059. * @example
  20060. * var geojson = turf.featureCollection([
  20061. * turf.point([0, 0], {'marker-symbol': 'circle'}),
  20062. * turf.point([2, 4], {'marker-symbol': 'star'}),
  20063. * turf.point([3, 6], {'marker-symbol': 'star'}),
  20064. * turf.point([5, 1], {'marker-symbol': 'square'}),
  20065. * turf.point([4, 2], {'marker-symbol': 'circle'})
  20066. * ]);
  20067. *
  20068. * // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)
  20069. * var clustered = turf.clustersKmeans(geojson);
  20070. *
  20071. * // Retrieve first cluster (0)
  20072. * var cluster = turf.getCluster(clustered, {cluster: 0});
  20073. * //= cluster
  20074. *
  20075. * // Retrieve cluster based on custom properties
  20076. * turf.getCluster(clustered, {'marker-symbol': 'circle'}).length;
  20077. * //= 2
  20078. * turf.getCluster(clustered, {'marker-symbol': 'square'}).length;
  20079. * //= 1
  20080. */
  20081. function getCluster(geojson, filter) {
  20082. // Validation
  20083. if (!geojson) throw new Error('geojson is required');
  20084. if (geojson.type !== 'FeatureCollection') throw new Error('geojson must be a FeatureCollection');
  20085. if (filter === undefined || filter === null) throw new Error('filter is required');
  20086. // Filter Features
  20087. var features = [];
  20088. featureEach(geojson, function (feature$$1) {
  20089. if (applyFilter(feature$$1.properties, filter)) features.push(feature$$1);
  20090. });
  20091. return featureCollection(features);
  20092. }
  20093. /**
  20094. * Callback for clusterEach
  20095. *
  20096. * @callback clusterEachCallback
  20097. * @param {FeatureCollection} [cluster] The current cluster being processed.
  20098. * @param {*} [clusterValue] Value used to create cluster being processed.
  20099. * @param {number} [currentIndex] The index of the current element being processed in the array.Starts at index 0
  20100. * @returns {void}
  20101. */
  20102. /**
  20103. * clusterEach
  20104. *
  20105. * @name clusterEach
  20106. * @param {FeatureCollection} geojson GeoJSON Features
  20107. * @param {string|number} property GeoJSON property key/value used to create clusters
  20108. * @param {Function} callback a method that takes (cluster, clusterValue, currentIndex)
  20109. * @returns {void}
  20110. * @example
  20111. * var geojson = turf.featureCollection([
  20112. * turf.point([0, 0]),
  20113. * turf.point([2, 4]),
  20114. * turf.point([3, 6]),
  20115. * turf.point([5, 1]),
  20116. * turf.point([4, 2])
  20117. * ]);
  20118. *
  20119. * // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)
  20120. * var clustered = turf.clustersKmeans(geojson);
  20121. *
  20122. * // Iterate over each cluster
  20123. * turf.clusterEach(clustered, 'cluster', function (cluster, clusterValue, currentIndex) {
  20124. * //= cluster
  20125. * //= clusterValue
  20126. * //= currentIndex
  20127. * })
  20128. *
  20129. * // Calculate the total number of clusters
  20130. * var total = 0
  20131. * turf.clusterEach(clustered, 'cluster', function () {
  20132. * total++;
  20133. * });
  20134. *
  20135. * // Create an Array of all the values retrieved from the 'cluster' property
  20136. * var values = []
  20137. * turf.clusterEach(clustered, 'cluster', function (cluster, clusterValue) {
  20138. * values.push(clusterValue);
  20139. * });
  20140. */
  20141. function clusterEach(geojson, property, callback) {
  20142. // Validation
  20143. if (!geojson) throw new Error('geojson is required');
  20144. if (geojson.type !== 'FeatureCollection') throw new Error('geojson must be a FeatureCollection');
  20145. if (property === undefined || property === null) throw new Error('property is required');
  20146. // Create clusters based on property values
  20147. var bins = createBins(geojson, property);
  20148. var values = Object.keys(bins);
  20149. for (var index = 0; index < values.length; index++) {
  20150. var value = values[index];
  20151. var bin = bins[value];
  20152. var features = [];
  20153. for (var i = 0; i < bin.length; i++) {
  20154. features.push(geojson.features[bin[i]]);
  20155. }
  20156. callback(featureCollection(features), value, index);
  20157. }
  20158. }
  20159. /**
  20160. * Callback for clusterReduce
  20161. *
  20162. * The first time the callback function is called, the values provided as arguments depend
  20163. * on whether the reduce method has an initialValue argument.
  20164. *
  20165. * If an initialValue is provided to the reduce method:
  20166. * - The previousValue argument is initialValue.
  20167. * - The currentValue argument is the value of the first element present in the array.
  20168. *
  20169. * If an initialValue is not provided:
  20170. * - The previousValue argument is the value of the first element present in the array.
  20171. * - The currentValue argument is the value of the second element present in the array.
  20172. *
  20173. * @callback clusterReduceCallback
  20174. * @param {*} [previousValue] The accumulated value previously returned in the last invocation
  20175. * of the callback, or initialValue, if supplied.
  20176. * @param {FeatureCollection} [cluster] The current cluster being processed.
  20177. * @param {*} [clusterValue] Value used to create cluster being processed.
  20178. * @param {number} [currentIndex] The index of the current element being processed in the
  20179. * array. Starts at index 0, if an initialValue is provided, and at index 1 otherwise.
  20180. */
  20181. /**
  20182. * Reduce clusters in GeoJSON Features, similar to Array.reduce()
  20183. *
  20184. * @name clusterReduce
  20185. * @param {FeatureCollection} geojson GeoJSON Features
  20186. * @param {string|number} property GeoJSON property key/value used to create clusters
  20187. * @param {Function} callback a method that takes (previousValue, cluster, clusterValue, currentIndex)
  20188. * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
  20189. * @returns {*} The value that results from the reduction.
  20190. * @example
  20191. * var geojson = turf.featureCollection([
  20192. * turf.point([0, 0]),
  20193. * turf.point([2, 4]),
  20194. * turf.point([3, 6]),
  20195. * turf.point([5, 1]),
  20196. * turf.point([4, 2])
  20197. * ]);
  20198. *
  20199. * // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)
  20200. * var clustered = turf.clustersKmeans(geojson);
  20201. *
  20202. * // Iterate over each cluster and perform a calculation
  20203. * var initialValue = 0
  20204. * turf.clusterReduce(clustered, 'cluster', function (previousValue, cluster, clusterValue, currentIndex) {
  20205. * //=previousValue
  20206. * //=cluster
  20207. * //=clusterValue
  20208. * //=currentIndex
  20209. * return previousValue++;
  20210. * }, initialValue);
  20211. *
  20212. * // Calculate the total number of clusters
  20213. * var total = turf.clusterReduce(clustered, 'cluster', function (previousValue) {
  20214. * return previousValue++;
  20215. * }, 0);
  20216. *
  20217. * // Create an Array of all the values retrieved from the 'cluster' property
  20218. * var values = turf.clusterReduce(clustered, 'cluster', function (previousValue, cluster, clusterValue) {
  20219. * return previousValue.concat(clusterValue);
  20220. * }, []);
  20221. */
  20222. function clusterReduce(geojson, property, callback, initialValue) {
  20223. var previousValue = initialValue;
  20224. clusterEach(geojson, property, function (cluster, clusterValue, currentIndex) {
  20225. if (currentIndex === 0 && initialValue === undefined) previousValue = cluster;
  20226. else previousValue = callback(previousValue, cluster, clusterValue, currentIndex);
  20227. });
  20228. return previousValue;
  20229. }
  20230. /**
  20231. * Create Bins
  20232. *
  20233. * @private
  20234. * @param {FeatureCollection} geojson GeoJSON Features
  20235. * @param {string|number} property Property values are used to create bins
  20236. * @returns {Object} bins with Feature IDs
  20237. * @example
  20238. * var geojson = turf.featureCollection([
  20239. * turf.point([0, 0], {cluster: 0, foo: 'null'}),
  20240. * turf.point([2, 4], {cluster: 1, foo: 'bar'}),
  20241. * turf.point([5, 1], {0: 'foo'}),
  20242. * turf.point([3, 6], {cluster: 1}),
  20243. * ]);
  20244. * createBins(geojson, 'cluster');
  20245. * //= { '0': [ 0 ], '1': [ 1, 3 ] }
  20246. */
  20247. function createBins(geojson, property) {
  20248. var bins = {};
  20249. featureEach(geojson, function (feature$$1, i) {
  20250. var properties = feature$$1.properties || {};
  20251. if (properties.hasOwnProperty(property)) {
  20252. var value = properties[property];
  20253. if (bins.hasOwnProperty(value)) bins[value].push(i);
  20254. else bins[value] = [i];
  20255. }
  20256. });
  20257. return bins;
  20258. }
  20259. /**
  20260. * Apply Filter
  20261. *
  20262. * @private
  20263. * @param {*} properties Properties
  20264. * @param {*} filter Filter
  20265. * @returns {boolean} applied Filter to properties
  20266. */
  20267. function applyFilter(properties, filter) {
  20268. if (properties === undefined) return false;
  20269. var filterType = typeof filter;
  20270. // String & Number
  20271. if (filterType === 'number' || filterType === 'string') return properties.hasOwnProperty(filter);
  20272. // Array
  20273. else if (Array.isArray(filter)) {
  20274. for (var i = 0; i < filter.length; i++) {
  20275. if (!applyFilter(properties, filter[i])) return false;
  20276. }
  20277. return true;
  20278. // Object
  20279. } else {
  20280. return propertiesContainsFilter(properties, filter);
  20281. }
  20282. }
  20283. /**
  20284. * Properties contains filter (does not apply deepEqual operations)
  20285. *
  20286. * @private
  20287. * @param {*} properties Properties
  20288. * @param {Object} filter Filter
  20289. * @returns {boolean} does filter equal Properties
  20290. * @example
  20291. * propertiesContainsFilter({foo: 'bar', cluster: 0}, {cluster: 0})
  20292. * //= true
  20293. * propertiesContainsFilter({foo: 'bar', cluster: 0}, {cluster: 1})
  20294. * //= false
  20295. */
  20296. function propertiesContainsFilter(properties, filter) {
  20297. var keys = Object.keys(filter);
  20298. for (var i = 0; i < keys.length; i++) {
  20299. var key = keys[i];
  20300. if (properties[key] !== filter[key]) return false;
  20301. }
  20302. return true;
  20303. }
  20304. /**
  20305. * Filter Properties
  20306. *
  20307. * @private
  20308. * @param {*} properties Properties
  20309. * @param {Array<string>} keys Used to filter Properties
  20310. * @returns {*} filtered Properties
  20311. * @example
  20312. * filterProperties({foo: 'bar', cluster: 0}, ['cluster'])
  20313. * //= {cluster: 0}
  20314. */
  20315. function filterProperties(properties, keys) {
  20316. if (!keys) return {};
  20317. if (!keys.length) return {};
  20318. var newProperties = {};
  20319. for (var i = 0; i < keys.length; i++) {
  20320. var key = keys[i];
  20321. if (properties.hasOwnProperty(key)) newProperties[key] = properties[key];
  20322. }
  20323. return newProperties;
  20324. }
  20325. var main_es$5 = Object.freeze({
  20326. getCluster: getCluster,
  20327. clusterEach: clusterEach,
  20328. clusterReduce: clusterReduce,
  20329. createBins: createBins,
  20330. applyFilter: applyFilter,
  20331. propertiesContainsFilter: propertiesContainsFilter,
  20332. filterProperties: filterProperties
  20333. });
  20334. /* Polyfill service v3.13.0
  20335. * For detailed credits and licence information see http://github.com/financial-times/polyfill-service
  20336. *
  20337. * - Array.prototype.fill, License: CC0 */
  20338. if (!('fill' in Array.prototype)) {
  20339. Object.defineProperty(Array.prototype, 'fill', {
  20340. configurable: true,
  20341. value: function fill (value) {
  20342. if (this === undefined || this === null) {
  20343. throw new TypeError(this + ' is not an object')
  20344. }
  20345. var arrayLike = Object(this);
  20346. var length = Math.max(Math.min(arrayLike.length, 9007199254740991), 0) || 0;
  20347. var relativeStart = 1 in arguments ? parseInt(Number(arguments[1]), 10) || 0 : 0;
  20348. relativeStart = relativeStart < 0 ? Math.max(length + relativeStart, 0) : Math.min(relativeStart, length);
  20349. var relativeEnd = 2 in arguments && arguments[2] !== undefined ? parseInt(Number(arguments[2]), 10) || 0 : length;
  20350. relativeEnd = relativeEnd < 0 ? Math.max(length + arguments[2], 0) : Math.min(relativeEnd, length);
  20351. while (relativeStart < relativeEnd) {
  20352. arrayLike[relativeStart] = value;
  20353. ++relativeStart;
  20354. }
  20355. return arrayLike
  20356. },
  20357. writable: true
  20358. });
  20359. }
  20360. /**
  20361. * Polyfill for IE support
  20362. */
  20363. Number.isFinite = Number.isFinite || function (value) {
  20364. return typeof value === 'number' && isFinite(value)
  20365. };
  20366. Number.isInteger = Number.isInteger || function (val) {
  20367. return typeof val === 'number' &&
  20368. isFinite(val) &&
  20369. Math.floor(val) === val
  20370. };
  20371. Number.parseFloat = Number.parseFloat || parseFloat;
  20372. Number.isNaN = Number.isNaN || function (value) {
  20373. return value !== value // eslint-disable-line
  20374. };
  20375. /**
  20376. * Polyfill for IE support
  20377. */
  20378. Math.trunc = Math.trunc || function (x) {
  20379. return x < 0 ? Math.ceil(x) : Math.floor(x)
  20380. };
  20381. var NumberUtil = function NumberUtil () {};
  20382. NumberUtil.prototype.interfaces_ = function interfaces_ () {
  20383. return []
  20384. };
  20385. NumberUtil.prototype.getClass = function getClass () {
  20386. return NumberUtil
  20387. };
  20388. NumberUtil.prototype.equalsWithTolerance = function equalsWithTolerance (x1, x2, tolerance) {
  20389. return Math.abs(x1 - x2) <= tolerance
  20390. };
  20391. var IllegalArgumentException = function IllegalArgumentException () {};
  20392. var Double = function Double () {};
  20393. var staticAccessors$1 = { MAX_VALUE: { configurable: true } };
  20394. Double.isNaN = function isNaN (n) { return Number.isNaN(n) };
  20395. Double.doubleToLongBits = function doubleToLongBits (n) { return n };
  20396. Double.longBitsToDouble = function longBitsToDouble (n) { return n };
  20397. Double.isInfinite = function isInfinite (n) { return !Number.isFinite(n) };
  20398. staticAccessors$1.MAX_VALUE.get = function () { return Number.MAX_VALUE };
  20399. Object.defineProperties( Double, staticAccessors$1 );
  20400. var Comparable = function Comparable () {};
  20401. var Clonable = function Clonable () {};
  20402. var Comparator = function Comparator () {};
  20403. function Serializable () {}
  20404. // import Assert from '../util/Assert'
  20405. var Coordinate = function Coordinate () {
  20406. this.x = null;
  20407. this.y = null;
  20408. this.z = null;
  20409. if (arguments.length === 0) {
  20410. this.x = 0.0;
  20411. this.y = 0.0;
  20412. this.z = Coordinate.NULL_ORDINATE;
  20413. } else if (arguments.length === 1) {
  20414. var c = arguments[0];
  20415. this.x = c.x;
  20416. this.y = c.y;
  20417. this.z = c.z;
  20418. } else if (arguments.length === 2) {
  20419. this.x = arguments[0];
  20420. this.y = arguments[1];
  20421. this.z = Coordinate.NULL_ORDINATE;
  20422. } else if (arguments.length === 3) {
  20423. this.x = arguments[0];
  20424. this.y = arguments[1];
  20425. this.z = arguments[2];
  20426. }
  20427. };
  20428. var staticAccessors = { DimensionalComparator: { configurable: true },serialVersionUID: { configurable: true },NULL_ORDINATE: { configurable: true },X: { configurable: true },Y: { configurable: true },Z: { configurable: true } };
  20429. Coordinate.prototype.setOrdinate = function setOrdinate (ordinateIndex, value) {
  20430. switch (ordinateIndex) {
  20431. case Coordinate.X:
  20432. this.x = value;
  20433. break
  20434. case Coordinate.Y:
  20435. this.y = value;
  20436. break
  20437. case Coordinate.Z:
  20438. this.z = value;
  20439. break
  20440. default:
  20441. throw new IllegalArgumentException('Invalid ordinate index: ' + ordinateIndex)
  20442. }
  20443. };
  20444. Coordinate.prototype.equals2D = function equals2D () {
  20445. if (arguments.length === 1) {
  20446. var other = arguments[0];
  20447. if (this.x !== other.x) {
  20448. return false
  20449. }
  20450. if (this.y !== other.y) {
  20451. return false
  20452. }
  20453. return true
  20454. } else if (arguments.length === 2) {
  20455. var c = arguments[0];
  20456. var tolerance = arguments[1];
  20457. if (!NumberUtil.equalsWithTolerance(this.x, c.x, tolerance)) {
  20458. return false
  20459. }
  20460. if (!NumberUtil.equalsWithTolerance(this.y, c.y, tolerance)) {
  20461. return false
  20462. }
  20463. return true
  20464. }
  20465. };
  20466. Coordinate.prototype.getOrdinate = function getOrdinate (ordinateIndex) {
  20467. switch (ordinateIndex) {
  20468. case Coordinate.X:
  20469. return this.x
  20470. case Coordinate.Y:
  20471. return this.y
  20472. case Coordinate.Z:
  20473. return this.z
  20474. default:
  20475. }
  20476. throw new IllegalArgumentException('Invalid ordinate index: ' + ordinateIndex)
  20477. };
  20478. Coordinate.prototype.equals3D = function equals3D (other) {
  20479. return this.x === other.x &&
  20480. this.y === other.y &&
  20481. ((this.z === other.z || Double.isNaN(this.z)) &&
  20482. Double.isNaN(other.z))
  20483. };
  20484. Coordinate.prototype.equals = function equals (other) {
  20485. if (!(other instanceof Coordinate)) {
  20486. return false
  20487. }
  20488. return this.equals2D(other)
  20489. };
  20490. Coordinate.prototype.equalInZ = function equalInZ (c, tolerance) {
  20491. return NumberUtil.equalsWithTolerance(this.z, c.z, tolerance)
  20492. };
  20493. Coordinate.prototype.compareTo = function compareTo (o) {
  20494. var other = o;
  20495. if (this.x < other.x) { return -1 }
  20496. if (this.x > other.x) { return 1 }
  20497. if (this.y < other.y) { return -1 }
  20498. if (this.y > other.y) { return 1 }
  20499. return 0
  20500. };
  20501. Coordinate.prototype.clone = function clone () {
  20502. // try {
  20503. // var coord = null
  20504. // return coord
  20505. // } catch (e) {
  20506. // if (e instanceof CloneNotSupportedException) {
  20507. // Assert.shouldNeverReachHere("this shouldn't happen because this class is Cloneable")
  20508. // return null
  20509. // } else throw e
  20510. // } finally {}
  20511. };
  20512. Coordinate.prototype.copy = function copy () {
  20513. return new Coordinate(this)
  20514. };
  20515. Coordinate.prototype.toString = function toString () {
  20516. return '(' + this.x + ', ' + this.y + ', ' + this.z + ')'
  20517. };
  20518. Coordinate.prototype.distance3D = function distance3D (c) {
  20519. var dx = this.x - c.x;
  20520. var dy = this.y - c.y;
  20521. var dz = this.z - c.z;
  20522. return Math.sqrt(dx * dx + dy * dy + dz * dz)
  20523. };
  20524. Coordinate.prototype.distance = function distance (c) {
  20525. var dx = this.x - c.x;
  20526. var dy = this.y - c.y;
  20527. return Math.sqrt(dx * dx + dy * dy)
  20528. };
  20529. Coordinate.prototype.hashCode = function hashCode () {
  20530. var result = 17;
  20531. result = 37 * result + Coordinate.hashCode(this.x);
  20532. result = 37 * result + Coordinate.hashCode(this.y);
  20533. return result
  20534. };
  20535. Coordinate.prototype.setCoordinate = function setCoordinate (other) {
  20536. this.x = other.x;
  20537. this.y = other.y;
  20538. this.z = other.z;
  20539. };
  20540. Coordinate.prototype.interfaces_ = function interfaces_ () {
  20541. return [Comparable, Clonable, Serializable]
  20542. };
  20543. Coordinate.prototype.getClass = function getClass () {
  20544. return Coordinate
  20545. };
  20546. Coordinate.hashCode = function hashCode () {
  20547. if (arguments.length === 1) {
  20548. var x = arguments[0];
  20549. var f = Double.doubleToLongBits(x);
  20550. return Math.trunc((f ^ f) >>> 32)
  20551. }
  20552. };
  20553. staticAccessors.DimensionalComparator.get = function () { return DimensionalComparator };
  20554. staticAccessors.serialVersionUID.get = function () { return 6683108902428366910 };
  20555. staticAccessors.NULL_ORDINATE.get = function () { return Double.NaN };
  20556. staticAccessors.X.get = function () { return 0 };
  20557. staticAccessors.Y.get = function () { return 1 };
  20558. staticAccessors.Z.get = function () { return 2 };
  20559. Object.defineProperties( Coordinate, staticAccessors );
  20560. var DimensionalComparator = function DimensionalComparator (dimensionsToTest) {
  20561. this._dimensionsToTest = 2;
  20562. if (arguments.length === 0) {} else if (arguments.length === 1) {
  20563. var dimensionsToTest$1 = arguments[0];
  20564. if (dimensionsToTest$1 !== 2 && dimensionsToTest$1 !== 3) { throw new IllegalArgumentException('only 2 or 3 dimensions may be specified') }
  20565. this._dimensionsToTest = dimensionsToTest$1;
  20566. }
  20567. };
  20568. DimensionalComparator.prototype.compare = function compare (o1, o2) {
  20569. var c1 = o1;
  20570. var c2 = o2;
  20571. var compX = DimensionalComparator.compare(c1.x, c2.x);
  20572. if (compX !== 0) { return compX }
  20573. var compY = DimensionalComparator.compare(c1.y, c2.y);
  20574. if (compY !== 0) { return compY }
  20575. if (this._dimensionsToTest <= 2) { return 0 }
  20576. var compZ = DimensionalComparator.compare(c1.z, c2.z);
  20577. return compZ
  20578. };
  20579. DimensionalComparator.prototype.interfaces_ = function interfaces_ () {
  20580. return [Comparator]
  20581. };
  20582. DimensionalComparator.prototype.getClass = function getClass () {
  20583. return DimensionalComparator
  20584. };
  20585. DimensionalComparator.compare = function compare (a, b) {
  20586. if (a < b) { return -1 }
  20587. if (a > b) { return 1 }
  20588. if (Double.isNaN(a)) {
  20589. if (Double.isNaN(b)) { return 0 }
  20590. return -1
  20591. }
  20592. if (Double.isNaN(b)) { return 1 }
  20593. return 0
  20594. };
  20595. // import hasInterface from '../../../../hasInterface'
  20596. // import CoordinateSequence from './CoordinateSequence'
  20597. var CoordinateSequenceFactory = function CoordinateSequenceFactory () {};
  20598. CoordinateSequenceFactory.prototype.create = function create () {
  20599. // if (arguments.length === 1) {
  20600. // if (arguments[0] instanceof Array) {
  20601. // let coordinates = arguments[0]
  20602. // } else if (hasInterface(arguments[0], CoordinateSequence)) {
  20603. // let coordSeq = arguments[0]
  20604. // }
  20605. // } else if (arguments.length === 2) {
  20606. // let size = arguments[0]
  20607. // let dimension = arguments[1]
  20608. // }
  20609. };
  20610. CoordinateSequenceFactory.prototype.interfaces_ = function interfaces_ () {
  20611. return []
  20612. };
  20613. CoordinateSequenceFactory.prototype.getClass = function getClass () {
  20614. return CoordinateSequenceFactory
  20615. };
  20616. var Location = function Location () {};
  20617. var staticAccessors$4 = { INTERIOR: { configurable: true },BOUNDARY: { configurable: true },EXTERIOR: { configurable: true },NONE: { configurable: true } };
  20618. Location.prototype.interfaces_ = function interfaces_ () {
  20619. return []
  20620. };
  20621. Location.prototype.getClass = function getClass () {
  20622. return Location
  20623. };
  20624. Location.toLocationSymbol = function toLocationSymbol (locationValue) {
  20625. switch (locationValue) {
  20626. case Location.EXTERIOR:
  20627. return 'e'
  20628. case Location.BOUNDARY:
  20629. return 'b'
  20630. case Location.INTERIOR:
  20631. return 'i'
  20632. case Location.NONE:
  20633. return '-'
  20634. default:
  20635. }
  20636. throw new IllegalArgumentException('Unknown location value: ' + locationValue)
  20637. };
  20638. staticAccessors$4.INTERIOR.get = function () { return 0 };
  20639. staticAccessors$4.BOUNDARY.get = function () { return 1 };
  20640. staticAccessors$4.EXTERIOR.get = function () { return 2 };
  20641. staticAccessors$4.NONE.get = function () { return -1 };
  20642. Object.defineProperties( Location, staticAccessors$4 );
  20643. var hasInterface = function (o, i) {
  20644. return o.interfaces_ && o.interfaces_().indexOf(i) > -1
  20645. };
  20646. var MathUtil = function MathUtil () {};
  20647. var staticAccessors$5 = { LOG_10: { configurable: true } };
  20648. MathUtil.prototype.interfaces_ = function interfaces_ () {
  20649. return []
  20650. };
  20651. MathUtil.prototype.getClass = function getClass () {
  20652. return MathUtil
  20653. };
  20654. MathUtil.log10 = function log10 (x) {
  20655. var ln = Math.log(x);
  20656. if (Double.isInfinite(ln)) { return ln }
  20657. if (Double.isNaN(ln)) { return ln }
  20658. return ln / MathUtil.LOG_10
  20659. };
  20660. MathUtil.min = function min (v1, v2, v3, v4) {
  20661. var min = v1;
  20662. if (v2 < min) { min = v2; }
  20663. if (v3 < min) { min = v3; }
  20664. if (v4 < min) { min = v4; }
  20665. return min
  20666. };
  20667. MathUtil.clamp = function clamp () {
  20668. if (typeof arguments[2] === 'number' && (typeof arguments[0] === 'number' && typeof arguments[1] === 'number')) {
  20669. var x = arguments[0];
  20670. var min = arguments[1];
  20671. var max = arguments[2];
  20672. if (x < min) { return min }
  20673. if (x > max) { return max }
  20674. return x
  20675. } else if (Number.isInteger(arguments[2]) && (Number.isInteger(arguments[0]) && Number.isInteger(arguments[1]))) {
  20676. var x$1 = arguments[0];
  20677. var min$1 = arguments[1];
  20678. var max$1 = arguments[2];
  20679. if (x$1 < min$1) { return min$1 }
  20680. if (x$1 > max$1) { return max$1 }
  20681. return x$1
  20682. }
  20683. };
  20684. MathUtil.wrap = function wrap (index, max) {
  20685. if (index < 0) {
  20686. return max - -index % max
  20687. }
  20688. return index % max
  20689. };
  20690. MathUtil.max = function max () {
  20691. if (arguments.length === 3) {
  20692. var v1 = arguments[0];
  20693. var v2 = arguments[1];
  20694. var v3 = arguments[2];
  20695. var max = v1;
  20696. if (v2 > max) { max = v2; }
  20697. if (v3 > max) { max = v3; }
  20698. return max
  20699. } else if (arguments.length === 4) {
  20700. var v1$1 = arguments[0];
  20701. var v2$1 = arguments[1];
  20702. var v3$1 = arguments[2];
  20703. var v4 = arguments[3];
  20704. var max$1 = v1$1;
  20705. if (v2$1 > max$1) { max$1 = v2$1; }
  20706. if (v3$1 > max$1) { max$1 = v3$1; }
  20707. if (v4 > max$1) { max$1 = v4; }
  20708. return max$1
  20709. }
  20710. };
  20711. MathUtil.average = function average (x1, x2) {
  20712. return (x1 + x2) / 2.0
  20713. };
  20714. staticAccessors$5.LOG_10.get = function () { return Math.log(10) };
  20715. Object.defineProperties( MathUtil, staticAccessors$5 );
  20716. var StringBuffer = function StringBuffer (str) {
  20717. this.str = str;
  20718. };
  20719. StringBuffer.prototype.append = function append (e) {
  20720. this.str += e;
  20721. };
  20722. StringBuffer.prototype.setCharAt = function setCharAt (i, c) {
  20723. this.str = this.str.substr(0, i) + c + this.str.substr(i + 1);
  20724. };
  20725. StringBuffer.prototype.toString = function toString (e) {
  20726. return this.str
  20727. };
  20728. var Integer = function Integer (value) {
  20729. this.value = value;
  20730. };
  20731. Integer.prototype.intValue = function intValue () {
  20732. return this.value
  20733. };
  20734. Integer.prototype.compareTo = function compareTo (o) {
  20735. if (this.value < o) { return -1 }
  20736. if (this.value > o) { return 1 }
  20737. return 0
  20738. };
  20739. Integer.isNaN = function isNaN (n) { return Number.isNaN(n) };
  20740. var Character = function Character () {};
  20741. Character.isWhitespace = function isWhitespace (c) { return ((c <= 32 && c >= 0) || c === 127) };
  20742. Character.toUpperCase = function toUpperCase (c) { return c.toUpperCase() };
  20743. var DD = function DD () {
  20744. this._hi = 0.0;
  20745. this._lo = 0.0;
  20746. if (arguments.length === 0) {
  20747. this.init(0.0);
  20748. } else if (arguments.length === 1) {
  20749. if (typeof arguments[0] === 'number') {
  20750. var x = arguments[0];
  20751. this.init(x);
  20752. } else if (arguments[0] instanceof DD) {
  20753. var dd = arguments[0];
  20754. this.init(dd);
  20755. } else if (typeof arguments[0] === 'string') {
  20756. var str = arguments[0];
  20757. DD.call(this, DD.parse(str));
  20758. }
  20759. } else if (arguments.length === 2) {
  20760. var hi = arguments[0];
  20761. var lo = arguments[1];
  20762. this.init(hi, lo);
  20763. }
  20764. };
  20765. var staticAccessors$7 = { PI: { configurable: true },TWO_PI: { configurable: true },PI_2: { configurable: true },E: { configurable: true },NaN: { configurable: true },EPS: { configurable: true },SPLIT: { configurable: true },MAX_PRINT_DIGITS: { configurable: true },TEN: { configurable: true },ONE: { configurable: true },SCI_NOT_EXPONENT_CHAR: { configurable: true },SCI_NOT_ZERO: { configurable: true } };
  20766. DD.prototype.le = function le (y) {
  20767. return (this._hi < y._hi || this._hi === y._hi) && this._lo <= y._lo
  20768. };
  20769. DD.prototype.extractSignificantDigits = function extractSignificantDigits (insertDecimalPoint, magnitude) {
  20770. var y = this.abs();
  20771. var mag = DD.magnitude(y._hi);
  20772. var scale = DD.TEN.pow(mag);
  20773. y = y.divide(scale);
  20774. if (y.gt(DD.TEN)) {
  20775. y = y.divide(DD.TEN);
  20776. mag += 1;
  20777. } else if (y.lt(DD.ONE)) {
  20778. y = y.multiply(DD.TEN);
  20779. mag -= 1;
  20780. }
  20781. var decimalPointPos = mag + 1;
  20782. var buf = new StringBuffer();
  20783. var numDigits = DD.MAX_PRINT_DIGITS - 1;
  20784. for (var i = 0; i <= numDigits; i++) {
  20785. if (insertDecimalPoint && i === decimalPointPos) {
  20786. buf.append('.');
  20787. }
  20788. var digit = Math.trunc(y._hi);
  20789. if (digit < 0) {
  20790. break
  20791. }
  20792. var rebiasBy10 = false;
  20793. var digitChar = 0;
  20794. if (digit > 9) {
  20795. rebiasBy10 = true;
  20796. digitChar = '9';
  20797. } else {
  20798. digitChar = '0' + digit;
  20799. }
  20800. buf.append(digitChar);
  20801. y = y.subtract(DD.valueOf(digit)).multiply(DD.TEN);
  20802. if (rebiasBy10) { y.selfAdd(DD.TEN); }
  20803. var continueExtractingDigits = true;
  20804. var remMag = DD.magnitude(y._hi);
  20805. if (remMag < 0 && Math.abs(remMag) >= numDigits - i) { continueExtractingDigits = false; }
  20806. if (!continueExtractingDigits) { break }
  20807. }
  20808. magnitude[0] = mag;
  20809. return buf.toString()
  20810. };
  20811. DD.prototype.sqr = function sqr () {
  20812. return this.multiply(this)
  20813. };
  20814. DD.prototype.doubleValue = function doubleValue () {
  20815. return this._hi + this._lo
  20816. };
  20817. DD.prototype.subtract = function subtract () {
  20818. if (arguments[0] instanceof DD) {
  20819. var y = arguments[0];
  20820. return this.add(y.negate())
  20821. } else if (typeof arguments[0] === 'number') {
  20822. var y$1 = arguments[0];
  20823. return this.add(-y$1)
  20824. }
  20825. };
  20826. DD.prototype.equals = function equals () {
  20827. if (arguments.length === 1) {
  20828. var y = arguments[0];
  20829. return this._hi === y._hi && this._lo === y._lo
  20830. }
  20831. };
  20832. DD.prototype.isZero = function isZero () {
  20833. return this._hi === 0.0 && this._lo === 0.0
  20834. };
  20835. DD.prototype.selfSubtract = function selfSubtract () {
  20836. if (arguments[0] instanceof DD) {
  20837. var y = arguments[0];
  20838. if (this.isNaN()) { return this }
  20839. return this.selfAdd(-y._hi, -y._lo)
  20840. } else if (typeof arguments[0] === 'number') {
  20841. var y$1 = arguments[0];
  20842. if (this.isNaN()) { return this }
  20843. return this.selfAdd(-y$1, 0.0)
  20844. }
  20845. };
  20846. DD.prototype.getSpecialNumberString = function getSpecialNumberString () {
  20847. if (this.isZero()) { return '0.0' }
  20848. if (this.isNaN()) { return 'NaN ' }
  20849. return null
  20850. };
  20851. DD.prototype.min = function min (x) {
  20852. if (this.le(x)) {
  20853. return this
  20854. } else {
  20855. return x
  20856. }
  20857. };
  20858. DD.prototype.selfDivide = function selfDivide () {
  20859. if (arguments.length === 1) {
  20860. if (arguments[0] instanceof DD) {
  20861. var y = arguments[0];
  20862. return this.selfDivide(y._hi, y._lo)
  20863. } else if (typeof arguments[0] === 'number') {
  20864. var y$1 = arguments[0];
  20865. return this.selfDivide(y$1, 0.0)
  20866. }
  20867. } else if (arguments.length === 2) {
  20868. var yhi = arguments[0];
  20869. var ylo = arguments[1];
  20870. var hc = null;
  20871. var tc = null;
  20872. var hy = null;
  20873. var ty = null;
  20874. var C = null;
  20875. var c = null;
  20876. var U = null;
  20877. var u = null;
  20878. C = this._hi / yhi;
  20879. c = DD.SPLIT * C;
  20880. hc = c - C;
  20881. u = DD.SPLIT * yhi;
  20882. hc = c - hc;
  20883. tc = C - hc;
  20884. hy = u - yhi;
  20885. U = C * yhi;
  20886. hy = u - hy;
  20887. ty = yhi - hy;
  20888. u = hc * hy - U + hc * ty + tc * hy + tc * ty;
  20889. c = (this._hi - U - u + this._lo - C * ylo) / yhi;
  20890. u = C + c;
  20891. this._hi = u;
  20892. this._lo = C - u + c;
  20893. return this
  20894. }
  20895. };
  20896. DD.prototype.dump = function dump () {
  20897. return 'DD<' + this._hi + ', ' + this._lo + '>'
  20898. };
  20899. DD.prototype.divide = function divide () {
  20900. if (arguments[0] instanceof DD) {
  20901. var y = arguments[0];
  20902. var hc = null;
  20903. var tc = null;
  20904. var hy = null;
  20905. var ty = null;
  20906. var C = null;
  20907. var c = null;
  20908. var U = null;
  20909. var u = null;
  20910. C = this._hi / y._hi;
  20911. c = DD.SPLIT * C;
  20912. hc = c - C;
  20913. u = DD.SPLIT * y._hi;
  20914. hc = c - hc;
  20915. tc = C - hc;
  20916. hy = u - y._hi;
  20917. U = C * y._hi;
  20918. hy = u - hy;
  20919. ty = y._hi - hy;
  20920. u = hc * hy - U + hc * ty + tc * hy + tc * ty;
  20921. c = (this._hi - U - u + this._lo - C * y._lo) / y._hi;
  20922. u = C + c;
  20923. var zhi = u;
  20924. var zlo = C - u + c;
  20925. return new DD(zhi, zlo)
  20926. } else if (typeof arguments[0] === 'number') {
  20927. var y$1 = arguments[0];
  20928. if (Double.isNaN(y$1)) { return DD.createNaN() }
  20929. return DD.copy(this).selfDivide(y$1, 0.0)
  20930. }
  20931. };
  20932. DD.prototype.ge = function ge (y) {
  20933. return (this._hi > y._hi || this._hi === y._hi) && this._lo >= y._lo
  20934. };
  20935. DD.prototype.pow = function pow (exp) {
  20936. if (exp === 0.0) { return DD.valueOf(1.0) }
  20937. var r = new DD(this);
  20938. var s = DD.valueOf(1.0);
  20939. var n = Math.abs(exp);
  20940. if (n > 1) {
  20941. while (n > 0) {
  20942. if (n % 2 === 1) {
  20943. s.selfMultiply(r);
  20944. }
  20945. n /= 2;
  20946. if (n > 0) { r = r.sqr(); }
  20947. }
  20948. } else {
  20949. s = r;
  20950. }
  20951. if (exp < 0) { return s.reciprocal() }
  20952. return s
  20953. };
  20954. DD.prototype.ceil = function ceil () {
  20955. if (this.isNaN()) { return DD.NaN }
  20956. var fhi = Math.ceil(this._hi);
  20957. var flo = 0.0;
  20958. if (fhi === this._hi) {
  20959. flo = Math.ceil(this._lo);
  20960. }
  20961. return new DD(fhi, flo)
  20962. };
  20963. DD.prototype.compareTo = function compareTo (o) {
  20964. var other = o;
  20965. if (this._hi < other._hi) { return -1 }
  20966. if (this._hi > other._hi) { return 1 }
  20967. if (this._lo < other._lo) { return -1 }
  20968. if (this._lo > other._lo) { return 1 }
  20969. return 0
  20970. };
  20971. DD.prototype.rint = function rint () {
  20972. if (this.isNaN()) { return this }
  20973. var plus5 = this.add(0.5);
  20974. return plus5.floor()
  20975. };
  20976. DD.prototype.setValue = function setValue () {
  20977. if (arguments[0] instanceof DD) {
  20978. var value = arguments[0];
  20979. this.init(value);
  20980. return this
  20981. } else if (typeof arguments[0] === 'number') {
  20982. var value$1 = arguments[0];
  20983. this.init(value$1);
  20984. return this
  20985. }
  20986. };
  20987. DD.prototype.max = function max (x) {
  20988. if (this.ge(x)) {
  20989. return this
  20990. } else {
  20991. return x
  20992. }
  20993. };
  20994. DD.prototype.sqrt = function sqrt () {
  20995. if (this.isZero()) { return DD.valueOf(0.0) }
  20996. if (this.isNegative()) {
  20997. return DD.NaN
  20998. }
  20999. var x = 1.0 / Math.sqrt(this._hi);
  21000. var ax = this._hi * x;
  21001. var axdd = DD.valueOf(ax);
  21002. var diffSq = this.subtract(axdd.sqr());
  21003. var d2 = diffSq._hi * (x * 0.5);
  21004. return axdd.add(d2)
  21005. };
  21006. DD.prototype.selfAdd = function selfAdd () {
  21007. if (arguments.length === 1) {
  21008. if (arguments[0] instanceof DD) {
  21009. var y = arguments[0];
  21010. return this.selfAdd(y._hi, y._lo)
  21011. } else if (typeof arguments[0] === 'number') {
  21012. var y$1 = arguments[0];
  21013. var H = null;
  21014. var h = null;
  21015. var S = null;
  21016. var s = null;
  21017. var e = null;
  21018. var f = null;
  21019. S = this._hi + y$1;
  21020. e = S - this._hi;
  21021. s = S - e;
  21022. s = y$1 - e + (this._hi - s);
  21023. f = s + this._lo;
  21024. H = S + f;
  21025. h = f + (S - H);
  21026. this._hi = H + h;
  21027. this._lo = h + (H - this._hi);
  21028. return this
  21029. }
  21030. } else if (arguments.length === 2) {
  21031. var yhi = arguments[0];
  21032. var ylo = arguments[1];
  21033. var H$1 = null;
  21034. var h$1 = null;
  21035. var T = null;
  21036. var t = null;
  21037. var S$1 = null;
  21038. var s$1 = null;
  21039. var e$1 = null;
  21040. var f$1 = null;
  21041. S$1 = this._hi + yhi;
  21042. T = this._lo + ylo;
  21043. e$1 = S$1 - this._hi;
  21044. f$1 = T - this._lo;
  21045. s$1 = S$1 - e$1;
  21046. t = T - f$1;
  21047. s$1 = yhi - e$1 + (this._hi - s$1);
  21048. t = ylo - f$1 + (this._lo - t);
  21049. e$1 = s$1 + T;
  21050. H$1 = S$1 + e$1;
  21051. h$1 = e$1 + (S$1 - H$1);
  21052. e$1 = t + h$1;
  21053. var zhi = H$1 + e$1;
  21054. var zlo = e$1 + (H$1 - zhi);
  21055. this._hi = zhi;
  21056. this._lo = zlo;
  21057. return this
  21058. }
  21059. };
  21060. DD.prototype.selfMultiply = function selfMultiply () {
  21061. if (arguments.length === 1) {
  21062. if (arguments[0] instanceof DD) {
  21063. var y = arguments[0];
  21064. return this.selfMultiply(y._hi, y._lo)
  21065. } else if (typeof arguments[0] === 'number') {
  21066. var y$1 = arguments[0];
  21067. return this.selfMultiply(y$1, 0.0)
  21068. }
  21069. } else if (arguments.length === 2) {
  21070. var yhi = arguments[0];
  21071. var ylo = arguments[1];
  21072. var hx = null;
  21073. var tx = null;
  21074. var hy = null;
  21075. var ty = null;
  21076. var C = null;
  21077. var c = null;
  21078. C = DD.SPLIT * this._hi;
  21079. hx = C - this._hi;
  21080. c = DD.SPLIT * yhi;
  21081. hx = C - hx;
  21082. tx = this._hi - hx;
  21083. hy = c - yhi;
  21084. C = this._hi * yhi;
  21085. hy = c - hy;
  21086. ty = yhi - hy;
  21087. c = hx * hy - C + hx * ty + tx * hy + tx * ty + (this._hi * ylo + this._lo * yhi);
  21088. var zhi = C + c;
  21089. hx = C - zhi;
  21090. var zlo = c + hx;
  21091. this._hi = zhi;
  21092. this._lo = zlo;
  21093. return this
  21094. }
  21095. };
  21096. DD.prototype.selfSqr = function selfSqr () {
  21097. return this.selfMultiply(this)
  21098. };
  21099. DD.prototype.floor = function floor () {
  21100. if (this.isNaN()) { return DD.NaN }
  21101. var fhi = Math.floor(this._hi);
  21102. var flo = 0.0;
  21103. if (fhi === this._hi) {
  21104. flo = Math.floor(this._lo);
  21105. }
  21106. return new DD(fhi, flo)
  21107. };
  21108. DD.prototype.negate = function negate () {
  21109. if (this.isNaN()) { return this }
  21110. return new DD(-this._hi, -this._lo)
  21111. };
  21112. DD.prototype.clone = function clone () {
  21113. // try {
  21114. // return null
  21115. // } catch (ex) {
  21116. // if (ex instanceof CloneNotSupportedException) {
  21117. // return null
  21118. // } else throw ex
  21119. // } finally {}
  21120. };
  21121. DD.prototype.multiply = function multiply () {
  21122. if (arguments[0] instanceof DD) {
  21123. var y = arguments[0];
  21124. if (y.isNaN()) { return DD.createNaN() }
  21125. return DD.copy(this).selfMultiply(y)
  21126. } else if (typeof arguments[0] === 'number') {
  21127. var y$1 = arguments[0];
  21128. if (Double.isNaN(y$1)) { return DD.createNaN() }
  21129. return DD.copy(this).selfMultiply(y$1, 0.0)
  21130. }
  21131. };
  21132. DD.prototype.isNaN = function isNaN () {
  21133. return Double.isNaN(this._hi)
  21134. };
  21135. DD.prototype.intValue = function intValue () {
  21136. return Math.trunc(this._hi)
  21137. };
  21138. DD.prototype.toString = function toString () {
  21139. var mag = DD.magnitude(this._hi);
  21140. if (mag >= -3 && mag <= 20) { return this.toStandardNotation() }
  21141. return this.toSciNotation()
  21142. };
  21143. DD.prototype.toStandardNotation = function toStandardNotation () {
  21144. var specialStr = this.getSpecialNumberString();
  21145. if (specialStr !== null) { return specialStr }
  21146. var magnitude = new Array(1).fill(null);
  21147. var sigDigits = this.extractSignificantDigits(true, magnitude);
  21148. var decimalPointPos = magnitude[0] + 1;
  21149. var num = sigDigits;
  21150. if (sigDigits.charAt(0) === '.') {
  21151. num = '0' + sigDigits;
  21152. } else if (decimalPointPos < 0) {
  21153. num = '0.' + DD.stringOfChar('0', -decimalPointPos) + sigDigits;
  21154. } else if (sigDigits.indexOf('.') === -1) {
  21155. var numZeroes = decimalPointPos - sigDigits.length;
  21156. var zeroes = DD.stringOfChar('0', numZeroes);
  21157. num = sigDigits + zeroes + '.0';
  21158. }
  21159. if (this.isNegative()) { return '-' + num }
  21160. return num
  21161. };
  21162. DD.prototype.reciprocal = function reciprocal () {
  21163. var hc = null;
  21164. var tc = null;
  21165. var hy = null;
  21166. var ty = null;
  21167. var C = null;
  21168. var c = null;
  21169. var U = null;
  21170. var u = null;
  21171. C = 1.0 / this._hi;
  21172. c = DD.SPLIT * C;
  21173. hc = c - C;
  21174. u = DD.SPLIT * this._hi;
  21175. hc = c - hc;
  21176. tc = C - hc;
  21177. hy = u - this._hi;
  21178. U = C * this._hi;
  21179. hy = u - hy;
  21180. ty = this._hi - hy;
  21181. u = hc * hy - U + hc * ty + tc * hy + tc * ty;
  21182. c = (1.0 - U - u - C * this._lo) / this._hi;
  21183. var zhi = C + c;
  21184. var zlo = C - zhi + c;
  21185. return new DD(zhi, zlo)
  21186. };
  21187. DD.prototype.toSciNotation = function toSciNotation () {
  21188. if (this.isZero()) { return DD.SCI_NOT_ZERO }
  21189. var specialStr = this.getSpecialNumberString();
  21190. if (specialStr !== null) { return specialStr }
  21191. var magnitude = new Array(1).fill(null);
  21192. var digits = this.extractSignificantDigits(false, magnitude);
  21193. var expStr = DD.SCI_NOT_EXPONENT_CHAR + magnitude[0];
  21194. if (digits.charAt(0) === '0') {
  21195. throw new Error('Found leading zero: ' + digits)
  21196. }
  21197. var trailingDigits = '';
  21198. if (digits.length > 1) { trailingDigits = digits.substring(1); }
  21199. var digitsWithDecimal = digits.charAt(0) + '.' + trailingDigits;
  21200. if (this.isNegative()) { return '-' + digitsWithDecimal + expStr }
  21201. return digitsWithDecimal + expStr
  21202. };
  21203. DD.prototype.abs = function abs () {
  21204. if (this.isNaN()) { return DD.NaN }
  21205. if (this.isNegative()) { return this.negate() }
  21206. return new DD(this)
  21207. };
  21208. DD.prototype.isPositive = function isPositive () {
  21209. return (this._hi > 0.0 || this._hi === 0.0) && this._lo > 0.0
  21210. };
  21211. DD.prototype.lt = function lt (y) {
  21212. return (this._hi < y._hi || this._hi === y._hi) && this._lo < y._lo
  21213. };
  21214. DD.prototype.add = function add () {
  21215. if (arguments[0] instanceof DD) {
  21216. var y = arguments[0];
  21217. return DD.copy(this).selfAdd(y)
  21218. } else if (typeof arguments[0] === 'number') {
  21219. var y$1 = arguments[0];
  21220. return DD.copy(this).selfAdd(y$1)
  21221. }
  21222. };
  21223. DD.prototype.init = function init () {
  21224. if (arguments.length === 1) {
  21225. if (typeof arguments[0] === 'number') {
  21226. var x = arguments[0];
  21227. this._hi = x;
  21228. this._lo = 0.0;
  21229. } else if (arguments[0] instanceof DD) {
  21230. var dd = arguments[0];
  21231. this._hi = dd._hi;
  21232. this._lo = dd._lo;
  21233. }
  21234. } else if (arguments.length === 2) {
  21235. var hi = arguments[0];
  21236. var lo = arguments[1];
  21237. this._hi = hi;
  21238. this._lo = lo;
  21239. }
  21240. };
  21241. DD.prototype.gt = function gt (y) {
  21242. return (this._hi > y._hi || this._hi === y._hi) && this._lo > y._lo
  21243. };
  21244. DD.prototype.isNegative = function isNegative () {
  21245. return (this._hi < 0.0 || this._hi === 0.0) && this._lo < 0.0
  21246. };
  21247. DD.prototype.trunc = function trunc () {
  21248. if (this.isNaN()) { return DD.NaN }
  21249. if (this.isPositive()) { return this.floor(); } else { return this.ceil() }
  21250. };
  21251. DD.prototype.signum = function signum () {
  21252. if (this._hi > 0) { return 1 }
  21253. if (this._hi < 0) { return -1 }
  21254. if (this._lo > 0) { return 1 }
  21255. if (this._lo < 0) { return -1 }
  21256. return 0
  21257. };
  21258. DD.prototype.interfaces_ = function interfaces_ () {
  21259. return [Serializable, Comparable, Clonable]
  21260. };
  21261. DD.prototype.getClass = function getClass () {
  21262. return DD
  21263. };
  21264. DD.sqr = function sqr (x) {
  21265. return DD.valueOf(x).selfMultiply(x)
  21266. };
  21267. DD.valueOf = function valueOf () {
  21268. if (typeof arguments[0] === 'string') {
  21269. var str = arguments[0];
  21270. return DD.parse(str)
  21271. } else if (typeof arguments[0] === 'number') {
  21272. var x = arguments[0];
  21273. return new DD(x)
  21274. }
  21275. };
  21276. DD.sqrt = function sqrt (x) {
  21277. return DD.valueOf(x).sqrt()
  21278. };
  21279. DD.parse = function parse (str) {
  21280. var i = 0;
  21281. var strlen = str.length;
  21282. while (Character.isWhitespace(str.charAt(i))) { i++; }
  21283. var isNegative = false;
  21284. if (i < strlen) {
  21285. var signCh = str.charAt(i);
  21286. if (signCh === '-' || signCh === '+') {
  21287. i++;
  21288. if (signCh === '-') { isNegative = true; }
  21289. }
  21290. }
  21291. var val = new DD();
  21292. var numDigits = 0;
  21293. var numBeforeDec = 0;
  21294. var exp = 0;
  21295. while (true) {
  21296. if (i >= strlen) { break }
  21297. var ch = str.charAt(i);
  21298. i++;
  21299. if (Character.isDigit(ch)) {
  21300. var d = ch - '0';
  21301. val.selfMultiply(DD.TEN);
  21302. val.selfAdd(d);
  21303. numDigits++;
  21304. continue
  21305. }
  21306. if (ch === '.') {
  21307. numBeforeDec = numDigits;
  21308. continue
  21309. }
  21310. if (ch === 'e' || ch === 'E') {
  21311. var expStr = str.substring(i);
  21312. try {
  21313. exp = Integer.parseInt(expStr);
  21314. } catch (ex) {
  21315. if (ex instanceof Error) {
  21316. throw new Error('Invalid exponent ' + expStr + ' in string ' + str)
  21317. } else { throw ex }
  21318. } finally {}
  21319. break
  21320. }
  21321. throw new Error("Unexpected character '" + ch + "' at position " + i + ' in string ' + str)
  21322. }
  21323. var val2 = val;
  21324. var numDecPlaces = numDigits - numBeforeDec - exp;
  21325. if (numDecPlaces === 0) {
  21326. val2 = val;
  21327. } else if (numDecPlaces > 0) {
  21328. var scale = DD.TEN.pow(numDecPlaces);
  21329. val2 = val.divide(scale);
  21330. } else if (numDecPlaces < 0) {
  21331. var scale$1 = DD.TEN.pow(-numDecPlaces);
  21332. val2 = val.multiply(scale$1);
  21333. }
  21334. if (isNegative) {
  21335. return val2.negate()
  21336. }
  21337. return val2
  21338. };
  21339. DD.createNaN = function createNaN () {
  21340. return new DD(Double.NaN, Double.NaN)
  21341. };
  21342. DD.copy = function copy (dd) {
  21343. return new DD(dd)
  21344. };
  21345. DD.magnitude = function magnitude (x) {
  21346. var xAbs = Math.abs(x);
  21347. var xLog10 = Math.log(xAbs) / Math.log(10);
  21348. var xMag = Math.trunc(Math.floor(xLog10));
  21349. var xApprox = Math.pow(10, xMag);
  21350. if (xApprox * 10 <= xAbs) { xMag += 1; }
  21351. return xMag
  21352. };
  21353. DD.stringOfChar = function stringOfChar (ch, len) {
  21354. var buf = new StringBuffer();
  21355. for (var i = 0; i < len; i++) {
  21356. buf.append(ch);
  21357. }
  21358. return buf.toString()
  21359. };
  21360. staticAccessors$7.PI.get = function () { return new DD(3.141592653589793116e+00, 1.224646799147353207e-16) };
  21361. staticAccessors$7.TWO_PI.get = function () { return new DD(6.283185307179586232e+00, 2.449293598294706414e-16) };
  21362. staticAccessors$7.PI_2.get = function () { return new DD(1.570796326794896558e+00, 6.123233995736766036e-17) };
  21363. staticAccessors$7.E.get = function () { return new DD(2.718281828459045091e+00, 1.445646891729250158e-16) };
  21364. staticAccessors$7.NaN.get = function () { return new DD(Double.NaN, Double.NaN) };
  21365. staticAccessors$7.EPS.get = function () { return 1.23259516440783e-32 };
  21366. staticAccessors$7.SPLIT.get = function () { return 134217729.0 };
  21367. staticAccessors$7.MAX_PRINT_DIGITS.get = function () { return 32 };
  21368. staticAccessors$7.TEN.get = function () { return DD.valueOf(10.0) };
  21369. staticAccessors$7.ONE.get = function () { return DD.valueOf(1.0) };
  21370. staticAccessors$7.SCI_NOT_EXPONENT_CHAR.get = function () { return 'E' };
  21371. staticAccessors$7.SCI_NOT_ZERO.get = function () { return '0.0E0' };
  21372. Object.defineProperties( DD, staticAccessors$7 );
  21373. var CGAlgorithmsDD = function CGAlgorithmsDD () {};
  21374. var staticAccessors$6 = { DP_SAFE_EPSILON: { configurable: true } };
  21375. CGAlgorithmsDD.prototype.interfaces_ = function interfaces_ () {
  21376. return []
  21377. };
  21378. CGAlgorithmsDD.prototype.getClass = function getClass () {
  21379. return CGAlgorithmsDD
  21380. };
  21381. CGAlgorithmsDD.orientationIndex = function orientationIndex (p1, p2, q) {
  21382. var index = CGAlgorithmsDD.orientationIndexFilter(p1, p2, q);
  21383. if (index <= 1) { return index }
  21384. var dx1 = DD.valueOf(p2.x).selfAdd(-p1.x);
  21385. var dy1 = DD.valueOf(p2.y).selfAdd(-p1.y);
  21386. var dx2 = DD.valueOf(q.x).selfAdd(-p2.x);
  21387. var dy2 = DD.valueOf(q.y).selfAdd(-p2.y);
  21388. return dx1.selfMultiply(dy2).selfSubtract(dy1.selfMultiply(dx2)).signum()
  21389. };
  21390. CGAlgorithmsDD.signOfDet2x2 = function signOfDet2x2 (x1, y1, x2, y2) {
  21391. var det = x1.multiply(y2).selfSubtract(y1.multiply(x2));
  21392. return det.signum()
  21393. };
  21394. CGAlgorithmsDD.intersection = function intersection (p1, p2, q1, q2) {
  21395. var denom1 = DD.valueOf(q2.y).selfSubtract(q1.y).selfMultiply(DD.valueOf(p2.x).selfSubtract(p1.x));
  21396. var denom2 = DD.valueOf(q2.x).selfSubtract(q1.x).selfMultiply(DD.valueOf(p2.y).selfSubtract(p1.y));
  21397. var denom = denom1.subtract(denom2);
  21398. var numx1 = DD.valueOf(q2.x).selfSubtract(q1.x).selfMultiply(DD.valueOf(p1.y).selfSubtract(q1.y));
  21399. var numx2 = DD.valueOf(q2.y).selfSubtract(q1.y).selfMultiply(DD.valueOf(p1.x).selfSubtract(q1.x));
  21400. var numx = numx1.subtract(numx2);
  21401. var fracP = numx.selfDivide(denom).doubleValue();
  21402. var x = DD.valueOf(p1.x).selfAdd(DD.valueOf(p2.x).selfSubtract(p1.x).selfMultiply(fracP)).doubleValue();
  21403. var numy1 = DD.valueOf(p2.x).selfSubtract(p1.x).selfMultiply(DD.valueOf(p1.y).selfSubtract(q1.y));
  21404. var numy2 = DD.valueOf(p2.y).selfSubtract(p1.y).selfMultiply(DD.valueOf(p1.x).selfSubtract(q1.x));
  21405. var numy = numy1.subtract(numy2);
  21406. var fracQ = numy.selfDivide(denom).doubleValue();
  21407. var y = DD.valueOf(q1.y).selfAdd(DD.valueOf(q2.y).selfSubtract(q1.y).selfMultiply(fracQ)).doubleValue();
  21408. return new Coordinate(x, y)
  21409. };
  21410. CGAlgorithmsDD.orientationIndexFilter = function orientationIndexFilter (pa, pb, pc) {
  21411. var detsum = null;
  21412. var detleft = (pa.x - pc.x) * (pb.y - pc.y);
  21413. var detright = (pa.y - pc.y) * (pb.x - pc.x);
  21414. var det = detleft - detright;
  21415. if (detleft > 0.0) {
  21416. if (detright <= 0.0) {
  21417. return CGAlgorithmsDD.signum(det)
  21418. } else {
  21419. detsum = detleft + detright;
  21420. }
  21421. } else if (detleft < 0.0) {
  21422. if (detright >= 0.0) {
  21423. return CGAlgorithmsDD.signum(det)
  21424. } else {
  21425. detsum = -detleft - detright;
  21426. }
  21427. } else {
  21428. return CGAlgorithmsDD.signum(det)
  21429. }
  21430. var errbound = CGAlgorithmsDD.DP_SAFE_EPSILON * detsum;
  21431. if (det >= errbound || -det >= errbound) {
  21432. return CGAlgorithmsDD.signum(det)
  21433. }
  21434. return 2
  21435. };
  21436. CGAlgorithmsDD.signum = function signum (x) {
  21437. if (x > 0) { return 1 }
  21438. if (x < 0) { return -1 }
  21439. return 0
  21440. };
  21441. staticAccessors$6.DP_SAFE_EPSILON.get = function () { return 1e-15 };
  21442. Object.defineProperties( CGAlgorithmsDD, staticAccessors$6 );
  21443. var CoordinateSequence = function CoordinateSequence () {};
  21444. var staticAccessors$8 = { X: { configurable: true },Y: { configurable: true },Z: { configurable: true },M: { configurable: true } };
  21445. staticAccessors$8.X.get = function () { return 0 };
  21446. staticAccessors$8.Y.get = function () { return 1 };
  21447. staticAccessors$8.Z.get = function () { return 2 };
  21448. staticAccessors$8.M.get = function () { return 3 };
  21449. CoordinateSequence.prototype.setOrdinate = function setOrdinate (index, ordinateIndex, value) {};
  21450. CoordinateSequence.prototype.size = function size () {};
  21451. CoordinateSequence.prototype.getOrdinate = function getOrdinate (index, ordinateIndex) {};
  21452. CoordinateSequence.prototype.getCoordinate = function getCoordinate () {};
  21453. CoordinateSequence.prototype.getCoordinateCopy = function getCoordinateCopy (i) {};
  21454. CoordinateSequence.prototype.getDimension = function getDimension () {};
  21455. CoordinateSequence.prototype.getX = function getX (index) {};
  21456. CoordinateSequence.prototype.clone = function clone () {};
  21457. CoordinateSequence.prototype.expandEnvelope = function expandEnvelope (env) {};
  21458. CoordinateSequence.prototype.copy = function copy () {};
  21459. CoordinateSequence.prototype.getY = function getY (index) {};
  21460. CoordinateSequence.prototype.toCoordinateArray = function toCoordinateArray () {};
  21461. CoordinateSequence.prototype.interfaces_ = function interfaces_ () {
  21462. return [Clonable]
  21463. };
  21464. CoordinateSequence.prototype.getClass = function getClass () {
  21465. return CoordinateSequence
  21466. };
  21467. Object.defineProperties( CoordinateSequence, staticAccessors$8 );
  21468. var Exception = function Exception () {};
  21469. var NotRepresentableException = (function (Exception$$1) {
  21470. function NotRepresentableException () {
  21471. Exception$$1.call(this, 'Projective point not representable on the Cartesian plane.');
  21472. }
  21473. if ( Exception$$1 ) NotRepresentableException.__proto__ = Exception$$1;
  21474. NotRepresentableException.prototype = Object.create( Exception$$1 && Exception$$1.prototype );
  21475. NotRepresentableException.prototype.constructor = NotRepresentableException;
  21476. NotRepresentableException.prototype.interfaces_ = function interfaces_ () {
  21477. return []
  21478. };
  21479. NotRepresentableException.prototype.getClass = function getClass () {
  21480. return NotRepresentableException
  21481. };
  21482. return NotRepresentableException;
  21483. }(Exception));
  21484. var System = function System () {};
  21485. System.arraycopy = function arraycopy (src, srcPos, dest, destPos, len) {
  21486. var c = 0;
  21487. for (var i = srcPos; i < srcPos + len; i++) {
  21488. dest[destPos + c] = src[i];
  21489. c++;
  21490. }
  21491. };
  21492. System.getProperty = function getProperty (name) {
  21493. return {
  21494. 'line.separator': '\n'
  21495. }[name]
  21496. };
  21497. var HCoordinate = function HCoordinate () {
  21498. this.x = null;
  21499. this.y = null;
  21500. this.w = null;
  21501. if (arguments.length === 0) {
  21502. this.x = 0.0;
  21503. this.y = 0.0;
  21504. this.w = 1.0;
  21505. } else if (arguments.length === 1) {
  21506. var p = arguments[0];
  21507. this.x = p.x;
  21508. this.y = p.y;
  21509. this.w = 1.0;
  21510. } else if (arguments.length === 2) {
  21511. if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') {
  21512. var _x = arguments[0];
  21513. var _y = arguments[1];
  21514. this.x = _x;
  21515. this.y = _y;
  21516. this.w = 1.0;
  21517. } else if (arguments[0] instanceof HCoordinate && arguments[1] instanceof HCoordinate) {
  21518. var p1 = arguments[0];
  21519. var p2 = arguments[1];
  21520. this.x = p1.y * p2.w - p2.y * p1.w;
  21521. this.y = p2.x * p1.w - p1.x * p2.w;
  21522. this.w = p1.x * p2.y - p2.x * p1.y;
  21523. } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Coordinate) {
  21524. var p1$1 = arguments[0];
  21525. var p2$1 = arguments[1];
  21526. this.x = p1$1.y - p2$1.y;
  21527. this.y = p2$1.x - p1$1.x;
  21528. this.w = p1$1.x * p2$1.y - p2$1.x * p1$1.y;
  21529. }
  21530. } else if (arguments.length === 3) {
  21531. var _x$1 = arguments[0];
  21532. var _y$1 = arguments[1];
  21533. var _w = arguments[2];
  21534. this.x = _x$1;
  21535. this.y = _y$1;
  21536. this.w = _w;
  21537. } else if (arguments.length === 4) {
  21538. var p1$2 = arguments[0];
  21539. var p2$2 = arguments[1];
  21540. var q1 = arguments[2];
  21541. var q2 = arguments[3];
  21542. var px = p1$2.y - p2$2.y;
  21543. var py = p2$2.x - p1$2.x;
  21544. var pw = p1$2.x * p2$2.y - p2$2.x * p1$2.y;
  21545. var qx = q1.y - q2.y;
  21546. var qy = q2.x - q1.x;
  21547. var qw = q1.x * q2.y - q2.x * q1.y;
  21548. this.x = py * qw - qy * pw;
  21549. this.y = qx * pw - px * qw;
  21550. this.w = px * qy - qx * py;
  21551. }
  21552. };
  21553. HCoordinate.prototype.getY = function getY () {
  21554. var a = this.y / this.w;
  21555. if (Double.isNaN(a) || Double.isInfinite(a)) {
  21556. throw new NotRepresentableException()
  21557. }
  21558. return a
  21559. };
  21560. HCoordinate.prototype.getX = function getX () {
  21561. var a = this.x / this.w;
  21562. if (Double.isNaN(a) || Double.isInfinite(a)) {
  21563. throw new NotRepresentableException()
  21564. }
  21565. return a
  21566. };
  21567. HCoordinate.prototype.getCoordinate = function getCoordinate () {
  21568. var p = new Coordinate();
  21569. p.x = this.getX();
  21570. p.y = this.getY();
  21571. return p
  21572. };
  21573. HCoordinate.prototype.interfaces_ = function interfaces_ () {
  21574. return []
  21575. };
  21576. HCoordinate.prototype.getClass = function getClass () {
  21577. return HCoordinate
  21578. };
  21579. HCoordinate.intersection = function intersection (p1, p2, q1, q2) {
  21580. var px = p1.y - p2.y;
  21581. var py = p2.x - p1.x;
  21582. var pw = p1.x * p2.y - p2.x * p1.y;
  21583. var qx = q1.y - q2.y;
  21584. var qy = q2.x - q1.x;
  21585. var qw = q1.x * q2.y - q2.x * q1.y;
  21586. var x = py * qw - qy * pw;
  21587. var y = qx * pw - px * qw;
  21588. var w = px * qy - qx * py;
  21589. var xInt = x / w;
  21590. var yInt = y / w;
  21591. if (Double.isNaN(xInt) || (Double.isInfinite(xInt) || Double.isNaN(yInt)) || Double.isInfinite(yInt)) {
  21592. throw new NotRepresentableException()
  21593. }
  21594. return new Coordinate(xInt, yInt)
  21595. };
  21596. var Envelope = function Envelope () {
  21597. this._minx = null;
  21598. this._maxx = null;
  21599. this._miny = null;
  21600. this._maxy = null;
  21601. if (arguments.length === 0) {
  21602. this.init();
  21603. } else if (arguments.length === 1) {
  21604. if (arguments[0] instanceof Coordinate) {
  21605. var p = arguments[0];
  21606. this.init(p.x, p.x, p.y, p.y);
  21607. } else if (arguments[0] instanceof Envelope) {
  21608. var env = arguments[0];
  21609. this.init(env);
  21610. }
  21611. } else if (arguments.length === 2) {
  21612. var p1 = arguments[0];
  21613. var p2 = arguments[1];
  21614. this.init(p1.x, p2.x, p1.y, p2.y);
  21615. } else if (arguments.length === 4) {
  21616. var x1 = arguments[0];
  21617. var x2 = arguments[1];
  21618. var y1 = arguments[2];
  21619. var y2 = arguments[3];
  21620. this.init(x1, x2, y1, y2);
  21621. }
  21622. };
  21623. var staticAccessors$9 = { serialVersionUID: { configurable: true } };
  21624. Envelope.prototype.getArea = function getArea () {
  21625. return this.getWidth() * this.getHeight()
  21626. };
  21627. Envelope.prototype.equals = function equals (other) {
  21628. if (!(other instanceof Envelope)) {
  21629. return false
  21630. }
  21631. var otherEnvelope = other;
  21632. if (this.isNull()) {
  21633. return otherEnvelope.isNull()
  21634. }
  21635. return this._maxx === otherEnvelope.getMaxX() && this._maxy === otherEnvelope.getMaxY() && this._minx === otherEnvelope.getMinX() && this._miny === otherEnvelope.getMinY()
  21636. };
  21637. Envelope.prototype.intersection = function intersection (env) {
  21638. if (this.isNull() || env.isNull() || !this.intersects(env)) { return new Envelope() }
  21639. var intMinX = this._minx > env._minx ? this._minx : env._minx;
  21640. var intMinY = this._miny > env._miny ? this._miny : env._miny;
  21641. var intMaxX = this._maxx < env._maxx ? this._maxx : env._maxx;
  21642. var intMaxY = this._maxy < env._maxy ? this._maxy : env._maxy;
  21643. return new Envelope(intMinX, intMaxX, intMinY, intMaxY)
  21644. };
  21645. Envelope.prototype.isNull = function isNull () {
  21646. return this._maxx < this._minx
  21647. };
  21648. Envelope.prototype.getMaxX = function getMaxX () {
  21649. return this._maxx
  21650. };
  21651. Envelope.prototype.covers = function covers () {
  21652. if (arguments.length === 1) {
  21653. if (arguments[0] instanceof Coordinate) {
  21654. var p = arguments[0];
  21655. return this.covers(p.x, p.y)
  21656. } else if (arguments[0] instanceof Envelope) {
  21657. var other = arguments[0];
  21658. if (this.isNull() || other.isNull()) {
  21659. return false
  21660. }
  21661. return other.getMinX() >= this._minx && other.getMaxX() <= this._maxx && other.getMinY() >= this._miny && other.getMaxY() <= this._maxy
  21662. }
  21663. } else if (arguments.length === 2) {
  21664. var x = arguments[0];
  21665. var y = arguments[1];
  21666. if (this.isNull()) { return false }
  21667. return x >= this._minx && x <= this._maxx && y >= this._miny && y <= this._maxy
  21668. }
  21669. };
  21670. Envelope.prototype.intersects = function intersects () {
  21671. if (arguments.length === 1) {
  21672. if (arguments[0] instanceof Envelope) {
  21673. var other = arguments[0];
  21674. if (this.isNull() || other.isNull()) {
  21675. return false
  21676. }
  21677. return !(other._minx > this._maxx || other._maxx < this._minx || other._miny > this._maxy || other._maxy < this._miny)
  21678. } else if (arguments[0] instanceof Coordinate) {
  21679. var p = arguments[0];
  21680. return this.intersects(p.x, p.y)
  21681. }
  21682. } else if (arguments.length === 2) {
  21683. var x = arguments[0];
  21684. var y = arguments[1];
  21685. if (this.isNull()) { return false }
  21686. return !(x > this._maxx || x < this._minx || y > this._maxy || y < this._miny)
  21687. }
  21688. };
  21689. Envelope.prototype.getMinY = function getMinY () {
  21690. return this._miny
  21691. };
  21692. Envelope.prototype.getMinX = function getMinX () {
  21693. return this._minx
  21694. };
  21695. Envelope.prototype.expandToInclude = function expandToInclude () {
  21696. if (arguments.length === 1) {
  21697. if (arguments[0] instanceof Coordinate) {
  21698. var p = arguments[0];
  21699. this.expandToInclude(p.x, p.y);
  21700. } else if (arguments[0] instanceof Envelope) {
  21701. var other = arguments[0];
  21702. if (other.isNull()) {
  21703. return null
  21704. }
  21705. if (this.isNull()) {
  21706. this._minx = other.getMinX();
  21707. this._maxx = other.getMaxX();
  21708. this._miny = other.getMinY();
  21709. this._maxy = other.getMaxY();
  21710. } else {
  21711. if (other._minx < this._minx) {
  21712. this._minx = other._minx;
  21713. }
  21714. if (other._maxx > this._maxx) {
  21715. this._maxx = other._maxx;
  21716. }
  21717. if (other._miny < this._miny) {
  21718. this._miny = other._miny;
  21719. }
  21720. if (other._maxy > this._maxy) {
  21721. this._maxy = other._maxy;
  21722. }
  21723. }
  21724. }
  21725. } else if (arguments.length === 2) {
  21726. var x = arguments[0];
  21727. var y = arguments[1];
  21728. if (this.isNull()) {
  21729. this._minx = x;
  21730. this._maxx = x;
  21731. this._miny = y;
  21732. this._maxy = y;
  21733. } else {
  21734. if (x < this._minx) {
  21735. this._minx = x;
  21736. }
  21737. if (x > this._maxx) {
  21738. this._maxx = x;
  21739. }
  21740. if (y < this._miny) {
  21741. this._miny = y;
  21742. }
  21743. if (y > this._maxy) {
  21744. this._maxy = y;
  21745. }
  21746. }
  21747. }
  21748. };
  21749. Envelope.prototype.minExtent = function minExtent () {
  21750. if (this.isNull()) { return 0.0 }
  21751. var w = this.getWidth();
  21752. var h = this.getHeight();
  21753. if (w < h) { return w }
  21754. return h
  21755. };
  21756. Envelope.prototype.getWidth = function getWidth () {
  21757. if (this.isNull()) {
  21758. return 0
  21759. }
  21760. return this._maxx - this._minx
  21761. };
  21762. Envelope.prototype.compareTo = function compareTo (o) {
  21763. var env = o;
  21764. if (this.isNull()) {
  21765. if (env.isNull()) { return 0 }
  21766. return -1
  21767. } else {
  21768. if (env.isNull()) { return 1 }
  21769. }
  21770. if (this._minx < env._minx) { return -1 }
  21771. if (this._minx > env._minx) { return 1 }
  21772. if (this._miny < env._miny) { return -1 }
  21773. if (this._miny > env._miny) { return 1 }
  21774. if (this._maxx < env._maxx) { return -1 }
  21775. if (this._maxx > env._maxx) { return 1 }
  21776. if (this._maxy < env._maxy) { return -1 }
  21777. if (this._maxy > env._maxy) { return 1 }
  21778. return 0
  21779. };
  21780. Envelope.prototype.translate = function translate (transX, transY) {
  21781. if (this.isNull()) {
  21782. return null
  21783. }
  21784. this.init(this.getMinX() + transX, this.getMaxX() + transX, this.getMinY() + transY, this.getMaxY() + transY);
  21785. };
  21786. Envelope.prototype.toString = function toString () {
  21787. return 'Env[' + this._minx + ' : ' + this._maxx + ', ' + this._miny + ' : ' + this._maxy + ']'
  21788. };
  21789. Envelope.prototype.setToNull = function setToNull () {
  21790. this._minx = 0;
  21791. this._maxx = -1;
  21792. this._miny = 0;
  21793. this._maxy = -1;
  21794. };
  21795. Envelope.prototype.getHeight = function getHeight () {
  21796. if (this.isNull()) {
  21797. return 0
  21798. }
  21799. return this._maxy - this._miny
  21800. };
  21801. Envelope.prototype.maxExtent = function maxExtent () {
  21802. if (this.isNull()) { return 0.0 }
  21803. var w = this.getWidth();
  21804. var h = this.getHeight();
  21805. if (w > h) { return w }
  21806. return h
  21807. };
  21808. Envelope.prototype.expandBy = function expandBy () {
  21809. if (arguments.length === 1) {
  21810. var distance = arguments[0];
  21811. this.expandBy(distance, distance);
  21812. } else if (arguments.length === 2) {
  21813. var deltaX = arguments[0];
  21814. var deltaY = arguments[1];
  21815. if (this.isNull()) { return null }
  21816. this._minx -= deltaX;
  21817. this._maxx += deltaX;
  21818. this._miny -= deltaY;
  21819. this._maxy += deltaY;
  21820. if (this._minx > this._maxx || this._miny > this._maxy) { this.setToNull(); }
  21821. }
  21822. };
  21823. Envelope.prototype.contains = function contains () {
  21824. if (arguments.length === 1) {
  21825. if (arguments[0] instanceof Envelope) {
  21826. var other = arguments[0];
  21827. return this.covers(other)
  21828. } else if (arguments[0] instanceof Coordinate) {
  21829. var p = arguments[0];
  21830. return this.covers(p)
  21831. }
  21832. } else if (arguments.length === 2) {
  21833. var x = arguments[0];
  21834. var y = arguments[1];
  21835. return this.covers(x, y)
  21836. }
  21837. };
  21838. Envelope.prototype.centre = function centre () {
  21839. if (this.isNull()) { return null }
  21840. return new Coordinate((this.getMinX() + this.getMaxX()) / 2.0, (this.getMinY() + this.getMaxY()) / 2.0)
  21841. };
  21842. Envelope.prototype.init = function init () {
  21843. if (arguments.length === 0) {
  21844. this.setToNull();
  21845. } else if (arguments.length === 1) {
  21846. if (arguments[0] instanceof Coordinate) {
  21847. var p = arguments[0];
  21848. this.init(p.x, p.x, p.y, p.y);
  21849. } else if (arguments[0] instanceof Envelope) {
  21850. var env = arguments[0];
  21851. this._minx = env._minx;
  21852. this._maxx = env._maxx;
  21853. this._miny = env._miny;
  21854. this._maxy = env._maxy;
  21855. }
  21856. } else if (arguments.length === 2) {
  21857. var p1 = arguments[0];
  21858. var p2 = arguments[1];
  21859. this.init(p1.x, p2.x, p1.y, p2.y);
  21860. } else if (arguments.length === 4) {
  21861. var x1 = arguments[0];
  21862. var x2 = arguments[1];
  21863. var y1 = arguments[2];
  21864. var y2 = arguments[3];
  21865. if (x1 < x2) {
  21866. this._minx = x1;
  21867. this._maxx = x2;
  21868. } else {
  21869. this._minx = x2;
  21870. this._maxx = x1;
  21871. }
  21872. if (y1 < y2) {
  21873. this._miny = y1;
  21874. this._maxy = y2;
  21875. } else {
  21876. this._miny = y2;
  21877. this._maxy = y1;
  21878. }
  21879. }
  21880. };
  21881. Envelope.prototype.getMaxY = function getMaxY () {
  21882. return this._maxy
  21883. };
  21884. Envelope.prototype.distance = function distance (env) {
  21885. if (this.intersects(env)) { return 0 }
  21886. var dx = 0.0;
  21887. if (this._maxx < env._minx) { dx = env._minx - this._maxx; } else if (this._minx > env._maxx) { dx = this._minx - env._maxx; }
  21888. var dy = 0.0;
  21889. if (this._maxy < env._miny) { dy = env._miny - this._maxy; } else if (this._miny > env._maxy) { dy = this._miny - env._maxy; }
  21890. if (dx === 0.0) { return dy }
  21891. if (dy === 0.0) { return dx }
  21892. return Math.sqrt(dx * dx + dy * dy)
  21893. };
  21894. Envelope.prototype.hashCode = function hashCode () {
  21895. var result = 17;
  21896. result = 37 * result + Coordinate.hashCode(this._minx);
  21897. result = 37 * result + Coordinate.hashCode(this._maxx);
  21898. result = 37 * result + Coordinate.hashCode(this._miny);
  21899. result = 37 * result + Coordinate.hashCode(this._maxy);
  21900. return result
  21901. };
  21902. Envelope.prototype.interfaces_ = function interfaces_ () {
  21903. return [Comparable, Serializable]
  21904. };
  21905. Envelope.prototype.getClass = function getClass () {
  21906. return Envelope
  21907. };
  21908. Envelope.intersects = function intersects () {
  21909. if (arguments.length === 3) {
  21910. var p1 = arguments[0];
  21911. var p2 = arguments[1];
  21912. var q = arguments[2];
  21913. if (q.x >= (p1.x < p2.x ? p1.x : p2.x) && q.x <= (p1.x > p2.x ? p1.x : p2.x) && (q.y >= (p1.y < p2.y ? p1.y : p2.y) && q.y <= (p1.y > p2.y ? p1.y : p2.y))) {
  21914. return true
  21915. }
  21916. return false
  21917. } else if (arguments.length === 4) {
  21918. var p1$1 = arguments[0];
  21919. var p2$1 = arguments[1];
  21920. var q1 = arguments[2];
  21921. var q2 = arguments[3];
  21922. var minq = Math.min(q1.x, q2.x);
  21923. var maxq = Math.max(q1.x, q2.x);
  21924. var minp = Math.min(p1$1.x, p2$1.x);
  21925. var maxp = Math.max(p1$1.x, p2$1.x);
  21926. if (minp > maxq) { return false }
  21927. if (maxp < minq) { return false }
  21928. minq = Math.min(q1.y, q2.y);
  21929. maxq = Math.max(q1.y, q2.y);
  21930. minp = Math.min(p1$1.y, p2$1.y);
  21931. maxp = Math.max(p1$1.y, p2$1.y);
  21932. if (minp > maxq) { return false }
  21933. if (maxp < minq) { return false }
  21934. return true
  21935. }
  21936. };
  21937. staticAccessors$9.serialVersionUID.get = function () { return 5873921885273102420 };
  21938. Object.defineProperties( Envelope, staticAccessors$9 );
  21939. var regExes = {
  21940. 'typeStr': /^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/,
  21941. 'emptyTypeStr': /^\s*(\w+)\s*EMPTY\s*$/,
  21942. 'spaces': /\s+/,
  21943. 'parenComma': /\)\s*,\s*\(/,
  21944. 'doubleParenComma': /\)\s*\)\s*,\s*\(\s*\(/, // can't use {2} here
  21945. 'trimParens': /^\s*\(?(.*?)\)?\s*$/
  21946. };
  21947. /**
  21948. * Class for reading and writing Well-Known Text.
  21949. *
  21950. * NOTE: Adapted from OpenLayers 2.11 implementation.
  21951. */
  21952. /** Create a new parser for WKT
  21953. *
  21954. * @param {GeometryFactory} geometryFactory
  21955. * @return An instance of WKTParser.
  21956. * @constructor
  21957. * @private
  21958. */
  21959. var WKTParser = function WKTParser (geometryFactory) {
  21960. this.geometryFactory = geometryFactory || new GeometryFactory();
  21961. };
  21962. /**
  21963. * Deserialize a WKT string and return a geometry. Supports WKT for POINT,
  21964. * MULTIPOINT, LINESTRING, LINEARRING, MULTILINESTRING, POLYGON, MULTIPOLYGON,
  21965. * and GEOMETRYCOLLECTION.
  21966. *
  21967. * @param {String} wkt A WKT string.
  21968. * @return {Geometry} A geometry instance.
  21969. * @private
  21970. */
  21971. WKTParser.prototype.read = function read (wkt) {
  21972. var geometry, type, str;
  21973. wkt = wkt.replace(/[\n\r]/g, ' ');
  21974. var matches = regExes.typeStr.exec(wkt);
  21975. if (wkt.search('EMPTY') !== -1) {
  21976. matches = regExes.emptyTypeStr.exec(wkt);
  21977. matches[2] = undefined;
  21978. }
  21979. if (matches) {
  21980. type = matches[1].toLowerCase();
  21981. str = matches[2];
  21982. if (parse$1[type]) {
  21983. geometry = parse$1[type].apply(this, [str]);
  21984. }
  21985. }
  21986. if (geometry === undefined) { throw new Error('Could not parse WKT ' + wkt) }
  21987. return geometry
  21988. };
  21989. /**
  21990. * Serialize a geometry into a WKT string.
  21991. *
  21992. * @param {Geometry} geometry A feature or array of features.
  21993. * @return {String} The WKT string representation of the input geometries.
  21994. * @private
  21995. */
  21996. WKTParser.prototype.write = function write (geometry) {
  21997. return this.extractGeometry(geometry)
  21998. };
  21999. /**
  22000. * Entry point to construct the WKT for a single Geometry object.
  22001. *
  22002. * @param {Geometry} geometry
  22003. * @return {String} A WKT string of representing the geometry.
  22004. * @private
  22005. */
  22006. WKTParser.prototype.extractGeometry = function extractGeometry (geometry) {
  22007. var type = geometry.getGeometryType().toLowerCase();
  22008. if (!extract$1[type]) {
  22009. return null
  22010. }
  22011. var wktType = type.toUpperCase();
  22012. var data;
  22013. if (geometry.isEmpty()) {
  22014. data = wktType + ' EMPTY';
  22015. } else {
  22016. data = wktType + '(' + extract$1[type].apply(this, [geometry]) + ')';
  22017. }
  22018. return data
  22019. };
  22020. /**
  22021. * Object with properties corresponding to the geometry types. Property values
  22022. * are functions that do the actual data extraction.
  22023. * @private
  22024. */
  22025. var extract$1 = {
  22026. coordinate: function coordinate (coordinate$1) {
  22027. return coordinate$1.x + ' ' + coordinate$1.y
  22028. },
  22029. /**
  22030. * Return a space delimited string of point coordinates.
  22031. *
  22032. * @param {Point}
  22033. * point
  22034. * @return {String} A string of coordinates representing the point.
  22035. */
  22036. point: function point (point$1) {
  22037. return extract$1.coordinate.call(this, point$1._coordinates._coordinates[0])
  22038. },
  22039. /**
  22040. * Return a comma delimited string of point coordinates from a multipoint.
  22041. *
  22042. * @param {MultiPoint}
  22043. * multipoint
  22044. * @return {String} A string of point coordinate strings representing the
  22045. * multipoint.
  22046. */
  22047. multipoint: function multipoint (multipoint$1) {
  22048. var this$1 = this;
  22049. var array = [];
  22050. for (var i = 0, len = multipoint$1._geometries.length; i < len; ++i) {
  22051. array.push('(' + extract$1.point.apply(this$1, [multipoint$1._geometries[i]]) + ')');
  22052. }
  22053. return array.join(',')
  22054. },
  22055. /**
  22056. * Return a comma delimited string of point coordinates from a line.
  22057. *
  22058. * @param {LineString} linestring
  22059. * @return {String} A string of point coordinate strings representing the linestring.
  22060. */
  22061. linestring: function linestring (linestring$1) {
  22062. var this$1 = this;
  22063. var array = [];
  22064. for (var i = 0, len = linestring$1._points._coordinates.length; i < len; ++i) {
  22065. array.push(extract$1.coordinate.apply(this$1, [linestring$1._points._coordinates[i]]));
  22066. }
  22067. return array.join(',')
  22068. },
  22069. linearring: function linearring (linearring$1) {
  22070. var this$1 = this;
  22071. var array = [];
  22072. for (var i = 0, len = linearring$1._points._coordinates.length; i < len; ++i) {
  22073. array.push(extract$1.coordinate.apply(this$1, [linearring$1._points._coordinates[i]]));
  22074. }
  22075. return array.join(',')
  22076. },
  22077. /**
  22078. * Return a comma delimited string of linestring strings from a
  22079. * multilinestring.
  22080. *
  22081. * @param {MultiLineString} multilinestring
  22082. * @return {String} A string of of linestring strings representing the multilinestring.
  22083. */
  22084. multilinestring: function multilinestring (multilinestring$1) {
  22085. var this$1 = this;
  22086. var array = [];
  22087. for (var i = 0, len = multilinestring$1._geometries.length; i < len; ++i) {
  22088. array.push('(' +
  22089. extract$1.linestring.apply(this$1, [multilinestring$1._geometries[i]]) +
  22090. ')');
  22091. }
  22092. return array.join(',')
  22093. },
  22094. /**
  22095. * Return a comma delimited string of linear ring arrays from a polygon.
  22096. *
  22097. * @param {Polygon} polygon
  22098. * @return {String} An array of linear ring arrays representing the polygon.
  22099. */
  22100. polygon: function polygon (polygon$1) {
  22101. var this$1 = this;
  22102. var array = [];
  22103. array.push('(' + extract$1.linestring.apply(this, [polygon$1._shell]) + ')');
  22104. for (var i = 0, len = polygon$1._holes.length; i < len; ++i) {
  22105. array.push('(' + extract$1.linestring.apply(this$1, [polygon$1._holes[i]]) + ')');
  22106. }
  22107. return array.join(',')
  22108. },
  22109. /**
  22110. * Return an array of polygon arrays from a multipolygon.
  22111. *
  22112. * @param {MultiPolygon} multipolygon
  22113. * @return {String} An array of polygon arrays representing the multipolygon.
  22114. */
  22115. multipolygon: function multipolygon (multipolygon$1) {
  22116. var this$1 = this;
  22117. var array = [];
  22118. for (var i = 0, len = multipolygon$1._geometries.length; i < len; ++i) {
  22119. array.push('(' + extract$1.polygon.apply(this$1, [multipolygon$1._geometries[i]]) + ')');
  22120. }
  22121. return array.join(',')
  22122. },
  22123. /**
  22124. * Return the WKT portion between 'GEOMETRYCOLLECTION(' and ')' for an
  22125. * geometrycollection.
  22126. *
  22127. * @param {GeometryCollection} collection
  22128. * @return {String} internal WKT representation of the collection.
  22129. */
  22130. geometrycollection: function geometrycollection (collection) {
  22131. var this$1 = this;
  22132. var array = [];
  22133. for (var i = 0, len = collection._geometries.length; i < len; ++i) {
  22134. array.push(this$1.extractGeometry(collection._geometries[i]));
  22135. }
  22136. return array.join(',')
  22137. }
  22138. };
  22139. /**
  22140. * Object with properties corresponding to the geometry types. Property values
  22141. * are functions that do the actual parsing.
  22142. * @private
  22143. */
  22144. var parse$1 = {
  22145. /**
  22146. * Return point geometry given a point WKT fragment.
  22147. *
  22148. * @param {String} str A WKT fragment representing the point.
  22149. * @return {Point} A point geometry.
  22150. * @private
  22151. */
  22152. point: function point (str) {
  22153. if (str === undefined) {
  22154. return this.geometryFactory.createPoint()
  22155. }
  22156. var coords = str.trim().split(regExes.spaces);
  22157. return this.geometryFactory.createPoint(new Coordinate(Number.parseFloat(coords[0]),
  22158. Number.parseFloat(coords[1])))
  22159. },
  22160. /**
  22161. * Return a multipoint geometry given a multipoint WKT fragment.
  22162. *
  22163. * @param {String} str A WKT fragment representing the multipoint.
  22164. * @return {Point} A multipoint feature.
  22165. * @private
  22166. */
  22167. multipoint: function multipoint (str) {
  22168. var this$1 = this;
  22169. if (str === undefined) {
  22170. return this.geometryFactory.createMultiPoint()
  22171. }
  22172. var point;
  22173. var points = str.trim().split(',');
  22174. var components = [];
  22175. for (var i = 0, len = points.length; i < len; ++i) {
  22176. point = points[i].replace(regExes.trimParens, '$1');
  22177. components.push(parse$1.point.apply(this$1, [point]));
  22178. }
  22179. return this.geometryFactory.createMultiPoint(components)
  22180. },
  22181. /**
  22182. * Return a linestring geometry given a linestring WKT fragment.
  22183. *
  22184. * @param {String} str A WKT fragment representing the linestring.
  22185. * @return {LineString} A linestring geometry.
  22186. * @private
  22187. */
  22188. linestring: function linestring (str) {
  22189. if (str === undefined) {
  22190. return this.geometryFactory.createLineString()
  22191. }
  22192. var points = str.trim().split(',');
  22193. var components = [];
  22194. var coords;
  22195. for (var i = 0, len = points.length; i < len; ++i) {
  22196. coords = points[i].trim().split(regExes.spaces);
  22197. components.push(new Coordinate(Number.parseFloat(coords[0]), Number.parseFloat(coords[1])));
  22198. }
  22199. return this.geometryFactory.createLineString(components)
  22200. },
  22201. /**
  22202. * Return a linearring geometry given a linearring WKT fragment.
  22203. *
  22204. * @param {String} str A WKT fragment representing the linearring.
  22205. * @return {LinearRing} A linearring geometry.
  22206. * @private
  22207. */
  22208. linearring: function linearring (str) {
  22209. if (str === undefined) {
  22210. return this.geometryFactory.createLinearRing()
  22211. }
  22212. var points = str.trim().split(',');
  22213. var components = [];
  22214. var coords;
  22215. for (var i = 0, len = points.length; i < len; ++i) {
  22216. coords = points[i].trim().split(regExes.spaces);
  22217. components.push(new Coordinate(Number.parseFloat(coords[0]), Number.parseFloat(coords[1])));
  22218. }
  22219. return this.geometryFactory.createLinearRing(components)
  22220. },
  22221. /**
  22222. * Return a multilinestring geometry given a multilinestring WKT fragment.
  22223. *
  22224. * @param {String} str A WKT fragment representing the multilinestring.
  22225. * @return {MultiLineString} A multilinestring geometry.
  22226. * @private
  22227. */
  22228. multilinestring: function multilinestring (str) {
  22229. var this$1 = this;
  22230. if (str === undefined) {
  22231. return this.geometryFactory.createMultiLineString()
  22232. }
  22233. var line;
  22234. var lines = str.trim().split(regExes.parenComma);
  22235. var components = [];
  22236. for (var i = 0, len = lines.length; i < len; ++i) {
  22237. line = lines[i].replace(regExes.trimParens, '$1');
  22238. components.push(parse$1.linestring.apply(this$1, [line]));
  22239. }
  22240. return this.geometryFactory.createMultiLineString(components)
  22241. },
  22242. /**
  22243. * Return a polygon geometry given a polygon WKT fragment.
  22244. *
  22245. * @param {String} str A WKT fragment representing the polygon.
  22246. * @return {Polygon} A polygon geometry.
  22247. * @private
  22248. */
  22249. polygon: function polygon (str) {
  22250. var this$1 = this;
  22251. if (str === undefined) {
  22252. return this.geometryFactory.createPolygon()
  22253. }
  22254. var ring, linestring, linearring;
  22255. var rings = str.trim().split(regExes.parenComma);
  22256. var shell;
  22257. var holes = [];
  22258. for (var i = 0, len = rings.length; i < len; ++i) {
  22259. ring = rings[i].replace(regExes.trimParens, '$1');
  22260. linestring = parse$1.linestring.apply(this$1, [ring]);
  22261. linearring = this$1.geometryFactory.createLinearRing(linestring._points);
  22262. if (i === 0) {
  22263. shell = linearring;
  22264. } else {
  22265. holes.push(linearring);
  22266. }
  22267. }
  22268. return this.geometryFactory.createPolygon(shell, holes)
  22269. },
  22270. /**
  22271. * Return a multipolygon geometry given a multipolygon WKT fragment.
  22272. *
  22273. * @param {String} str A WKT fragment representing the multipolygon.
  22274. * @return {MultiPolygon} A multipolygon geometry.
  22275. * @private
  22276. */
  22277. multipolygon: function multipolygon (str) {
  22278. var this$1 = this;
  22279. if (str === undefined) {
  22280. return this.geometryFactory.createMultiPolygon()
  22281. }
  22282. var polygon;
  22283. var polygons = str.trim().split(regExes.doubleParenComma);
  22284. var components = [];
  22285. for (var i = 0, len = polygons.length; i < len; ++i) {
  22286. polygon = polygons[i].replace(regExes.trimParens, '$1');
  22287. components.push(parse$1.polygon.apply(this$1, [polygon]));
  22288. }
  22289. return this.geometryFactory.createMultiPolygon(components)
  22290. },
  22291. /**
  22292. * Return a geometrycollection given a geometrycollection WKT fragment.
  22293. *
  22294. * @param {String} str A WKT fragment representing the geometrycollection.
  22295. * @return {GeometryCollection}
  22296. * @private
  22297. */
  22298. geometrycollection: function geometrycollection (str) {
  22299. var this$1 = this;
  22300. if (str === undefined) {
  22301. return this.geometryFactory.createGeometryCollection()
  22302. }
  22303. // separate components of the collection with |
  22304. str = str.replace(/,\s*([A-Za-z])/g, '|$1');
  22305. var wktArray = str.trim().split('|');
  22306. var components = [];
  22307. for (var i = 0, len = wktArray.length; i < len; ++i) {
  22308. components.push(this$1.read(wktArray[i]));
  22309. }
  22310. return this.geometryFactory.createGeometryCollection(components)
  22311. }
  22312. };
  22313. /**
  22314. * Writes the Well-Known Text representation of a {@link Geometry}. The
  22315. * Well-Known Text format is defined in the <A
  22316. * HREF="http://www.opengis.org/techno/specs.htm"> OGC Simple Features
  22317. * Specification for SQL</A>.
  22318. * <p>
  22319. * The <code>WKTWriter</code> outputs coordinates rounded to the precision
  22320. * model. Only the maximum number of decimal places necessary to represent the
  22321. * ordinates to the required precision will be output.
  22322. * <p>
  22323. * The SFS WKT spec does not define a special tag for {@link LinearRing}s.
  22324. * Under the spec, rings are output as <code>LINESTRING</code>s.
  22325. */
  22326. /**
  22327. * @param {GeometryFactory} geometryFactory
  22328. * @constructor
  22329. */
  22330. var WKTWriter = function WKTWriter (geometryFactory) {
  22331. this.parser = new WKTParser(geometryFactory);
  22332. };
  22333. /**
  22334. * Converts a <code>Geometry</code> to its Well-known Text representation.
  22335. *
  22336. * @param {Geometry} geometry a <code>Geometry</code> to process.
  22337. * @return {string} a <Geometry Tagged Text> string (see the OpenGIS Simple
  22338. * Features Specification).
  22339. * @memberof WKTWriter
  22340. */
  22341. WKTWriter.prototype.write = function write (geometry) {
  22342. return this.parser.write(geometry)
  22343. };
  22344. /**
  22345. * Generates the WKT for a <tt>LINESTRING</tt> specified by two
  22346. * {@link Coordinate}s.
  22347. *
  22348. * @param p0 the first coordinate.
  22349. * @param p1 the second coordinate.
  22350. *
  22351. * @return the WKT.
  22352. * @private
  22353. */
  22354. WKTWriter.toLineString = function toLineString (p0, p1) {
  22355. if (arguments.length !== 2) {
  22356. throw new Error('Not implemented')
  22357. }
  22358. return 'LINESTRING ( ' + p0.x + ' ' + p0.y + ', ' + p1.x + ' ' + p1.y + ' )'
  22359. };
  22360. var RuntimeException = (function (Error) {
  22361. function RuntimeException (message) {
  22362. Error.call(this, message);
  22363. this.name = 'RuntimeException';
  22364. this.message = message;
  22365. this.stack = (new Error()).stack;
  22366. }
  22367. if ( Error ) RuntimeException.__proto__ = Error;
  22368. RuntimeException.prototype = Object.create( Error && Error.prototype );
  22369. RuntimeException.prototype.constructor = RuntimeException;
  22370. return RuntimeException;
  22371. }(Error));
  22372. var AssertionFailedException = (function (RuntimeException$$1) {
  22373. function AssertionFailedException () {
  22374. RuntimeException$$1.call(this);
  22375. if (arguments.length === 0) {
  22376. RuntimeException$$1.call(this);
  22377. } else if (arguments.length === 1) {
  22378. var message = arguments[0];
  22379. RuntimeException$$1.call(this, message);
  22380. }
  22381. }
  22382. if ( RuntimeException$$1 ) AssertionFailedException.__proto__ = RuntimeException$$1;
  22383. AssertionFailedException.prototype = Object.create( RuntimeException$$1 && RuntimeException$$1.prototype );
  22384. AssertionFailedException.prototype.constructor = AssertionFailedException;
  22385. AssertionFailedException.prototype.interfaces_ = function interfaces_ () {
  22386. return []
  22387. };
  22388. AssertionFailedException.prototype.getClass = function getClass () {
  22389. return AssertionFailedException
  22390. };
  22391. return AssertionFailedException;
  22392. }(RuntimeException));
  22393. var Assert = function Assert () {};
  22394. Assert.prototype.interfaces_ = function interfaces_ () {
  22395. return []
  22396. };
  22397. Assert.prototype.getClass = function getClass () {
  22398. return Assert
  22399. };
  22400. Assert.shouldNeverReachHere = function shouldNeverReachHere () {
  22401. if (arguments.length === 0) {
  22402. Assert.shouldNeverReachHere(null);
  22403. } else if (arguments.length === 1) {
  22404. var message = arguments[0];
  22405. throw new AssertionFailedException('Should never reach here' + (message !== null ? ': ' + message : ''))
  22406. }
  22407. };
  22408. Assert.isTrue = function isTrue () {
  22409. var assertion;
  22410. var message;
  22411. if (arguments.length === 1) {
  22412. assertion = arguments[0];
  22413. Assert.isTrue(assertion, null);
  22414. } else if (arguments.length === 2) {
  22415. assertion = arguments[0];
  22416. message = arguments[1];
  22417. if (!assertion) {
  22418. if (message === null) {
  22419. throw new AssertionFailedException()
  22420. } else {
  22421. throw new AssertionFailedException(message)
  22422. }
  22423. }
  22424. }
  22425. };
  22426. Assert.equals = function equals () {
  22427. var expectedValue;
  22428. var actualValue;
  22429. var message;
  22430. if (arguments.length === 2) {
  22431. expectedValue = arguments[0];
  22432. actualValue = arguments[1];
  22433. Assert.equals(expectedValue, actualValue, null);
  22434. } else if (arguments.length === 3) {
  22435. expectedValue = arguments[0];
  22436. actualValue = arguments[1];
  22437. message = arguments[2];
  22438. if (!actualValue.equals(expectedValue)) {
  22439. throw new AssertionFailedException('Expected ' + expectedValue + ' but encountered ' + actualValue + (message !== null ? ': ' + message : ''))
  22440. }
  22441. }
  22442. };
  22443. var LineIntersector = function LineIntersector () {
  22444. this._result = null;
  22445. this._inputLines = Array(2).fill().map(function () { return Array(2); });
  22446. this._intPt = new Array(2).fill(null);
  22447. this._intLineIndex = null;
  22448. this._isProper = null;
  22449. this._pa = null;
  22450. this._pb = null;
  22451. this._precisionModel = null;
  22452. this._intPt[0] = new Coordinate();
  22453. this._intPt[1] = new Coordinate();
  22454. this._pa = this._intPt[0];
  22455. this._pb = this._intPt[1];
  22456. this._result = 0;
  22457. };
  22458. var staticAccessors$10 = { DONT_INTERSECT: { configurable: true },DO_INTERSECT: { configurable: true },COLLINEAR: { configurable: true },NO_INTERSECTION: { configurable: true },POINT_INTERSECTION: { configurable: true },COLLINEAR_INTERSECTION: { configurable: true } };
  22459. LineIntersector.prototype.getIndexAlongSegment = function getIndexAlongSegment (segmentIndex, intIndex) {
  22460. this.computeIntLineIndex();
  22461. return this._intLineIndex[segmentIndex][intIndex]
  22462. };
  22463. LineIntersector.prototype.getTopologySummary = function getTopologySummary () {
  22464. var catBuf = new StringBuffer();
  22465. if (this.isEndPoint()) { catBuf.append(' endpoint'); }
  22466. if (this._isProper) { catBuf.append(' proper'); }
  22467. if (this.isCollinear()) { catBuf.append(' collinear'); }
  22468. return catBuf.toString()
  22469. };
  22470. LineIntersector.prototype.computeIntersection = function computeIntersection (p1, p2, p3, p4) {
  22471. this._inputLines[0][0] = p1;
  22472. this._inputLines[0][1] = p2;
  22473. this._inputLines[1][0] = p3;
  22474. this._inputLines[1][1] = p4;
  22475. this._result = this.computeIntersect(p1, p2, p3, p4);
  22476. };
  22477. LineIntersector.prototype.getIntersectionNum = function getIntersectionNum () {
  22478. return this._result
  22479. };
  22480. LineIntersector.prototype.computeIntLineIndex = function computeIntLineIndex () {
  22481. if (arguments.length === 0) {
  22482. if (this._intLineIndex === null) {
  22483. this._intLineIndex = Array(2).fill().map(function () { return Array(2); });
  22484. this.computeIntLineIndex(0);
  22485. this.computeIntLineIndex(1);
  22486. }
  22487. } else if (arguments.length === 1) {
  22488. var segmentIndex = arguments[0];
  22489. var dist0 = this.getEdgeDistance(segmentIndex, 0);
  22490. var dist1 = this.getEdgeDistance(segmentIndex, 1);
  22491. if (dist0 > dist1) {
  22492. this._intLineIndex[segmentIndex][0] = 0;
  22493. this._intLineIndex[segmentIndex][1] = 1;
  22494. } else {
  22495. this._intLineIndex[segmentIndex][0] = 1;
  22496. this._intLineIndex[segmentIndex][1] = 0;
  22497. }
  22498. }
  22499. };
  22500. LineIntersector.prototype.isProper = function isProper () {
  22501. return this.hasIntersection() && this._isProper
  22502. };
  22503. LineIntersector.prototype.setPrecisionModel = function setPrecisionModel (precisionModel) {
  22504. this._precisionModel = precisionModel;
  22505. };
  22506. LineIntersector.prototype.isInteriorIntersection = function isInteriorIntersection () {
  22507. var this$1 = this;
  22508. if (arguments.length === 0) {
  22509. if (this.isInteriorIntersection(0)) { return true }
  22510. if (this.isInteriorIntersection(1)) { return true }
  22511. return false
  22512. } else if (arguments.length === 1) {
  22513. var inputLineIndex = arguments[0];
  22514. for (var i = 0; i < this._result; i++) {
  22515. if (!(this$1._intPt[i].equals2D(this$1._inputLines[inputLineIndex][0]) || this$1._intPt[i].equals2D(this$1._inputLines[inputLineIndex][1]))) {
  22516. return true
  22517. }
  22518. }
  22519. return false
  22520. }
  22521. };
  22522. LineIntersector.prototype.getIntersection = function getIntersection (intIndex) {
  22523. return this._intPt[intIndex]
  22524. };
  22525. LineIntersector.prototype.isEndPoint = function isEndPoint () {
  22526. return this.hasIntersection() && !this._isProper
  22527. };
  22528. LineIntersector.prototype.hasIntersection = function hasIntersection () {
  22529. return this._result !== LineIntersector.NO_INTERSECTION
  22530. };
  22531. LineIntersector.prototype.getEdgeDistance = function getEdgeDistance (segmentIndex, intIndex) {
  22532. var dist = LineIntersector.computeEdgeDistance(this._intPt[intIndex], this._inputLines[segmentIndex][0], this._inputLines[segmentIndex][1]);
  22533. return dist
  22534. };
  22535. LineIntersector.prototype.isCollinear = function isCollinear () {
  22536. return this._result === LineIntersector.COLLINEAR_INTERSECTION
  22537. };
  22538. LineIntersector.prototype.toString = function toString () {
  22539. return WKTWriter.toLineString(this._inputLines[0][0], this._inputLines[0][1]) + ' - ' + WKTWriter.toLineString(this._inputLines[1][0], this._inputLines[1][1]) + this.getTopologySummary()
  22540. };
  22541. LineIntersector.prototype.getEndpoint = function getEndpoint (segmentIndex, ptIndex) {
  22542. return this._inputLines[segmentIndex][ptIndex]
  22543. };
  22544. LineIntersector.prototype.isIntersection = function isIntersection (pt) {
  22545. var this$1 = this;
  22546. for (var i = 0; i < this._result; i++) {
  22547. if (this$1._intPt[i].equals2D(pt)) {
  22548. return true
  22549. }
  22550. }
  22551. return false
  22552. };
  22553. LineIntersector.prototype.getIntersectionAlongSegment = function getIntersectionAlongSegment (segmentIndex, intIndex) {
  22554. this.computeIntLineIndex();
  22555. return this._intPt[this._intLineIndex[segmentIndex][intIndex]]
  22556. };
  22557. LineIntersector.prototype.interfaces_ = function interfaces_ () {
  22558. return []
  22559. };
  22560. LineIntersector.prototype.getClass = function getClass () {
  22561. return LineIntersector
  22562. };
  22563. LineIntersector.computeEdgeDistance = function computeEdgeDistance (p, p0, p1) {
  22564. var dx = Math.abs(p1.x - p0.x);
  22565. var dy = Math.abs(p1.y - p0.y);
  22566. var dist = -1.0;
  22567. if (p.equals(p0)) {
  22568. dist = 0.0;
  22569. } else if (p.equals(p1)) {
  22570. if (dx > dy) { dist = dx; } else { dist = dy; }
  22571. } else {
  22572. var pdx = Math.abs(p.x - p0.x);
  22573. var pdy = Math.abs(p.y - p0.y);
  22574. if (dx > dy) { dist = pdx; } else { dist = pdy; }
  22575. if (dist === 0.0 && !p.equals(p0)) {
  22576. dist = Math.max(pdx, pdy);
  22577. }
  22578. }
  22579. Assert.isTrue(!(dist === 0.0 && !p.equals(p0)), 'Bad distance calculation');
  22580. return dist
  22581. };
  22582. LineIntersector.nonRobustComputeEdgeDistance = function nonRobustComputeEdgeDistance (p, p1, p2) {
  22583. var dx = p.x - p1.x;
  22584. var dy = p.y - p1.y;
  22585. var dist = Math.sqrt(dx * dx + dy * dy);
  22586. Assert.isTrue(!(dist === 0.0 && !p.equals(p1)), 'Invalid distance calculation');
  22587. return dist
  22588. };
  22589. staticAccessors$10.DONT_INTERSECT.get = function () { return 0 };
  22590. staticAccessors$10.DO_INTERSECT.get = function () { return 1 };
  22591. staticAccessors$10.COLLINEAR.get = function () { return 2 };
  22592. staticAccessors$10.NO_INTERSECTION.get = function () { return 0 };
  22593. staticAccessors$10.POINT_INTERSECTION.get = function () { return 1 };
  22594. staticAccessors$10.COLLINEAR_INTERSECTION.get = function () { return 2 };
  22595. Object.defineProperties( LineIntersector, staticAccessors$10 );
  22596. var RobustLineIntersector = (function (LineIntersector$$1) {
  22597. function RobustLineIntersector () {
  22598. LineIntersector$$1.apply(this, arguments);
  22599. }
  22600. if ( LineIntersector$$1 ) RobustLineIntersector.__proto__ = LineIntersector$$1;
  22601. RobustLineIntersector.prototype = Object.create( LineIntersector$$1 && LineIntersector$$1.prototype );
  22602. RobustLineIntersector.prototype.constructor = RobustLineIntersector;
  22603. RobustLineIntersector.prototype.isInSegmentEnvelopes = function isInSegmentEnvelopes (intPt) {
  22604. var env0 = new Envelope(this._inputLines[0][0], this._inputLines[0][1]);
  22605. var env1 = new Envelope(this._inputLines[1][0], this._inputLines[1][1]);
  22606. return env0.contains(intPt) && env1.contains(intPt)
  22607. };
  22608. RobustLineIntersector.prototype.computeIntersection = function computeIntersection () {
  22609. if (arguments.length === 3) {
  22610. var p = arguments[0];
  22611. var p1 = arguments[1];
  22612. var p2 = arguments[2];
  22613. this._isProper = false;
  22614. if (Envelope.intersects(p1, p2, p)) {
  22615. if (CGAlgorithms.orientationIndex(p1, p2, p) === 0 && CGAlgorithms.orientationIndex(p2, p1, p) === 0) {
  22616. this._isProper = true;
  22617. if (p.equals(p1) || p.equals(p2)) {
  22618. this._isProper = false;
  22619. }
  22620. this._result = LineIntersector$$1.POINT_INTERSECTION;
  22621. return null
  22622. }
  22623. }
  22624. this._result = LineIntersector$$1.NO_INTERSECTION;
  22625. } else { return LineIntersector$$1.prototype.computeIntersection.apply(this, arguments) }
  22626. };
  22627. RobustLineIntersector.prototype.normalizeToMinimum = function normalizeToMinimum (n1, n2, n3, n4, normPt) {
  22628. normPt.x = this.smallestInAbsValue(n1.x, n2.x, n3.x, n4.x);
  22629. normPt.y = this.smallestInAbsValue(n1.y, n2.y, n3.y, n4.y);
  22630. n1.x -= normPt.x;
  22631. n1.y -= normPt.y;
  22632. n2.x -= normPt.x;
  22633. n2.y -= normPt.y;
  22634. n3.x -= normPt.x;
  22635. n3.y -= normPt.y;
  22636. n4.x -= normPt.x;
  22637. n4.y -= normPt.y;
  22638. };
  22639. RobustLineIntersector.prototype.safeHCoordinateIntersection = function safeHCoordinateIntersection (p1, p2, q1, q2) {
  22640. var intPt = null;
  22641. try {
  22642. intPt = HCoordinate.intersection(p1, p2, q1, q2);
  22643. } catch (e) {
  22644. if (e instanceof NotRepresentableException) {
  22645. intPt = RobustLineIntersector.nearestEndpoint(p1, p2, q1, q2);
  22646. } else { throw e }
  22647. } finally {}
  22648. return intPt
  22649. };
  22650. RobustLineIntersector.prototype.intersection = function intersection (p1, p2, q1, q2) {
  22651. var intPt = this.intersectionWithNormalization(p1, p2, q1, q2);
  22652. if (!this.isInSegmentEnvelopes(intPt)) {
  22653. intPt = new Coordinate(RobustLineIntersector.nearestEndpoint(p1, p2, q1, q2));
  22654. }
  22655. if (this._precisionModel !== null) {
  22656. this._precisionModel.makePrecise(intPt);
  22657. }
  22658. return intPt
  22659. };
  22660. RobustLineIntersector.prototype.smallestInAbsValue = function smallestInAbsValue (x1, x2, x3, x4) {
  22661. var x = x1;
  22662. var xabs = Math.abs(x);
  22663. if (Math.abs(x2) < xabs) {
  22664. x = x2;
  22665. xabs = Math.abs(x2);
  22666. }
  22667. if (Math.abs(x3) < xabs) {
  22668. x = x3;
  22669. xabs = Math.abs(x3);
  22670. }
  22671. if (Math.abs(x4) < xabs) {
  22672. x = x4;
  22673. }
  22674. return x
  22675. };
  22676. RobustLineIntersector.prototype.checkDD = function checkDD (p1, p2, q1, q2, intPt) {
  22677. var intPtDD = CGAlgorithmsDD.intersection(p1, p2, q1, q2);
  22678. var isIn = this.isInSegmentEnvelopes(intPtDD);
  22679. System.out.println('DD in env = ' + isIn + ' --------------------- ' + intPtDD);
  22680. if (intPt.distance(intPtDD) > 0.0001) {
  22681. System.out.println('Distance = ' + intPt.distance(intPtDD));
  22682. }
  22683. };
  22684. RobustLineIntersector.prototype.intersectionWithNormalization = function intersectionWithNormalization (p1, p2, q1, q2) {
  22685. var n1 = new Coordinate(p1);
  22686. var n2 = new Coordinate(p2);
  22687. var n3 = new Coordinate(q1);
  22688. var n4 = new Coordinate(q2);
  22689. var normPt = new Coordinate();
  22690. this.normalizeToEnvCentre(n1, n2, n3, n4, normPt);
  22691. var intPt = this.safeHCoordinateIntersection(n1, n2, n3, n4);
  22692. intPt.x += normPt.x;
  22693. intPt.y += normPt.y;
  22694. return intPt
  22695. };
  22696. RobustLineIntersector.prototype.computeCollinearIntersection = function computeCollinearIntersection (p1, p2, q1, q2) {
  22697. var p1q1p2 = Envelope.intersects(p1, p2, q1);
  22698. var p1q2p2 = Envelope.intersects(p1, p2, q2);
  22699. var q1p1q2 = Envelope.intersects(q1, q2, p1);
  22700. var q1p2q2 = Envelope.intersects(q1, q2, p2);
  22701. if (p1q1p2 && p1q2p2) {
  22702. this._intPt[0] = q1;
  22703. this._intPt[1] = q2;
  22704. return LineIntersector$$1.COLLINEAR_INTERSECTION
  22705. }
  22706. if (q1p1q2 && q1p2q2) {
  22707. this._intPt[0] = p1;
  22708. this._intPt[1] = p2;
  22709. return LineIntersector$$1.COLLINEAR_INTERSECTION
  22710. }
  22711. if (p1q1p2 && q1p1q2) {
  22712. this._intPt[0] = q1;
  22713. this._intPt[1] = p1;
  22714. return q1.equals(p1) && !p1q2p2 && !q1p2q2 ? LineIntersector$$1.POINT_INTERSECTION : LineIntersector$$1.COLLINEAR_INTERSECTION
  22715. }
  22716. if (p1q1p2 && q1p2q2) {
  22717. this._intPt[0] = q1;
  22718. this._intPt[1] = p2;
  22719. return q1.equals(p2) && !p1q2p2 && !q1p1q2 ? LineIntersector$$1.POINT_INTERSECTION : LineIntersector$$1.COLLINEAR_INTERSECTION
  22720. }
  22721. if (p1q2p2 && q1p1q2) {
  22722. this._intPt[0] = q2;
  22723. this._intPt[1] = p1;
  22724. return q2.equals(p1) && !p1q1p2 && !q1p2q2 ? LineIntersector$$1.POINT_INTERSECTION : LineIntersector$$1.COLLINEAR_INTERSECTION
  22725. }
  22726. if (p1q2p2 && q1p2q2) {
  22727. this._intPt[0] = q2;
  22728. this._intPt[1] = p2;
  22729. return q2.equals(p2) && !p1q1p2 && !q1p1q2 ? LineIntersector$$1.POINT_INTERSECTION : LineIntersector$$1.COLLINEAR_INTERSECTION
  22730. }
  22731. return LineIntersector$$1.NO_INTERSECTION
  22732. };
  22733. RobustLineIntersector.prototype.normalizeToEnvCentre = function normalizeToEnvCentre (n00, n01, n10, n11, normPt) {
  22734. var minX0 = n00.x < n01.x ? n00.x : n01.x;
  22735. var minY0 = n00.y < n01.y ? n00.y : n01.y;
  22736. var maxX0 = n00.x > n01.x ? n00.x : n01.x;
  22737. var maxY0 = n00.y > n01.y ? n00.y : n01.y;
  22738. var minX1 = n10.x < n11.x ? n10.x : n11.x;
  22739. var minY1 = n10.y < n11.y ? n10.y : n11.y;
  22740. var maxX1 = n10.x > n11.x ? n10.x : n11.x;
  22741. var maxY1 = n10.y > n11.y ? n10.y : n11.y;
  22742. var intMinX = minX0 > minX1 ? minX0 : minX1;
  22743. var intMaxX = maxX0 < maxX1 ? maxX0 : maxX1;
  22744. var intMinY = minY0 > minY1 ? minY0 : minY1;
  22745. var intMaxY = maxY0 < maxY1 ? maxY0 : maxY1;
  22746. var intMidX = (intMinX + intMaxX) / 2.0;
  22747. var intMidY = (intMinY + intMaxY) / 2.0;
  22748. normPt.x = intMidX;
  22749. normPt.y = intMidY;
  22750. n00.x -= normPt.x;
  22751. n00.y -= normPt.y;
  22752. n01.x -= normPt.x;
  22753. n01.y -= normPt.y;
  22754. n10.x -= normPt.x;
  22755. n10.y -= normPt.y;
  22756. n11.x -= normPt.x;
  22757. n11.y -= normPt.y;
  22758. };
  22759. RobustLineIntersector.prototype.computeIntersect = function computeIntersect (p1, p2, q1, q2) {
  22760. this._isProper = false;
  22761. if (!Envelope.intersects(p1, p2, q1, q2)) { return LineIntersector$$1.NO_INTERSECTION }
  22762. var Pq1 = CGAlgorithms.orientationIndex(p1, p2, q1);
  22763. var Pq2 = CGAlgorithms.orientationIndex(p1, p2, q2);
  22764. if ((Pq1 > 0 && Pq2 > 0) || (Pq1 < 0 && Pq2 < 0)) {
  22765. return LineIntersector$$1.NO_INTERSECTION
  22766. }
  22767. var Qp1 = CGAlgorithms.orientationIndex(q1, q2, p1);
  22768. var Qp2 = CGAlgorithms.orientationIndex(q1, q2, p2);
  22769. if ((Qp1 > 0 && Qp2 > 0) || (Qp1 < 0 && Qp2 < 0)) {
  22770. return LineIntersector$$1.NO_INTERSECTION
  22771. }
  22772. var collinear = Pq1 === 0 && Pq2 === 0 && Qp1 === 0 && Qp2 === 0;
  22773. if (collinear) {
  22774. return this.computeCollinearIntersection(p1, p2, q1, q2)
  22775. }
  22776. if (Pq1 === 0 || Pq2 === 0 || Qp1 === 0 || Qp2 === 0) {
  22777. this._isProper = false;
  22778. if (p1.equals2D(q1) || p1.equals2D(q2)) {
  22779. this._intPt[0] = p1;
  22780. } else if (p2.equals2D(q1) || p2.equals2D(q2)) {
  22781. this._intPt[0] = p2;
  22782. } else if (Pq1 === 0) {
  22783. this._intPt[0] = new Coordinate(q1);
  22784. } else if (Pq2 === 0) {
  22785. this._intPt[0] = new Coordinate(q2);
  22786. } else if (Qp1 === 0) {
  22787. this._intPt[0] = new Coordinate(p1);
  22788. } else if (Qp2 === 0) {
  22789. this._intPt[0] = new Coordinate(p2);
  22790. }
  22791. } else {
  22792. this._isProper = true;
  22793. this._intPt[0] = this.intersection(p1, p2, q1, q2);
  22794. }
  22795. return LineIntersector$$1.POINT_INTERSECTION
  22796. };
  22797. RobustLineIntersector.prototype.interfaces_ = function interfaces_ () {
  22798. return []
  22799. };
  22800. RobustLineIntersector.prototype.getClass = function getClass () {
  22801. return RobustLineIntersector
  22802. };
  22803. RobustLineIntersector.nearestEndpoint = function nearestEndpoint (p1, p2, q1, q2) {
  22804. var nearestPt = p1;
  22805. var minDist = CGAlgorithms.distancePointLine(p1, q1, q2);
  22806. var dist = CGAlgorithms.distancePointLine(p2, q1, q2);
  22807. if (dist < minDist) {
  22808. minDist = dist;
  22809. nearestPt = p2;
  22810. }
  22811. dist = CGAlgorithms.distancePointLine(q1, p1, p2);
  22812. if (dist < minDist) {
  22813. minDist = dist;
  22814. nearestPt = q1;
  22815. }
  22816. dist = CGAlgorithms.distancePointLine(q2, p1, p2);
  22817. if (dist < minDist) {
  22818. minDist = dist;
  22819. nearestPt = q2;
  22820. }
  22821. return nearestPt
  22822. };
  22823. return RobustLineIntersector;
  22824. }(LineIntersector));
  22825. var RobustDeterminant = function RobustDeterminant () {};
  22826. RobustDeterminant.prototype.interfaces_ = function interfaces_ () {
  22827. return []
  22828. };
  22829. RobustDeterminant.prototype.getClass = function getClass () {
  22830. return RobustDeterminant
  22831. };
  22832. RobustDeterminant.orientationIndex = function orientationIndex (p1, p2, q) {
  22833. var dx1 = p2.x - p1.x;
  22834. var dy1 = p2.y - p1.y;
  22835. var dx2 = q.x - p2.x;
  22836. var dy2 = q.y - p2.y;
  22837. return RobustDeterminant.signOfDet2x2(dx1, dy1, dx2, dy2)
  22838. };
  22839. RobustDeterminant.signOfDet2x2 = function signOfDet2x2 (x1, y1, x2, y2) {
  22840. var sign = null;
  22841. var swap = null;
  22842. var k = null;
  22843. sign = 1;
  22844. if (x1 === 0.0 || y2 === 0.0) {
  22845. if (y1 === 0.0 || x2 === 0.0) {
  22846. return 0
  22847. } else if (y1 > 0) {
  22848. if (x2 > 0) {
  22849. return -sign
  22850. } else {
  22851. return sign
  22852. }
  22853. } else {
  22854. if (x2 > 0) {
  22855. return sign
  22856. } else {
  22857. return -sign
  22858. }
  22859. }
  22860. }
  22861. if (y1 === 0.0 || x2 === 0.0) {
  22862. if (y2 > 0) {
  22863. if (x1 > 0) {
  22864. return sign
  22865. } else {
  22866. return -sign
  22867. }
  22868. } else {
  22869. if (x1 > 0) {
  22870. return -sign
  22871. } else {
  22872. return sign
  22873. }
  22874. }
  22875. }
  22876. if (y1 > 0.0) {
  22877. if (y2 > 0.0) {
  22878. if (y1 <= y2) {
  22879. } else {
  22880. sign = -sign;
  22881. swap = x1;
  22882. x1 = x2;
  22883. x2 = swap;
  22884. swap = y1;
  22885. y1 = y2;
  22886. y2 = swap;
  22887. }
  22888. } else {
  22889. if (y1 <= -y2) {
  22890. sign = -sign;
  22891. x2 = -x2;
  22892. y2 = -y2;
  22893. } else {
  22894. swap = x1;
  22895. x1 = -x2;
  22896. x2 = swap;
  22897. swap = y1;
  22898. y1 = -y2;
  22899. y2 = swap;
  22900. }
  22901. }
  22902. } else {
  22903. if (y2 > 0.0) {
  22904. if (-y1 <= y2) {
  22905. sign = -sign;
  22906. x1 = -x1;
  22907. y1 = -y1;
  22908. } else {
  22909. swap = -x1;
  22910. x1 = x2;
  22911. x2 = swap;
  22912. swap = -y1;
  22913. y1 = y2;
  22914. y2 = swap;
  22915. }
  22916. } else {
  22917. if (y1 >= y2) {
  22918. x1 = -x1;
  22919. y1 = -y1;
  22920. x2 = -x2;
  22921. y2 = -y2;
  22922. } else {
  22923. sign = -sign;
  22924. swap = -x1;
  22925. x1 = -x2;
  22926. x2 = swap;
  22927. swap = -y1;
  22928. y1 = -y2;
  22929. y2 = swap;
  22930. }
  22931. }
  22932. }
  22933. if (x1 > 0.0) {
  22934. if (x2 > 0.0) {
  22935. if (x1 <= x2) {
  22936. } else {
  22937. return sign
  22938. }
  22939. } else {
  22940. return sign
  22941. }
  22942. } else {
  22943. if (x2 > 0.0) {
  22944. return -sign
  22945. } else {
  22946. if (x1 >= x2) {
  22947. sign = -sign;
  22948. x1 = -x1;
  22949. x2 = -x2;
  22950. } else {
  22951. return -sign
  22952. }
  22953. }
  22954. }
  22955. while (true) {
  22956. k = Math.floor(x2 / x1);
  22957. x2 = x2 - k * x1;
  22958. y2 = y2 - k * y1;
  22959. if (y2 < 0.0) {
  22960. return -sign
  22961. }
  22962. if (y2 > y1) {
  22963. return sign
  22964. }
  22965. if (x1 > x2 + x2) {
  22966. if (y1 < y2 + y2) {
  22967. return sign
  22968. }
  22969. } else {
  22970. if (y1 > y2 + y2) {
  22971. return -sign
  22972. } else {
  22973. x2 = x1 - x2;
  22974. y2 = y1 - y2;
  22975. sign = -sign;
  22976. }
  22977. }
  22978. if (y2 === 0.0) {
  22979. if (x2 === 0.0) {
  22980. return 0
  22981. } else {
  22982. return -sign
  22983. }
  22984. }
  22985. if (x2 === 0.0) {
  22986. return sign
  22987. }
  22988. k = Math.floor(x1 / x2);
  22989. x1 = x1 - k * x2;
  22990. y1 = y1 - k * y2;
  22991. if (y1 < 0.0) {
  22992. return sign
  22993. }
  22994. if (y1 > y2) {
  22995. return -sign
  22996. }
  22997. if (x2 > x1 + x1) {
  22998. if (y2 < y1 + y1) {
  22999. return -sign
  23000. }
  23001. } else {
  23002. if (y2 > y1 + y1) {
  23003. return sign
  23004. } else {
  23005. x1 = x2 - x1;
  23006. y1 = y2 - y1;
  23007. sign = -sign;
  23008. }
  23009. }
  23010. if (y1 === 0.0) {
  23011. if (x1 === 0.0) {
  23012. return 0
  23013. } else {
  23014. return sign
  23015. }
  23016. }
  23017. if (x1 === 0.0) {
  23018. return -sign
  23019. }
  23020. }
  23021. };
  23022. var RayCrossingCounter = function RayCrossingCounter () {
  23023. this._p = null;
  23024. this._crossingCount = 0;
  23025. this._isPointOnSegment = false;
  23026. var p = arguments[0];
  23027. this._p = p;
  23028. };
  23029. RayCrossingCounter.prototype.countSegment = function countSegment (p1, p2) {
  23030. if (p1.x < this._p.x && p2.x < this._p.x) { return null }
  23031. if (this._p.x === p2.x && this._p.y === p2.y) {
  23032. this._isPointOnSegment = true;
  23033. return null
  23034. }
  23035. if (p1.y === this._p.y && p2.y === this._p.y) {
  23036. var minx = p1.x;
  23037. var maxx = p2.x;
  23038. if (minx > maxx) {
  23039. minx = p2.x;
  23040. maxx = p1.x;
  23041. }
  23042. if (this._p.x >= minx && this._p.x <= maxx) {
  23043. this._isPointOnSegment = true;
  23044. }
  23045. return null
  23046. }
  23047. if ((p1.y > this._p.y && p2.y <= this._p.y) || (p2.y > this._p.y && p1.y <= this._p.y)) {
  23048. var x1 = p1.x - this._p.x;
  23049. var y1 = p1.y - this._p.y;
  23050. var x2 = p2.x - this._p.x;
  23051. var y2 = p2.y - this._p.y;
  23052. var xIntSign = RobustDeterminant.signOfDet2x2(x1, y1, x2, y2);
  23053. if (xIntSign === 0.0) {
  23054. this._isPointOnSegment = true;
  23055. return null
  23056. }
  23057. if (y2 < y1) { xIntSign = -xIntSign; }
  23058. if (xIntSign > 0.0) {
  23059. this._crossingCount++;
  23060. }
  23061. }
  23062. };
  23063. RayCrossingCounter.prototype.isPointInPolygon = function isPointInPolygon () {
  23064. return this.getLocation() !== Location.EXTERIOR
  23065. };
  23066. RayCrossingCounter.prototype.getLocation = function getLocation () {
  23067. if (this._isPointOnSegment) { return Location.BOUNDARY }
  23068. if (this._crossingCount % 2 === 1) {
  23069. return Location.INTERIOR
  23070. }
  23071. return Location.EXTERIOR
  23072. };
  23073. RayCrossingCounter.prototype.isOnSegment = function isOnSegment () {
  23074. return this._isPointOnSegment
  23075. };
  23076. RayCrossingCounter.prototype.interfaces_ = function interfaces_ () {
  23077. return []
  23078. };
  23079. RayCrossingCounter.prototype.getClass = function getClass () {
  23080. return RayCrossingCounter
  23081. };
  23082. RayCrossingCounter.locatePointInRing = function locatePointInRing () {
  23083. if (arguments[0] instanceof Coordinate && hasInterface(arguments[1], CoordinateSequence)) {
  23084. var p = arguments[0];
  23085. var ring = arguments[1];
  23086. var counter = new RayCrossingCounter(p);
  23087. var p1 = new Coordinate();
  23088. var p2 = new Coordinate();
  23089. for (var i = 1; i < ring.size(); i++) {
  23090. ring.getCoordinate(i, p1);
  23091. ring.getCoordinate(i - 1, p2);
  23092. counter.countSegment(p1, p2);
  23093. if (counter.isOnSegment()) { return counter.getLocation() }
  23094. }
  23095. return counter.getLocation()
  23096. } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Array) {
  23097. var p$1 = arguments[0];
  23098. var ring$1 = arguments[1];
  23099. var counter$1 = new RayCrossingCounter(p$1);
  23100. for (var i$1 = 1; i$1 < ring$1.length; i$1++) {
  23101. var p1$1 = ring$1[i$1];
  23102. var p2$1 = ring$1[i$1 - 1];
  23103. counter$1.countSegment(p1$1, p2$1);
  23104. if (counter$1.isOnSegment()) { return counter$1.getLocation() }
  23105. }
  23106. return counter$1.getLocation()
  23107. }
  23108. };
  23109. var CGAlgorithms = function CGAlgorithms () {};
  23110. var staticAccessors$3 = { CLOCKWISE: { configurable: true },RIGHT: { configurable: true },COUNTERCLOCKWISE: { configurable: true },LEFT: { configurable: true },COLLINEAR: { configurable: true },STRAIGHT: { configurable: true } };
  23111. CGAlgorithms.prototype.interfaces_ = function interfaces_ () {
  23112. return []
  23113. };
  23114. CGAlgorithms.prototype.getClass = function getClass () {
  23115. return CGAlgorithms
  23116. };
  23117. CGAlgorithms.orientationIndex = function orientationIndex (p1, p2, q) {
  23118. return CGAlgorithmsDD.orientationIndex(p1, p2, q)
  23119. };
  23120. CGAlgorithms.signedArea = function signedArea () {
  23121. if (arguments[0] instanceof Array) {
  23122. var ring = arguments[0];
  23123. if (ring.length < 3) { return 0.0 }
  23124. var sum = 0.0;
  23125. var x0 = ring[0].x;
  23126. for (var i = 1; i < ring.length - 1; i++) {
  23127. var x = ring[i].x - x0;
  23128. var y1 = ring[i + 1].y;
  23129. var y2 = ring[i - 1].y;
  23130. sum += x * (y2 - y1);
  23131. }
  23132. return sum / 2.0
  23133. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  23134. var ring$1 = arguments[0];
  23135. var n = ring$1.size();
  23136. if (n < 3) { return 0.0 }
  23137. var p0 = new Coordinate();
  23138. var p1 = new Coordinate();
  23139. var p2 = new Coordinate();
  23140. ring$1.getCoordinate(0, p1);
  23141. ring$1.getCoordinate(1, p2);
  23142. var x0$1 = p1.x;
  23143. p2.x -= x0$1;
  23144. var sum$1 = 0.0;
  23145. for (var i$1 = 1; i$1 < n - 1; i$1++) {
  23146. p0.y = p1.y;
  23147. p1.x = p2.x;
  23148. p1.y = p2.y;
  23149. ring$1.getCoordinate(i$1 + 1, p2);
  23150. p2.x -= x0$1;
  23151. sum$1 += p1.x * (p0.y - p2.y);
  23152. }
  23153. return sum$1 / 2.0
  23154. }
  23155. };
  23156. CGAlgorithms.distanceLineLine = function distanceLineLine (A, B, C, D) {
  23157. if (A.equals(B)) { return CGAlgorithms.distancePointLine(A, C, D) }
  23158. if (C.equals(D)) { return CGAlgorithms.distancePointLine(D, A, B) }
  23159. var noIntersection = false;
  23160. if (!Envelope.intersects(A, B, C, D)) {
  23161. noIntersection = true;
  23162. } else {
  23163. var denom = (B.x - A.x) * (D.y - C.y) - (B.y - A.y) * (D.x - C.x);
  23164. if (denom === 0) {
  23165. noIntersection = true;
  23166. } else {
  23167. var rNumb = (A.y - C.y) * (D.x - C.x) - (A.x - C.x) * (D.y - C.y);
  23168. var sNum = (A.y - C.y) * (B.x - A.x) - (A.x - C.x) * (B.y - A.y);
  23169. var s = sNum / denom;
  23170. var r = rNumb / denom;
  23171. if (r < 0 || r > 1 || s < 0 || s > 1) {
  23172. noIntersection = true;
  23173. }
  23174. }
  23175. }
  23176. if (noIntersection) {
  23177. return MathUtil.min(CGAlgorithms.distancePointLine(A, C, D), CGAlgorithms.distancePointLine(B, C, D), CGAlgorithms.distancePointLine(C, A, B), CGAlgorithms.distancePointLine(D, A, B))
  23178. }
  23179. return 0.0
  23180. };
  23181. CGAlgorithms.isPointInRing = function isPointInRing (p, ring) {
  23182. return CGAlgorithms.locatePointInRing(p, ring) !== Location.EXTERIOR
  23183. };
  23184. CGAlgorithms.computeLength = function computeLength (pts) {
  23185. var n = pts.size();
  23186. if (n <= 1) { return 0.0 }
  23187. var len = 0.0;
  23188. var p = new Coordinate();
  23189. pts.getCoordinate(0, p);
  23190. var x0 = p.x;
  23191. var y0 = p.y;
  23192. for (var i = 1; i < n; i++) {
  23193. pts.getCoordinate(i, p);
  23194. var x1 = p.x;
  23195. var y1 = p.y;
  23196. var dx = x1 - x0;
  23197. var dy = y1 - y0;
  23198. len += Math.sqrt(dx * dx + dy * dy);
  23199. x0 = x1;
  23200. y0 = y1;
  23201. }
  23202. return len
  23203. };
  23204. CGAlgorithms.isCCW = function isCCW (ring) {
  23205. var nPts = ring.length - 1;
  23206. if (nPts < 3) { throw new IllegalArgumentException('Ring has fewer than 4 points, so orientation cannot be determined') }
  23207. var hiPt = ring[0];
  23208. var hiIndex = 0;
  23209. for (var i = 1; i <= nPts; i++) {
  23210. var p = ring[i];
  23211. if (p.y > hiPt.y) {
  23212. hiPt = p;
  23213. hiIndex = i;
  23214. }
  23215. }
  23216. var iPrev = hiIndex;
  23217. do {
  23218. iPrev = iPrev - 1;
  23219. if (iPrev < 0) { iPrev = nPts; }
  23220. } while (ring[iPrev].equals2D(hiPt) && iPrev !== hiIndex)
  23221. var iNext = hiIndex;
  23222. do {
  23223. iNext = (iNext + 1) % nPts;
  23224. } while (ring[iNext].equals2D(hiPt) && iNext !== hiIndex)
  23225. var prev = ring[iPrev];
  23226. var next = ring[iNext];
  23227. if (prev.equals2D(hiPt) || next.equals2D(hiPt) || prev.equals2D(next)) { return false }
  23228. var disc = CGAlgorithms.computeOrientation(prev, hiPt, next);
  23229. var isCCW = false;
  23230. if (disc === 0) {
  23231. isCCW = prev.x > next.x;
  23232. } else {
  23233. isCCW = disc > 0;
  23234. }
  23235. return isCCW
  23236. };
  23237. CGAlgorithms.locatePointInRing = function locatePointInRing (p, ring) {
  23238. return RayCrossingCounter.locatePointInRing(p, ring)
  23239. };
  23240. CGAlgorithms.distancePointLinePerpendicular = function distancePointLinePerpendicular (p, A, B) {
  23241. var len2 = (B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y);
  23242. var s = ((A.y - p.y) * (B.x - A.x) - (A.x - p.x) * (B.y - A.y)) / len2;
  23243. return Math.abs(s) * Math.sqrt(len2)
  23244. };
  23245. CGAlgorithms.computeOrientation = function computeOrientation (p1, p2, q) {
  23246. return CGAlgorithms.orientationIndex(p1, p2, q)
  23247. };
  23248. CGAlgorithms.distancePointLine = function distancePointLine () {
  23249. if (arguments.length === 2) {
  23250. var p = arguments[0];
  23251. var line = arguments[1];
  23252. if (line.length === 0) { throw new IllegalArgumentException('Line array must contain at least one vertex') }
  23253. var minDistance = p.distance(line[0]);
  23254. for (var i = 0; i < line.length - 1; i++) {
  23255. var dist = CGAlgorithms.distancePointLine(p, line[i], line[i + 1]);
  23256. if (dist < minDistance) {
  23257. minDistance = dist;
  23258. }
  23259. }
  23260. return minDistance
  23261. } else if (arguments.length === 3) {
  23262. var p$1 = arguments[0];
  23263. var A = arguments[1];
  23264. var B = arguments[2];
  23265. if (A.x === B.x && A.y === B.y) { return p$1.distance(A) }
  23266. var len2 = (B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y);
  23267. var r = ((p$1.x - A.x) * (B.x - A.x) + (p$1.y - A.y) * (B.y - A.y)) / len2;
  23268. if (r <= 0.0) { return p$1.distance(A) }
  23269. if (r >= 1.0) { return p$1.distance(B) }
  23270. var s = ((A.y - p$1.y) * (B.x - A.x) - (A.x - p$1.x) * (B.y - A.y)) / len2;
  23271. return Math.abs(s) * Math.sqrt(len2)
  23272. }
  23273. };
  23274. CGAlgorithms.isOnLine = function isOnLine (p, pt) {
  23275. var lineIntersector = new RobustLineIntersector();
  23276. for (var i = 1; i < pt.length; i++) {
  23277. var p0 = pt[i - 1];
  23278. var p1 = pt[i];
  23279. lineIntersector.computeIntersection(p, p0, p1);
  23280. if (lineIntersector.hasIntersection()) {
  23281. return true
  23282. }
  23283. }
  23284. return false
  23285. };
  23286. staticAccessors$3.CLOCKWISE.get = function () { return -1 };
  23287. staticAccessors$3.RIGHT.get = function () { return CGAlgorithms.CLOCKWISE };
  23288. staticAccessors$3.COUNTERCLOCKWISE.get = function () { return 1 };
  23289. staticAccessors$3.LEFT.get = function () { return CGAlgorithms.COUNTERCLOCKWISE };
  23290. staticAccessors$3.COLLINEAR.get = function () { return 0 };
  23291. staticAccessors$3.STRAIGHT.get = function () { return CGAlgorithms.COLLINEAR };
  23292. Object.defineProperties( CGAlgorithms, staticAccessors$3 );
  23293. var GeometryComponentFilter = function GeometryComponentFilter () {};
  23294. GeometryComponentFilter.prototype.filter = function filter (geom) {};
  23295. GeometryComponentFilter.prototype.interfaces_ = function interfaces_ () {
  23296. return []
  23297. };
  23298. GeometryComponentFilter.prototype.getClass = function getClass () {
  23299. return GeometryComponentFilter
  23300. };
  23301. var Geometry = function Geometry () {
  23302. var factory = arguments[0];
  23303. this._envelope = null;
  23304. this._factory = null;
  23305. this._SRID = null;
  23306. this._userData = null;
  23307. this._factory = factory;
  23308. this._SRID = factory.getSRID();
  23309. };
  23310. var staticAccessors$11 = { serialVersionUID: { configurable: true },SORTINDEX_POINT: { configurable: true },SORTINDEX_MULTIPOINT: { configurable: true },SORTINDEX_LINESTRING: { configurable: true },SORTINDEX_LINEARRING: { configurable: true },SORTINDEX_MULTILINESTRING: { configurable: true },SORTINDEX_POLYGON: { configurable: true },SORTINDEX_MULTIPOLYGON: { configurable: true },SORTINDEX_GEOMETRYCOLLECTION: { configurable: true },geometryChangedFilter: { configurable: true } };
  23311. Geometry.prototype.isGeometryCollection = function isGeometryCollection () {
  23312. return this.getSortIndex() === Geometry.SORTINDEX_GEOMETRYCOLLECTION
  23313. };
  23314. Geometry.prototype.getFactory = function getFactory () {
  23315. return this._factory
  23316. };
  23317. Geometry.prototype.getGeometryN = function getGeometryN (n) {
  23318. return this
  23319. };
  23320. Geometry.prototype.getArea = function getArea () {
  23321. return 0.0
  23322. };
  23323. Geometry.prototype.isRectangle = function isRectangle () {
  23324. return false
  23325. };
  23326. Geometry.prototype.equals = function equals () {
  23327. if (arguments[0] instanceof Geometry) {
  23328. var g$1 = arguments[0];
  23329. if (g$1 === null) { return false }
  23330. return this.equalsTopo(g$1)
  23331. } else if (arguments[0] instanceof Object) {
  23332. var o = arguments[0];
  23333. if (!(o instanceof Geometry)) { return false }
  23334. var g = o;
  23335. return this.equalsExact(g)
  23336. }
  23337. };
  23338. Geometry.prototype.equalsExact = function equalsExact (other) {
  23339. return this === other || this.equalsExact(other, 0)
  23340. };
  23341. Geometry.prototype.geometryChanged = function geometryChanged () {
  23342. this.apply(Geometry.geometryChangedFilter);
  23343. };
  23344. Geometry.prototype.geometryChangedAction = function geometryChangedAction () {
  23345. this._envelope = null;
  23346. };
  23347. Geometry.prototype.equalsNorm = function equalsNorm (g) {
  23348. if (g === null) { return false }
  23349. return this.norm().equalsExact(g.norm())
  23350. };
  23351. Geometry.prototype.getLength = function getLength () {
  23352. return 0.0
  23353. };
  23354. Geometry.prototype.getNumGeometries = function getNumGeometries () {
  23355. return 1
  23356. };
  23357. Geometry.prototype.compareTo = function compareTo () {
  23358. if (arguments.length === 1) {
  23359. var o = arguments[0];
  23360. var other = o;
  23361. if (this.getSortIndex() !== other.getSortIndex()) {
  23362. return this.getSortIndex() - other.getSortIndex()
  23363. }
  23364. if (this.isEmpty() && other.isEmpty()) {
  23365. return 0
  23366. }
  23367. if (this.isEmpty()) {
  23368. return -1
  23369. }
  23370. if (other.isEmpty()) {
  23371. return 1
  23372. }
  23373. return this.compareToSameClass(o)
  23374. } else if (arguments.length === 2) {
  23375. var other$1 = arguments[0];
  23376. var comp = arguments[1];
  23377. if (this.getSortIndex() !== other$1.getSortIndex()) {
  23378. return this.getSortIndex() - other$1.getSortIndex()
  23379. }
  23380. if (this.isEmpty() && other$1.isEmpty()) {
  23381. return 0
  23382. }
  23383. if (this.isEmpty()) {
  23384. return -1
  23385. }
  23386. if (other$1.isEmpty()) {
  23387. return 1
  23388. }
  23389. return this.compareToSameClass(other$1, comp)
  23390. }
  23391. };
  23392. Geometry.prototype.getUserData = function getUserData () {
  23393. return this._userData
  23394. };
  23395. Geometry.prototype.getSRID = function getSRID () {
  23396. return this._SRID
  23397. };
  23398. Geometry.prototype.getEnvelope = function getEnvelope () {
  23399. return this.getFactory().toGeometry(this.getEnvelopeInternal())
  23400. };
  23401. Geometry.prototype.checkNotGeometryCollection = function checkNotGeometryCollection (g) {
  23402. if (g.getSortIndex() === Geometry.SORTINDEX_GEOMETRYCOLLECTION) {
  23403. throw new IllegalArgumentException('This method does not support GeometryCollection arguments')
  23404. }
  23405. };
  23406. Geometry.prototype.equal = function equal (a, b, tolerance) {
  23407. if (tolerance === 0) {
  23408. return a.equals(b)
  23409. }
  23410. return a.distance(b) <= tolerance
  23411. };
  23412. Geometry.prototype.norm = function norm () {
  23413. var copy = this.copy();
  23414. copy.normalize();
  23415. return copy
  23416. };
  23417. Geometry.prototype.getPrecisionModel = function getPrecisionModel () {
  23418. return this._factory.getPrecisionModel()
  23419. };
  23420. Geometry.prototype.getEnvelopeInternal = function getEnvelopeInternal () {
  23421. if (this._envelope === null) {
  23422. this._envelope = this.computeEnvelopeInternal();
  23423. }
  23424. return new Envelope(this._envelope)
  23425. };
  23426. Geometry.prototype.setSRID = function setSRID (SRID) {
  23427. this._SRID = SRID;
  23428. };
  23429. Geometry.prototype.setUserData = function setUserData (userData) {
  23430. this._userData = userData;
  23431. };
  23432. Geometry.prototype.compare = function compare (a, b) {
  23433. var i = a.iterator();
  23434. var j = b.iterator();
  23435. while (i.hasNext() && j.hasNext()) {
  23436. var aElement = i.next();
  23437. var bElement = j.next();
  23438. var comparison = aElement.compareTo(bElement);
  23439. if (comparison !== 0) {
  23440. return comparison
  23441. }
  23442. }
  23443. if (i.hasNext()) {
  23444. return 1
  23445. }
  23446. if (j.hasNext()) {
  23447. return -1
  23448. }
  23449. return 0
  23450. };
  23451. Geometry.prototype.hashCode = function hashCode () {
  23452. return this.getEnvelopeInternal().hashCode()
  23453. };
  23454. Geometry.prototype.isGeometryCollectionOrDerived = function isGeometryCollectionOrDerived () {
  23455. if (this.getSortIndex() === Geometry.SORTINDEX_GEOMETRYCOLLECTION || this.getSortIndex() === Geometry.SORTINDEX_MULTIPOINT || this.getSortIndex() === Geometry.SORTINDEX_MULTILINESTRING || this.getSortIndex() === Geometry.SORTINDEX_MULTIPOLYGON) {
  23456. return true
  23457. }
  23458. return false
  23459. };
  23460. Geometry.prototype.interfaces_ = function interfaces_ () {
  23461. return [Clonable, Comparable, Serializable]
  23462. };
  23463. Geometry.prototype.getClass = function getClass () {
  23464. return Geometry
  23465. };
  23466. Geometry.hasNonEmptyElements = function hasNonEmptyElements (geometries) {
  23467. for (var i = 0; i < geometries.length; i++) {
  23468. if (!geometries[i].isEmpty()) {
  23469. return true
  23470. }
  23471. }
  23472. return false
  23473. };
  23474. Geometry.hasNullElements = function hasNullElements (array) {
  23475. for (var i = 0; i < array.length; i++) {
  23476. if (array[i] === null) {
  23477. return true
  23478. }
  23479. }
  23480. return false
  23481. };
  23482. staticAccessors$11.serialVersionUID.get = function () { return 8763622679187376702 };
  23483. staticAccessors$11.SORTINDEX_POINT.get = function () { return 0 };
  23484. staticAccessors$11.SORTINDEX_MULTIPOINT.get = function () { return 1 };
  23485. staticAccessors$11.SORTINDEX_LINESTRING.get = function () { return 2 };
  23486. staticAccessors$11.SORTINDEX_LINEARRING.get = function () { return 3 };
  23487. staticAccessors$11.SORTINDEX_MULTILINESTRING.get = function () { return 4 };
  23488. staticAccessors$11.SORTINDEX_POLYGON.get = function () { return 5 };
  23489. staticAccessors$11.SORTINDEX_MULTIPOLYGON.get = function () { return 6 };
  23490. staticAccessors$11.SORTINDEX_GEOMETRYCOLLECTION.get = function () { return 7 };
  23491. staticAccessors$11.geometryChangedFilter.get = function () { return geometryChangedFilter };
  23492. Object.defineProperties( Geometry, staticAccessors$11 );
  23493. var geometryChangedFilter = function geometryChangedFilter () {};
  23494. geometryChangedFilter.interfaces_ = function interfaces_ () {
  23495. return [GeometryComponentFilter]
  23496. };
  23497. geometryChangedFilter.filter = function filter (geom) {
  23498. geom.geometryChangedAction();
  23499. };
  23500. var CoordinateFilter = function CoordinateFilter () {};
  23501. CoordinateFilter.prototype.filter = function filter (coord) {};
  23502. CoordinateFilter.prototype.interfaces_ = function interfaces_ () {
  23503. return []
  23504. };
  23505. CoordinateFilter.prototype.getClass = function getClass () {
  23506. return CoordinateFilter
  23507. };
  23508. var BoundaryNodeRule = function BoundaryNodeRule () {};
  23509. var staticAccessors$12 = { Mod2BoundaryNodeRule: { configurable: true },EndPointBoundaryNodeRule: { configurable: true },MultiValentEndPointBoundaryNodeRule: { configurable: true },MonoValentEndPointBoundaryNodeRule: { configurable: true },MOD2_BOUNDARY_RULE: { configurable: true },ENDPOINT_BOUNDARY_RULE: { configurable: true },MULTIVALENT_ENDPOINT_BOUNDARY_RULE: { configurable: true },MONOVALENT_ENDPOINT_BOUNDARY_RULE: { configurable: true },OGC_SFS_BOUNDARY_RULE: { configurable: true } };
  23510. BoundaryNodeRule.prototype.isInBoundary = function isInBoundary (boundaryCount) {};
  23511. BoundaryNodeRule.prototype.interfaces_ = function interfaces_ () {
  23512. return []
  23513. };
  23514. BoundaryNodeRule.prototype.getClass = function getClass () {
  23515. return BoundaryNodeRule
  23516. };
  23517. staticAccessors$12.Mod2BoundaryNodeRule.get = function () { return Mod2BoundaryNodeRule };
  23518. staticAccessors$12.EndPointBoundaryNodeRule.get = function () { return EndPointBoundaryNodeRule };
  23519. staticAccessors$12.MultiValentEndPointBoundaryNodeRule.get = function () { return MultiValentEndPointBoundaryNodeRule };
  23520. staticAccessors$12.MonoValentEndPointBoundaryNodeRule.get = function () { return MonoValentEndPointBoundaryNodeRule };
  23521. staticAccessors$12.MOD2_BOUNDARY_RULE.get = function () { return new Mod2BoundaryNodeRule() };
  23522. staticAccessors$12.ENDPOINT_BOUNDARY_RULE.get = function () { return new EndPointBoundaryNodeRule() };
  23523. staticAccessors$12.MULTIVALENT_ENDPOINT_BOUNDARY_RULE.get = function () { return new MultiValentEndPointBoundaryNodeRule() };
  23524. staticAccessors$12.MONOVALENT_ENDPOINT_BOUNDARY_RULE.get = function () { return new MonoValentEndPointBoundaryNodeRule() };
  23525. staticAccessors$12.OGC_SFS_BOUNDARY_RULE.get = function () { return BoundaryNodeRule.MOD2_BOUNDARY_RULE };
  23526. Object.defineProperties( BoundaryNodeRule, staticAccessors$12 );
  23527. var Mod2BoundaryNodeRule = function Mod2BoundaryNodeRule () {};
  23528. Mod2BoundaryNodeRule.prototype.isInBoundary = function isInBoundary (boundaryCount) {
  23529. return boundaryCount % 2 === 1
  23530. };
  23531. Mod2BoundaryNodeRule.prototype.interfaces_ = function interfaces_ () {
  23532. return [BoundaryNodeRule]
  23533. };
  23534. Mod2BoundaryNodeRule.prototype.getClass = function getClass () {
  23535. return Mod2BoundaryNodeRule
  23536. };
  23537. var EndPointBoundaryNodeRule = function EndPointBoundaryNodeRule () {};
  23538. EndPointBoundaryNodeRule.prototype.isInBoundary = function isInBoundary (boundaryCount) {
  23539. return boundaryCount > 0
  23540. };
  23541. EndPointBoundaryNodeRule.prototype.interfaces_ = function interfaces_ () {
  23542. return [BoundaryNodeRule]
  23543. };
  23544. EndPointBoundaryNodeRule.prototype.getClass = function getClass () {
  23545. return EndPointBoundaryNodeRule
  23546. };
  23547. var MultiValentEndPointBoundaryNodeRule = function MultiValentEndPointBoundaryNodeRule () {};
  23548. MultiValentEndPointBoundaryNodeRule.prototype.isInBoundary = function isInBoundary (boundaryCount) {
  23549. return boundaryCount > 1
  23550. };
  23551. MultiValentEndPointBoundaryNodeRule.prototype.interfaces_ = function interfaces_ () {
  23552. return [BoundaryNodeRule]
  23553. };
  23554. MultiValentEndPointBoundaryNodeRule.prototype.getClass = function getClass () {
  23555. return MultiValentEndPointBoundaryNodeRule
  23556. };
  23557. var MonoValentEndPointBoundaryNodeRule = function MonoValentEndPointBoundaryNodeRule () {};
  23558. MonoValentEndPointBoundaryNodeRule.prototype.isInBoundary = function isInBoundary (boundaryCount) {
  23559. return boundaryCount === 1
  23560. };
  23561. MonoValentEndPointBoundaryNodeRule.prototype.interfaces_ = function interfaces_ () {
  23562. return [BoundaryNodeRule]
  23563. };
  23564. MonoValentEndPointBoundaryNodeRule.prototype.getClass = function getClass () {
  23565. return MonoValentEndPointBoundaryNodeRule
  23566. };
  23567. // import Iterator from './Iterator'
  23568. /**
  23569. * @see http://download.oracle.com/javase/6/docs/api/java/util/Collection.html
  23570. *
  23571. * @constructor
  23572. * @private
  23573. */
  23574. var Collection = function Collection () {};
  23575. Collection.prototype.add = function add () {};
  23576. /**
  23577. * Appends all of the elements in the specified collection to the end of this
  23578. * list, in the order that they are returned by the specified collection's
  23579. * iterator (optional operation).
  23580. * @param {javascript.util.Collection} c
  23581. * @return {boolean}
  23582. */
  23583. Collection.prototype.addAll = function addAll () {};
  23584. /**
  23585. * Returns true if this collection contains no elements.
  23586. * @return {boolean}
  23587. */
  23588. Collection.prototype.isEmpty = function isEmpty () {};
  23589. /**
  23590. * Returns an iterator over the elements in this collection.
  23591. * @return {javascript.util.Iterator}
  23592. */
  23593. Collection.prototype.iterator = function iterator () {};
  23594. /**
  23595. * Returns an iterator over the elements in this collection.
  23596. * @return {number}
  23597. */
  23598. Collection.prototype.size = function size () {};
  23599. /**
  23600. * Returns an array containing all of the elements in this collection.
  23601. * @return {Array}
  23602. */
  23603. Collection.prototype.toArray = function toArray () {};
  23604. /**
  23605. * Removes a single instance of the specified element from this collection if it
  23606. * is present. (optional)
  23607. * @param {Object} e
  23608. * @return {boolean}
  23609. */
  23610. Collection.prototype.remove = function remove () {};
  23611. /**
  23612. * @param {string} [message] Optional message
  23613. * @extends {Error}
  23614. * @constructor
  23615. * @private
  23616. */
  23617. var IndexOutOfBoundsException = (function (Error) {
  23618. function IndexOutOfBoundsException (message) {
  23619. Error.call(this);
  23620. this.message = message || '';
  23621. }
  23622. if ( Error ) IndexOutOfBoundsException.__proto__ = Error;
  23623. IndexOutOfBoundsException.prototype = Object.create( Error && Error.prototype );
  23624. IndexOutOfBoundsException.prototype.constructor = IndexOutOfBoundsException;
  23625. var staticAccessors = { name: { configurable: true } };
  23626. /**
  23627. * @type {string}
  23628. */
  23629. staticAccessors.name.get = function () { return 'IndexOutOfBoundsException' };
  23630. Object.defineProperties( IndexOutOfBoundsException, staticAccessors );
  23631. return IndexOutOfBoundsException;
  23632. }(Error));
  23633. /**
  23634. * @see http://download.oracle.com/javase/6/docs/api/java/util/Iterator.html
  23635. * @constructor
  23636. * @private
  23637. */
  23638. var Iterator = function Iterator () {};
  23639. Iterator.prototype.hasNext = function hasNext () {};
  23640. /**
  23641. * Returns the next element in the iteration.
  23642. * @return {Object}
  23643. */
  23644. Iterator.prototype.next = function next () {};
  23645. /**
  23646. * Removes from the underlying collection the last element returned by the
  23647. * iterator (optional operation).
  23648. */
  23649. Iterator.prototype.remove = function remove () {};
  23650. /**
  23651. * @see http://download.oracle.com/javase/6/docs/api/java/util/List.html
  23652. *
  23653. * @extends {javascript.util.Collection}
  23654. * @constructor
  23655. * @private
  23656. */
  23657. var List = (function (Collection$$1) {
  23658. function List () {
  23659. Collection$$1.apply(this, arguments);
  23660. }
  23661. if ( Collection$$1 ) List.__proto__ = Collection$$1;
  23662. List.prototype = Object.create( Collection$$1 && Collection$$1.prototype );
  23663. List.prototype.constructor = List;
  23664. List.prototype.get = function get () { };
  23665. /**
  23666. * Replaces the element at the specified position in this list with the
  23667. * specified element (optional operation).
  23668. * @param {number} index
  23669. * @param {Object} e
  23670. * @return {Object}
  23671. */
  23672. List.prototype.set = function set () { };
  23673. /**
  23674. * Returns true if this collection contains no elements.
  23675. * @return {boolean}
  23676. */
  23677. List.prototype.isEmpty = function isEmpty () { };
  23678. return List;
  23679. }(Collection));
  23680. /**
  23681. * @param {string=} message Optional message
  23682. * @extends {Error}
  23683. * @constructor
  23684. * @private
  23685. */
  23686. function NoSuchElementException (message) {
  23687. this.message = message || '';
  23688. }
  23689. NoSuchElementException.prototype = new Error();
  23690. /**
  23691. * @type {string}
  23692. */
  23693. NoSuchElementException.prototype.name = 'NoSuchElementException';
  23694. // import OperationNotSupported from './OperationNotSupported'
  23695. /**
  23696. * @see http://download.oracle.com/javase/6/docs/api/java/util/ArrayList.html
  23697. *
  23698. * @extends List
  23699. * @private
  23700. */
  23701. var ArrayList = (function (List$$1) {
  23702. function ArrayList () {
  23703. List$$1.call(this);
  23704. this.array_ = [];
  23705. if (arguments[0] instanceof Collection) {
  23706. this.addAll(arguments[0]);
  23707. }
  23708. }
  23709. if ( List$$1 ) ArrayList.__proto__ = List$$1;
  23710. ArrayList.prototype = Object.create( List$$1 && List$$1.prototype );
  23711. ArrayList.prototype.constructor = ArrayList;
  23712. ArrayList.prototype.ensureCapacity = function ensureCapacity () {};
  23713. ArrayList.prototype.interfaces_ = function interfaces_ () { return [List$$1, Collection] };
  23714. /**
  23715. * @override
  23716. */
  23717. ArrayList.prototype.add = function add (e) {
  23718. if (arguments.length === 1) {
  23719. this.array_.push(e);
  23720. } else {
  23721. this.array_.splice(arguments[0], arguments[1]);
  23722. }
  23723. return true
  23724. };
  23725. ArrayList.prototype.clear = function clear () {
  23726. this.array_ = [];
  23727. };
  23728. /**
  23729. * @override
  23730. */
  23731. ArrayList.prototype.addAll = function addAll (c) {
  23732. var this$1 = this;
  23733. for (var i = c.iterator(); i.hasNext();) {
  23734. this$1.add(i.next());
  23735. }
  23736. return true
  23737. };
  23738. /**
  23739. * @override
  23740. */
  23741. ArrayList.prototype.set = function set (index, element) {
  23742. var oldElement = this.array_[index];
  23743. this.array_[index] = element;
  23744. return oldElement
  23745. };
  23746. /**
  23747. * @override
  23748. */
  23749. ArrayList.prototype.iterator = function iterator () {
  23750. return new Iterator_(this)
  23751. };
  23752. /**
  23753. * @override
  23754. */
  23755. ArrayList.prototype.get = function get (index) {
  23756. if (index < 0 || index >= this.size()) {
  23757. throw new IndexOutOfBoundsException()
  23758. }
  23759. return this.array_[index]
  23760. };
  23761. /**
  23762. * @override
  23763. */
  23764. ArrayList.prototype.isEmpty = function isEmpty () {
  23765. return this.array_.length === 0
  23766. };
  23767. /**
  23768. * @override
  23769. */
  23770. ArrayList.prototype.size = function size () {
  23771. return this.array_.length
  23772. };
  23773. /**
  23774. * @override
  23775. */
  23776. ArrayList.prototype.toArray = function toArray () {
  23777. var this$1 = this;
  23778. var array = [];
  23779. for (var i = 0, len = this.array_.length; i < len; i++) {
  23780. array.push(this$1.array_[i]);
  23781. }
  23782. return array
  23783. };
  23784. /**
  23785. * @override
  23786. */
  23787. ArrayList.prototype.remove = function remove (o) {
  23788. var this$1 = this;
  23789. var found = false;
  23790. for (var i = 0, len = this.array_.length; i < len; i++) {
  23791. if (this$1.array_[i] === o) {
  23792. this$1.array_.splice(i, 1);
  23793. found = true;
  23794. break
  23795. }
  23796. }
  23797. return found
  23798. };
  23799. return ArrayList;
  23800. }(List));
  23801. /**
  23802. * @extends {Iterator}
  23803. * @param {ArrayList} arrayList
  23804. * @constructor
  23805. * @private
  23806. */
  23807. var Iterator_ = (function (Iterator$$1) {
  23808. function Iterator_ (arrayList) {
  23809. Iterator$$1.call(this);
  23810. /**
  23811. * @type {ArrayList}
  23812. * @private
  23813. */
  23814. this.arrayList_ = arrayList;
  23815. /**
  23816. * @type {number}
  23817. * @private
  23818. */
  23819. this.position_ = 0;
  23820. }
  23821. if ( Iterator$$1 ) Iterator_.__proto__ = Iterator$$1;
  23822. Iterator_.prototype = Object.create( Iterator$$1 && Iterator$$1.prototype );
  23823. Iterator_.prototype.constructor = Iterator_;
  23824. /**
  23825. * @override
  23826. */
  23827. Iterator_.prototype.next = function next () {
  23828. if (this.position_ === this.arrayList_.size()) {
  23829. throw new NoSuchElementException()
  23830. }
  23831. return this.arrayList_.get(this.position_++)
  23832. };
  23833. /**
  23834. * @override
  23835. */
  23836. Iterator_.prototype.hasNext = function hasNext () {
  23837. if (this.position_ < this.arrayList_.size()) {
  23838. return true
  23839. } else {
  23840. return false
  23841. }
  23842. };
  23843. /**
  23844. * TODO: should be in ListIterator
  23845. * @override
  23846. */
  23847. Iterator_.prototype.set = function set (element) {
  23848. return this.arrayList_.set(this.position_ - 1, element)
  23849. };
  23850. /**
  23851. * @override
  23852. */
  23853. Iterator_.prototype.remove = function remove () {
  23854. this.arrayList_.remove(this.arrayList_.get(this.position_));
  23855. };
  23856. return Iterator_;
  23857. }(Iterator));
  23858. var CoordinateList = (function (ArrayList$$1) {
  23859. function CoordinateList () {
  23860. ArrayList$$1.call(this);
  23861. if (arguments.length === 0) {
  23862. } else if (arguments.length === 1) {
  23863. var coord = arguments[0];
  23864. this.ensureCapacity(coord.length);
  23865. this.add(coord, true);
  23866. } else if (arguments.length === 2) {
  23867. var coord$1 = arguments[0];
  23868. var allowRepeated = arguments[1];
  23869. this.ensureCapacity(coord$1.length);
  23870. this.add(coord$1, allowRepeated);
  23871. }
  23872. }
  23873. if ( ArrayList$$1 ) CoordinateList.__proto__ = ArrayList$$1;
  23874. CoordinateList.prototype = Object.create( ArrayList$$1 && ArrayList$$1.prototype );
  23875. CoordinateList.prototype.constructor = CoordinateList;
  23876. var staticAccessors = { coordArrayType: { configurable: true } };
  23877. staticAccessors.coordArrayType.get = function () { return new Array(0).fill(null) };
  23878. CoordinateList.prototype.getCoordinate = function getCoordinate (i) {
  23879. return this.get(i)
  23880. };
  23881. CoordinateList.prototype.addAll = function addAll () {
  23882. var this$1 = this;
  23883. if (arguments.length === 2) {
  23884. var coll = arguments[0];
  23885. var allowRepeated = arguments[1];
  23886. var isChanged = false;
  23887. for (var i = coll.iterator(); i.hasNext();) {
  23888. this$1.add(i.next(), allowRepeated);
  23889. isChanged = true;
  23890. }
  23891. return isChanged
  23892. } else { return ArrayList$$1.prototype.addAll.apply(this, arguments) }
  23893. };
  23894. CoordinateList.prototype.clone = function clone () {
  23895. var this$1 = this;
  23896. var clone = ArrayList$$1.prototype.clone.call(this);
  23897. for (var i = 0; i < this.size(); i++) {
  23898. clone.add(i, this$1.get(i).copy());
  23899. }
  23900. return clone
  23901. };
  23902. CoordinateList.prototype.toCoordinateArray = function toCoordinateArray () {
  23903. return this.toArray(CoordinateList.coordArrayType)
  23904. };
  23905. CoordinateList.prototype.add = function add () {
  23906. var this$1 = this;
  23907. if (arguments.length === 1) {
  23908. var coord = arguments[0];
  23909. ArrayList$$1.prototype.add.call(this, coord);
  23910. } else if (arguments.length === 2) {
  23911. if (arguments[0] instanceof Array && typeof arguments[1] === 'boolean') {
  23912. var coord$1 = arguments[0];
  23913. var allowRepeated = arguments[1];
  23914. this.add(coord$1, allowRepeated, true);
  23915. return true
  23916. } else if (arguments[0] instanceof Coordinate && typeof arguments[1] === 'boolean') {
  23917. var coord$2 = arguments[0];
  23918. var allowRepeated$1 = arguments[1];
  23919. if (!allowRepeated$1) {
  23920. if (this.size() >= 1) {
  23921. var last = this.get(this.size() - 1);
  23922. if (last.equals2D(coord$2)) { return null }
  23923. }
  23924. }
  23925. ArrayList$$1.prototype.add.call(this, coord$2);
  23926. } else if (arguments[0] instanceof Object && typeof arguments[1] === 'boolean') {
  23927. var obj = arguments[0];
  23928. var allowRepeated$2 = arguments[1];
  23929. this.add(obj, allowRepeated$2);
  23930. return true
  23931. }
  23932. } else if (arguments.length === 3) {
  23933. if (typeof arguments[2] === 'boolean' && (arguments[0] instanceof Array && typeof arguments[1] === 'boolean')) {
  23934. var coord$3 = arguments[0];
  23935. var allowRepeated$3 = arguments[1];
  23936. var direction = arguments[2];
  23937. if (direction) {
  23938. for (var i$1 = 0; i$1 < coord$3.length; i$1++) {
  23939. this$1.add(coord$3[i$1], allowRepeated$3);
  23940. }
  23941. } else {
  23942. for (var i$2 = coord$3.length - 1; i$2 >= 0; i$2--) {
  23943. this$1.add(coord$3[i$2], allowRepeated$3);
  23944. }
  23945. }
  23946. return true
  23947. } else if (typeof arguments[2] === 'boolean' && (Number.isInteger(arguments[0]) && arguments[1] instanceof Coordinate)) {
  23948. var i$3 = arguments[0];
  23949. var coord$4 = arguments[1];
  23950. var allowRepeated$4 = arguments[2];
  23951. if (!allowRepeated$4) {
  23952. var size = this.size();
  23953. if (size > 0) {
  23954. if (i$3 > 0) {
  23955. var prev = this.get(i$3 - 1);
  23956. if (prev.equals2D(coord$4)) { return null }
  23957. }
  23958. if (i$3 < size) {
  23959. var next = this.get(i$3);
  23960. if (next.equals2D(coord$4)) { return null }
  23961. }
  23962. }
  23963. }
  23964. ArrayList$$1.prototype.add.call(this, i$3, coord$4);
  23965. }
  23966. } else if (arguments.length === 4) {
  23967. var coord$5 = arguments[0];
  23968. var allowRepeated$5 = arguments[1];
  23969. var start = arguments[2];
  23970. var end = arguments[3];
  23971. var inc = 1;
  23972. if (start > end) { inc = -1; }
  23973. for (var i = start; i !== end; i += inc) {
  23974. this$1.add(coord$5[i], allowRepeated$5);
  23975. }
  23976. return true
  23977. }
  23978. };
  23979. CoordinateList.prototype.closeRing = function closeRing () {
  23980. if (this.size() > 0) { this.add(new Coordinate(this.get(0)), false); }
  23981. };
  23982. CoordinateList.prototype.interfaces_ = function interfaces_ () {
  23983. return []
  23984. };
  23985. CoordinateList.prototype.getClass = function getClass () {
  23986. return CoordinateList
  23987. };
  23988. Object.defineProperties( CoordinateList, staticAccessors );
  23989. return CoordinateList;
  23990. }(ArrayList));
  23991. var CoordinateArrays = function CoordinateArrays () {};
  23992. var staticAccessors$13 = { ForwardComparator: { configurable: true },BidirectionalComparator: { configurable: true },coordArrayType: { configurable: true } };
  23993. staticAccessors$13.ForwardComparator.get = function () { return ForwardComparator };
  23994. staticAccessors$13.BidirectionalComparator.get = function () { return BidirectionalComparator };
  23995. staticAccessors$13.coordArrayType.get = function () { return new Array(0).fill(null) };
  23996. CoordinateArrays.prototype.interfaces_ = function interfaces_ () {
  23997. return []
  23998. };
  23999. CoordinateArrays.prototype.getClass = function getClass () {
  24000. return CoordinateArrays
  24001. };
  24002. CoordinateArrays.isRing = function isRing (pts) {
  24003. if (pts.length < 4) { return false }
  24004. if (!pts[0].equals2D(pts[pts.length - 1])) { return false }
  24005. return true
  24006. };
  24007. CoordinateArrays.ptNotInList = function ptNotInList (testPts, pts) {
  24008. for (var i = 0; i < testPts.length; i++) {
  24009. var testPt = testPts[i];
  24010. if (CoordinateArrays.indexOf(testPt, pts) < 0) { return testPt }
  24011. }
  24012. return null
  24013. };
  24014. CoordinateArrays.scroll = function scroll (coordinates, firstCoordinate) {
  24015. var i = CoordinateArrays.indexOf(firstCoordinate, coordinates);
  24016. if (i < 0) { return null }
  24017. var newCoordinates = new Array(coordinates.length).fill(null);
  24018. System.arraycopy(coordinates, i, newCoordinates, 0, coordinates.length - i);
  24019. System.arraycopy(coordinates, 0, newCoordinates, coordinates.length - i, i);
  24020. System.arraycopy(newCoordinates, 0, coordinates, 0, coordinates.length);
  24021. };
  24022. CoordinateArrays.equals = function equals () {
  24023. if (arguments.length === 2) {
  24024. var coord1 = arguments[0];
  24025. var coord2 = arguments[1];
  24026. if (coord1 === coord2) { return true }
  24027. if (coord1 === null || coord2 === null) { return false }
  24028. if (coord1.length !== coord2.length) { return false }
  24029. for (var i = 0; i < coord1.length; i++) {
  24030. if (!coord1[i].equals(coord2[i])) { return false }
  24031. }
  24032. return true
  24033. } else if (arguments.length === 3) {
  24034. var coord1$1 = arguments[0];
  24035. var coord2$1 = arguments[1];
  24036. var coordinateComparator = arguments[2];
  24037. if (coord1$1 === coord2$1) { return true }
  24038. if (coord1$1 === null || coord2$1 === null) { return false }
  24039. if (coord1$1.length !== coord2$1.length) { return false }
  24040. for (var i$1 = 0; i$1 < coord1$1.length; i$1++) {
  24041. if (coordinateComparator.compare(coord1$1[i$1], coord2$1[i$1]) !== 0) { return false }
  24042. }
  24043. return true
  24044. }
  24045. };
  24046. CoordinateArrays.intersection = function intersection (coordinates, env) {
  24047. var coordList = new CoordinateList();
  24048. for (var i = 0; i < coordinates.length; i++) {
  24049. if (env.intersects(coordinates[i])) { coordList.add(coordinates[i], true); }
  24050. }
  24051. return coordList.toCoordinateArray()
  24052. };
  24053. CoordinateArrays.hasRepeatedPoints = function hasRepeatedPoints (coord) {
  24054. for (var i = 1; i < coord.length; i++) {
  24055. if (coord[i - 1].equals(coord[i])) {
  24056. return true
  24057. }
  24058. }
  24059. return false
  24060. };
  24061. CoordinateArrays.removeRepeatedPoints = function removeRepeatedPoints (coord) {
  24062. if (!CoordinateArrays.hasRepeatedPoints(coord)) { return coord }
  24063. var coordList = new CoordinateList(coord, false);
  24064. return coordList.toCoordinateArray()
  24065. };
  24066. CoordinateArrays.reverse = function reverse (coord) {
  24067. var last = coord.length - 1;
  24068. var mid = Math.trunc(last / 2);
  24069. for (var i = 0; i <= mid; i++) {
  24070. var tmp = coord[i];
  24071. coord[i] = coord[last - i];
  24072. coord[last - i] = tmp;
  24073. }
  24074. };
  24075. CoordinateArrays.removeNull = function removeNull (coord) {
  24076. var nonNull = 0;
  24077. for (var i = 0; i < coord.length; i++) {
  24078. if (coord[i] !== null) { nonNull++; }
  24079. }
  24080. var newCoord = new Array(nonNull).fill(null);
  24081. if (nonNull === 0) { return newCoord }
  24082. var j = 0;
  24083. for (var i$1 = 0; i$1 < coord.length; i$1++) {
  24084. if (coord[i$1] !== null) { newCoord[j++] = coord[i$1]; }
  24085. }
  24086. return newCoord
  24087. };
  24088. CoordinateArrays.copyDeep = function copyDeep () {
  24089. if (arguments.length === 1) {
  24090. var coordinates = arguments[0];
  24091. var copy = new Array(coordinates.length).fill(null);
  24092. for (var i = 0; i < coordinates.length; i++) {
  24093. copy[i] = new Coordinate(coordinates[i]);
  24094. }
  24095. return copy
  24096. } else if (arguments.length === 5) {
  24097. var src = arguments[0];
  24098. var srcStart = arguments[1];
  24099. var dest = arguments[2];
  24100. var destStart = arguments[3];
  24101. var length = arguments[4];
  24102. for (var i$1 = 0; i$1 < length; i$1++) {
  24103. dest[destStart + i$1] = new Coordinate(src[srcStart + i$1]);
  24104. }
  24105. }
  24106. };
  24107. CoordinateArrays.isEqualReversed = function isEqualReversed (pts1, pts2) {
  24108. for (var i = 0; i < pts1.length; i++) {
  24109. var p1 = pts1[i];
  24110. var p2 = pts2[pts1.length - i - 1];
  24111. if (p1.compareTo(p2) !== 0) { return false }
  24112. }
  24113. return true
  24114. };
  24115. CoordinateArrays.envelope = function envelope (coordinates) {
  24116. var env = new Envelope();
  24117. for (var i = 0; i < coordinates.length; i++) {
  24118. env.expandToInclude(coordinates[i]);
  24119. }
  24120. return env
  24121. };
  24122. CoordinateArrays.toCoordinateArray = function toCoordinateArray (coordList) {
  24123. return coordList.toArray(CoordinateArrays.coordArrayType)
  24124. };
  24125. CoordinateArrays.atLeastNCoordinatesOrNothing = function atLeastNCoordinatesOrNothing (n, c) {
  24126. return c.length >= n ? c : []
  24127. };
  24128. CoordinateArrays.indexOf = function indexOf (coordinate, coordinates) {
  24129. for (var i = 0; i < coordinates.length; i++) {
  24130. if (coordinate.equals(coordinates[i])) {
  24131. return i
  24132. }
  24133. }
  24134. return -1
  24135. };
  24136. CoordinateArrays.increasingDirection = function increasingDirection (pts) {
  24137. for (var i = 0; i < Math.trunc(pts.length / 2); i++) {
  24138. var j = pts.length - 1 - i;
  24139. var comp = pts[i].compareTo(pts[j]);
  24140. if (comp !== 0) { return comp }
  24141. }
  24142. return 1
  24143. };
  24144. CoordinateArrays.compare = function compare (pts1, pts2) {
  24145. var i = 0;
  24146. while (i < pts1.length && i < pts2.length) {
  24147. var compare = pts1[i].compareTo(pts2[i]);
  24148. if (compare !== 0) { return compare }
  24149. i++;
  24150. }
  24151. if (i < pts2.length) { return -1 }
  24152. if (i < pts1.length) { return 1 }
  24153. return 0
  24154. };
  24155. CoordinateArrays.minCoordinate = function minCoordinate (coordinates) {
  24156. var minCoord = null;
  24157. for (var i = 0; i < coordinates.length; i++) {
  24158. if (minCoord === null || minCoord.compareTo(coordinates[i]) > 0) {
  24159. minCoord = coordinates[i];
  24160. }
  24161. }
  24162. return minCoord
  24163. };
  24164. CoordinateArrays.extract = function extract (pts, start, end) {
  24165. start = MathUtil.clamp(start, 0, pts.length);
  24166. end = MathUtil.clamp(end, -1, pts.length);
  24167. var npts = end - start + 1;
  24168. if (end < 0) { npts = 0; }
  24169. if (start >= pts.length) { npts = 0; }
  24170. if (end < start) { npts = 0; }
  24171. var extractPts = new Array(npts).fill(null);
  24172. if (npts === 0) { return extractPts }
  24173. var iPts = 0;
  24174. for (var i = start; i <= end; i++) {
  24175. extractPts[iPts++] = pts[i];
  24176. }
  24177. return extractPts
  24178. };
  24179. Object.defineProperties( CoordinateArrays, staticAccessors$13 );
  24180. var ForwardComparator = function ForwardComparator () {};
  24181. ForwardComparator.prototype.compare = function compare (o1, o2) {
  24182. var pts1 = o1;
  24183. var pts2 = o2;
  24184. return CoordinateArrays.compare(pts1, pts2)
  24185. };
  24186. ForwardComparator.prototype.interfaces_ = function interfaces_ () {
  24187. return [Comparator]
  24188. };
  24189. ForwardComparator.prototype.getClass = function getClass () {
  24190. return ForwardComparator
  24191. };
  24192. var BidirectionalComparator = function BidirectionalComparator () {};
  24193. BidirectionalComparator.prototype.compare = function compare (o1, o2) {
  24194. var pts1 = o1;
  24195. var pts2 = o2;
  24196. if (pts1.length < pts2.length) { return -1 }
  24197. if (pts1.length > pts2.length) { return 1 }
  24198. if (pts1.length === 0) { return 0 }
  24199. var forwardComp = CoordinateArrays.compare(pts1, pts2);
  24200. var isEqualRev = CoordinateArrays.isEqualReversed(pts1, pts2);
  24201. if (isEqualRev) { return 0 }
  24202. return forwardComp
  24203. };
  24204. BidirectionalComparator.prototype.OLDcompare = function OLDcompare (o1, o2) {
  24205. var pts1 = o1;
  24206. var pts2 = o2;
  24207. if (pts1.length < pts2.length) { return -1 }
  24208. if (pts1.length > pts2.length) { return 1 }
  24209. if (pts1.length === 0) { return 0 }
  24210. var dir1 = CoordinateArrays.increasingDirection(pts1);
  24211. var dir2 = CoordinateArrays.increasingDirection(pts2);
  24212. var i1 = dir1 > 0 ? 0 : pts1.length - 1;
  24213. var i2 = dir2 > 0 ? 0 : pts1.length - 1;
  24214. for (var i = 0; i < pts1.length; i++) {
  24215. var comparePt = pts1[i1].compareTo(pts2[i2]);
  24216. if (comparePt !== 0) { return comparePt }
  24217. i1 += dir1;
  24218. i2 += dir2;
  24219. }
  24220. return 0
  24221. };
  24222. BidirectionalComparator.prototype.interfaces_ = function interfaces_ () {
  24223. return [Comparator]
  24224. };
  24225. BidirectionalComparator.prototype.getClass = function getClass () {
  24226. return BidirectionalComparator
  24227. };
  24228. /**
  24229. * @see http://download.oracle.com/javase/6/docs/api/java/util/Map.html
  24230. *
  24231. * @constructor
  24232. * @private
  24233. */
  24234. var Map$1 = function Map () {};
  24235. Map$1.prototype.get = function get () {};
  24236. /**
  24237. * Associates the specified value with the specified key in this map (optional
  24238. * operation).
  24239. * @param {Object} key
  24240. * @param {Object} value
  24241. * @return {Object}
  24242. */
  24243. Map$1.prototype.put = function put () {};
  24244. /**
  24245. * Returns the number of key-value mappings in this map.
  24246. * @return {number}
  24247. */
  24248. Map$1.prototype.size = function size () {};
  24249. /**
  24250. * Returns a Collection view of the values contained in this map.
  24251. * @return {javascript.util.Collection}
  24252. */
  24253. Map$1.prototype.values = function values () {};
  24254. /**
  24255. * Returns a {@link Set} view of the mappings contained in this map.
  24256. * The set is backed by the map, so changes to the map are
  24257. * reflected in the set, and vice-versa.If the map is modified
  24258. * while an iteration over the set is in progress (except through
  24259. * the iterator's own <tt>remove</tt> operation, or through the
  24260. * <tt>setValue</tt> operation on a map entry returned by the
  24261. * iterator) the results of the iteration are undefined.The set
  24262. * supports element removal, which removes the corresponding
  24263. * mapping from the map, via the <tt>Iterator.remove</tt>,
  24264. * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
  24265. * <tt>clear</tt> operations.It does not support the
  24266. * <tt>add</tt> or <tt>addAll</tt> operations.
  24267. *
  24268. * @return {Set} a set view of the mappings contained in this map
  24269. */
  24270. Map$1.prototype.entrySet = function entrySet () {};
  24271. /**
  24272. * @see http://download.oracle.com/javase/6/docs/api/java/util/SortedMap.html
  24273. *
  24274. * @extends {Map}
  24275. * @constructor
  24276. * @private
  24277. */
  24278. var SortedMap = (function (Map) {
  24279. function SortedMap () {
  24280. Map.apply(this, arguments);
  24281. }if ( Map ) SortedMap.__proto__ = Map;
  24282. SortedMap.prototype = Object.create( Map && Map.prototype );
  24283. SortedMap.prototype.constructor = SortedMap;
  24284. return SortedMap;
  24285. }(Map$1));
  24286. /**
  24287. * @param {string=} message Optional message
  24288. * @extends {Error}
  24289. * @constructor
  24290. * @private
  24291. */
  24292. function OperationNotSupported (message) {
  24293. this.message = message || '';
  24294. }
  24295. OperationNotSupported.prototype = new Error();
  24296. /**
  24297. * @type {string}
  24298. */
  24299. OperationNotSupported.prototype.name = 'OperationNotSupported';
  24300. /**
  24301. * @see http://download.oracle.com/javase/6/docs/api/java/util/Set.html
  24302. *
  24303. * @extends {Collection}
  24304. * @constructor
  24305. * @private
  24306. */
  24307. function Set() {}
  24308. Set.prototype = new Collection();
  24309. /**
  24310. * Returns true if this set contains the specified element. More formally,
  24311. * returns true if and only if this set contains an element e such that (o==null ?
  24312. * e==null : o.equals(e)).
  24313. * @param {Object} e
  24314. * @return {boolean}
  24315. */
  24316. Set.prototype.contains = function() {};
  24317. /**
  24318. * @see http://docs.oracle.com/javase/6/docs/api/java/util/HashSet.html
  24319. *
  24320. * @extends {javascript.util.Set}
  24321. * @constructor
  24322. * @private
  24323. */
  24324. var HashSet = (function (Set$$1) {
  24325. function HashSet () {
  24326. Set$$1.call(this);
  24327. this.array_ = [];
  24328. if (arguments[0] instanceof Collection) {
  24329. this.addAll(arguments[0]);
  24330. }
  24331. }
  24332. if ( Set$$1 ) HashSet.__proto__ = Set$$1;
  24333. HashSet.prototype = Object.create( Set$$1 && Set$$1.prototype );
  24334. HashSet.prototype.constructor = HashSet;
  24335. /**
  24336. * @override
  24337. */
  24338. HashSet.prototype.contains = function contains (o) {
  24339. var this$1 = this;
  24340. for (var i = 0, len = this.array_.length; i < len; i++) {
  24341. var e = this$1.array_[i];
  24342. if (e === o) {
  24343. return true
  24344. }
  24345. }
  24346. return false
  24347. };
  24348. /**
  24349. * @override
  24350. */
  24351. HashSet.prototype.add = function add (o) {
  24352. if (this.contains(o)) {
  24353. return false
  24354. }
  24355. this.array_.push(o);
  24356. return true
  24357. };
  24358. /**
  24359. * @override
  24360. */
  24361. HashSet.prototype.addAll = function addAll (c) {
  24362. var this$1 = this;
  24363. for (var i = c.iterator(); i.hasNext();) {
  24364. this$1.add(i.next());
  24365. }
  24366. return true
  24367. };
  24368. /**
  24369. * @override
  24370. */
  24371. HashSet.prototype.remove = function remove (o) {
  24372. // throw new javascript.util.OperationNotSupported()
  24373. throw new Error()
  24374. };
  24375. /**
  24376. * @override
  24377. */
  24378. HashSet.prototype.size = function size () {
  24379. return this.array_.length
  24380. };
  24381. /**
  24382. * @override
  24383. */
  24384. HashSet.prototype.isEmpty = function isEmpty () {
  24385. return this.array_.length === 0
  24386. };
  24387. /**
  24388. * @override
  24389. */
  24390. HashSet.prototype.toArray = function toArray () {
  24391. var this$1 = this;
  24392. var array = [];
  24393. for (var i = 0, len = this.array_.length; i < len; i++) {
  24394. array.push(this$1.array_[i]);
  24395. }
  24396. return array
  24397. };
  24398. /**
  24399. * @override
  24400. */
  24401. HashSet.prototype.iterator = function iterator () {
  24402. return new Iterator_$1(this)
  24403. };
  24404. return HashSet;
  24405. }(Set));
  24406. /**
  24407. * @extends {Iterator}
  24408. * @param {HashSet} hashSet
  24409. * @constructor
  24410. * @private
  24411. */
  24412. var Iterator_$1 = (function (Iterator$$1) {
  24413. function Iterator_ (hashSet) {
  24414. Iterator$$1.call(this);
  24415. /**
  24416. * @type {HashSet}
  24417. * @private
  24418. */
  24419. this.hashSet_ = hashSet;
  24420. /**
  24421. * @type {number}
  24422. * @private
  24423. */
  24424. this.position_ = 0;
  24425. }
  24426. if ( Iterator$$1 ) Iterator_.__proto__ = Iterator$$1;
  24427. Iterator_.prototype = Object.create( Iterator$$1 && Iterator$$1.prototype );
  24428. Iterator_.prototype.constructor = Iterator_;
  24429. /**
  24430. * @override
  24431. */
  24432. Iterator_.prototype.next = function next () {
  24433. if (this.position_ === this.hashSet_.size()) {
  24434. throw new NoSuchElementException()
  24435. }
  24436. return this.hashSet_.array_[this.position_++]
  24437. };
  24438. /**
  24439. * @override
  24440. */
  24441. Iterator_.prototype.hasNext = function hasNext () {
  24442. if (this.position_ < this.hashSet_.size()) {
  24443. return true
  24444. } else {
  24445. return false
  24446. }
  24447. };
  24448. /**
  24449. * @override
  24450. */
  24451. Iterator_.prototype.remove = function remove () {
  24452. throw new OperationNotSupported()
  24453. };
  24454. return Iterator_;
  24455. }(Iterator));
  24456. var BLACK = 0;
  24457. var RED = 1;
  24458. function colorOf (p) { return (p === null ? BLACK : p.color) }
  24459. function parentOf (p) { return (p === null ? null : p.parent) }
  24460. function setColor (p, c) { if (p !== null) { p.color = c; } }
  24461. function leftOf (p) { return (p === null ? null : p.left) }
  24462. function rightOf (p) { return (p === null ? null : p.right) }
  24463. /**
  24464. * @see http://download.oracle.com/javase/6/docs/api/java/util/TreeMap.html
  24465. *
  24466. * @extends {SortedMap}
  24467. * @constructor
  24468. * @private
  24469. */
  24470. function TreeMap () {
  24471. /**
  24472. * @type {Object}
  24473. * @private
  24474. */
  24475. this.root_ = null;
  24476. /**
  24477. * @type {number}
  24478. * @private
  24479. */
  24480. this.size_ = 0;
  24481. }
  24482. TreeMap.prototype = new SortedMap();
  24483. /**
  24484. * @override
  24485. */
  24486. TreeMap.prototype.get = function (key) {
  24487. var p = this.root_;
  24488. while (p !== null) {
  24489. var cmp = key['compareTo'](p.key);
  24490. if (cmp < 0) { p = p.left; }
  24491. else if (cmp > 0) { p = p.right; }
  24492. else { return p.value }
  24493. }
  24494. return null
  24495. };
  24496. /**
  24497. * @override
  24498. */
  24499. TreeMap.prototype.put = function (key, value) {
  24500. if (this.root_ === null) {
  24501. this.root_ = {
  24502. key: key,
  24503. value: value,
  24504. left: null,
  24505. right: null,
  24506. parent: null,
  24507. color: BLACK,
  24508. getValue: function getValue () { return this.value },
  24509. getKey: function getKey () { return this.key }
  24510. };
  24511. this.size_ = 1;
  24512. return null
  24513. }
  24514. var t = this.root_;
  24515. var parent;
  24516. var cmp;
  24517. do {
  24518. parent = t;
  24519. cmp = key['compareTo'](t.key);
  24520. if (cmp < 0) {
  24521. t = t.left;
  24522. } else if (cmp > 0) {
  24523. t = t.right;
  24524. } else {
  24525. var oldValue = t.value;
  24526. t.value = value;
  24527. return oldValue
  24528. }
  24529. } while (t !== null)
  24530. var e = {
  24531. key: key,
  24532. left: null,
  24533. right: null,
  24534. value: value,
  24535. parent: parent,
  24536. color: BLACK,
  24537. getValue: function getValue () { return this.value },
  24538. getKey: function getKey () { return this.key }
  24539. };
  24540. if (cmp < 0) {
  24541. parent.left = e;
  24542. } else {
  24543. parent.right = e;
  24544. }
  24545. this.fixAfterInsertion(e);
  24546. this.size_++;
  24547. return null
  24548. };
  24549. /**
  24550. * @param {Object} x
  24551. */
  24552. TreeMap.prototype.fixAfterInsertion = function (x) {
  24553. var this$1 = this;
  24554. x.color = RED;
  24555. while (x != null && x !== this.root_ && x.parent.color === RED) {
  24556. if (parentOf(x) === leftOf(parentOf(parentOf(x)))) {
  24557. var y = rightOf(parentOf(parentOf(x)));
  24558. if (colorOf(y) === RED) {
  24559. setColor(parentOf(x), BLACK);
  24560. setColor(y, BLACK);
  24561. setColor(parentOf(parentOf(x)), RED);
  24562. x = parentOf(parentOf(x));
  24563. } else {
  24564. if (x === rightOf(parentOf(x))) {
  24565. x = parentOf(x);
  24566. this$1.rotateLeft(x);
  24567. }
  24568. setColor(parentOf(x), BLACK);
  24569. setColor(parentOf(parentOf(x)), RED);
  24570. this$1.rotateRight(parentOf(parentOf(x)));
  24571. }
  24572. } else {
  24573. var y$1 = leftOf(parentOf(parentOf(x)));
  24574. if (colorOf(y$1) === RED) {
  24575. setColor(parentOf(x), BLACK);
  24576. setColor(y$1, BLACK);
  24577. setColor(parentOf(parentOf(x)), RED);
  24578. x = parentOf(parentOf(x));
  24579. } else {
  24580. if (x === leftOf(parentOf(x))) {
  24581. x = parentOf(x);
  24582. this$1.rotateRight(x);
  24583. }
  24584. setColor(parentOf(x), BLACK);
  24585. setColor(parentOf(parentOf(x)), RED);
  24586. this$1.rotateLeft(parentOf(parentOf(x)));
  24587. }
  24588. }
  24589. }
  24590. this.root_.color = BLACK;
  24591. };
  24592. /**
  24593. * @override
  24594. */
  24595. TreeMap.prototype.values = function () {
  24596. var arrayList = new ArrayList();
  24597. var p = this.getFirstEntry();
  24598. if (p !== null) {
  24599. arrayList.add(p.value);
  24600. while ((p = TreeMap.successor(p)) !== null) {
  24601. arrayList.add(p.value);
  24602. }
  24603. }
  24604. return arrayList
  24605. };
  24606. /**
  24607. * @override
  24608. */
  24609. TreeMap.prototype.entrySet = function () {
  24610. var hashSet = new HashSet();
  24611. var p = this.getFirstEntry();
  24612. if (p !== null) {
  24613. hashSet.add(p);
  24614. while ((p = TreeMap.successor(p)) !== null) {
  24615. hashSet.add(p);
  24616. }
  24617. }
  24618. return hashSet
  24619. };
  24620. /**
  24621. * @param {Object} p
  24622. */
  24623. TreeMap.prototype.rotateLeft = function (p) {
  24624. if (p != null) {
  24625. var r = p.right;
  24626. p.right = r.left;
  24627. if (r.left != null) { r.left.parent = p; }
  24628. r.parent = p.parent;
  24629. if (p.parent === null) { this.root_ = r; } else if (p.parent.left === p) { p.parent.left = r; } else { p.parent.right = r; }
  24630. r.left = p;
  24631. p.parent = r;
  24632. }
  24633. };
  24634. /**
  24635. * @param {Object} p
  24636. */
  24637. TreeMap.prototype.rotateRight = function (p) {
  24638. if (p != null) {
  24639. var l = p.left;
  24640. p.left = l.right;
  24641. if (l.right != null) { l.right.parent = p; }
  24642. l.parent = p.parent;
  24643. if (p.parent === null) { this.root_ = l; } else if (p.parent.right === p) { p.parent.right = l; } else { p.parent.left = l; }
  24644. l.right = p;
  24645. p.parent = l;
  24646. }
  24647. };
  24648. /**
  24649. * @return {Object}
  24650. */
  24651. TreeMap.prototype.getFirstEntry = function () {
  24652. var p = this.root_;
  24653. if (p != null) {
  24654. while (p.left != null) {
  24655. p = p.left;
  24656. }
  24657. }
  24658. return p
  24659. };
  24660. /**
  24661. * @param {Object} t
  24662. * @return {Object}
  24663. * @private
  24664. */
  24665. TreeMap.successor = function (t) {
  24666. if (t === null) { return null } else if (t.right !== null) {
  24667. var p = t.right;
  24668. while (p.left !== null) {
  24669. p = p.left;
  24670. }
  24671. return p
  24672. } else {
  24673. var p$1 = t.parent;
  24674. var ch = t;
  24675. while (p$1 !== null && ch === p$1.right) {
  24676. ch = p$1;
  24677. p$1 = p$1.parent;
  24678. }
  24679. return p$1
  24680. }
  24681. };
  24682. /**
  24683. * @override
  24684. */
  24685. TreeMap.prototype.size = function () {
  24686. return this.size_
  24687. };
  24688. var Lineal = function Lineal () {};
  24689. Lineal.prototype.interfaces_ = function interfaces_ () {
  24690. return []
  24691. };
  24692. Lineal.prototype.getClass = function getClass () {
  24693. return Lineal
  24694. };
  24695. /**
  24696. * @see http://download.oracle.com/javase/6/docs/api/java/util/SortedSet.html
  24697. *
  24698. * @extends {Set}
  24699. * @constructor
  24700. * @private
  24701. */
  24702. function SortedSet () {}
  24703. SortedSet.prototype = new Set();
  24704. // import Iterator from './Iterator'
  24705. /**
  24706. * @see http://download.oracle.com/javase/6/docs/api/java/util/TreeSet.html
  24707. *
  24708. * @extends {SortedSet}
  24709. * @constructor
  24710. * @private
  24711. */
  24712. function TreeSet () {
  24713. /**
  24714. * @type {Array}
  24715. * @private
  24716. */
  24717. this.array_ = [];
  24718. if (arguments[0] instanceof Collection) {
  24719. this.addAll(arguments[0]);
  24720. }
  24721. }
  24722. TreeSet.prototype = new SortedSet();
  24723. /**
  24724. * @override
  24725. */
  24726. TreeSet.prototype.contains = function (o) {
  24727. var this$1 = this;
  24728. for (var i = 0, len = this.array_.length; i < len; i++) {
  24729. var e = this$1.array_[i];
  24730. if (e['compareTo'](o) === 0) {
  24731. return true
  24732. }
  24733. }
  24734. return false
  24735. };
  24736. /**
  24737. * @override
  24738. */
  24739. TreeSet.prototype.add = function (o) {
  24740. var this$1 = this;
  24741. if (this.contains(o)) {
  24742. return false
  24743. }
  24744. for (var i = 0, len = this.array_.length; i < len; i++) {
  24745. var e = this$1.array_[i];
  24746. if (e['compareTo'](o) === 1) {
  24747. this$1.array_.splice(i, 0, o);
  24748. return true
  24749. }
  24750. }
  24751. this.array_.push(o);
  24752. return true
  24753. };
  24754. /**
  24755. * @override
  24756. */
  24757. TreeSet.prototype.addAll = function (c) {
  24758. var this$1 = this;
  24759. for (var i = c.iterator(); i.hasNext();) {
  24760. this$1.add(i.next());
  24761. }
  24762. return true
  24763. };
  24764. /**
  24765. * @override
  24766. */
  24767. TreeSet.prototype.remove = function (e) {
  24768. throw new OperationNotSupported()
  24769. };
  24770. /**
  24771. * @override
  24772. */
  24773. TreeSet.prototype.size = function () {
  24774. return this.array_.length
  24775. };
  24776. /**
  24777. * @override
  24778. */
  24779. TreeSet.prototype.isEmpty = function () {
  24780. return this.array_.length === 0
  24781. };
  24782. /**
  24783. * @override
  24784. */
  24785. TreeSet.prototype.toArray = function () {
  24786. var this$1 = this;
  24787. var array = [];
  24788. for (var i = 0, len = this.array_.length; i < len; i++) {
  24789. array.push(this$1.array_[i]);
  24790. }
  24791. return array
  24792. };
  24793. /**
  24794. * @override
  24795. */
  24796. TreeSet.prototype.iterator = function () {
  24797. return new Iterator_$2(this)
  24798. };
  24799. /**
  24800. * @extends {javascript.util.Iterator}
  24801. * @param {javascript.util.TreeSet} treeSet
  24802. * @constructor
  24803. * @private
  24804. */
  24805. var Iterator_$2 = function (treeSet) {
  24806. /**
  24807. * @type {javascript.util.TreeSet}
  24808. * @private
  24809. */
  24810. this.treeSet_ = treeSet;
  24811. /**
  24812. * @type {number}
  24813. * @private
  24814. */
  24815. this.position_ = 0;
  24816. };
  24817. /**
  24818. * @override
  24819. */
  24820. Iterator_$2.prototype.next = function () {
  24821. if (this.position_ === this.treeSet_.size()) {
  24822. throw new NoSuchElementException()
  24823. }
  24824. return this.treeSet_.array_[this.position_++]
  24825. };
  24826. /**
  24827. * @override
  24828. */
  24829. Iterator_$2.prototype.hasNext = function () {
  24830. if (this.position_ < this.treeSet_.size()) {
  24831. return true
  24832. } else {
  24833. return false
  24834. }
  24835. };
  24836. /**
  24837. * @override
  24838. */
  24839. Iterator_$2.prototype.remove = function () {
  24840. throw new OperationNotSupported()
  24841. };
  24842. /**
  24843. * @see http://download.oracle.com/javase/6/docs/api/java/util/Arrays.html
  24844. *
  24845. * @constructor
  24846. * @private
  24847. */
  24848. var Arrays = function Arrays () {};
  24849. Arrays.sort = function sort () {
  24850. var a = arguments[0];
  24851. var i;
  24852. var t;
  24853. var comparator;
  24854. var compare;
  24855. if (arguments.length === 1) {
  24856. compare = function (a, b) {
  24857. return a.compareTo(b)
  24858. };
  24859. a.sort(compare);
  24860. } else if (arguments.length === 2) {
  24861. comparator = arguments[1];
  24862. compare = function (a, b) {
  24863. return comparator['compare'](a, b)
  24864. };
  24865. a.sort(compare);
  24866. } else if (arguments.length === 3) {
  24867. t = a.slice(arguments[1], arguments[2]);
  24868. t.sort();
  24869. var r = a.slice(0, arguments[1]).concat(t, a.slice(arguments[2], a.length));
  24870. a.splice(0, a.length);
  24871. for (i = 0; i < r.length; i++) {
  24872. a.push(r[i]);
  24873. }
  24874. } else if (arguments.length === 4) {
  24875. t = a.slice(arguments[1], arguments[2]);
  24876. comparator = arguments[3];
  24877. compare = function (a, b) {
  24878. return comparator['compare'](a, b)
  24879. };
  24880. t.sort(compare);
  24881. r = a.slice(0, arguments[1]).concat(t, a.slice(arguments[2], a.length));
  24882. a.splice(0, a.length);
  24883. for (i = 0; i < r.length; i++) {
  24884. a.push(r[i]);
  24885. }
  24886. }
  24887. };
  24888. /**
  24889. * @param {Array} array
  24890. * @return {ArrayList}
  24891. */
  24892. Arrays.asList = function asList (array) {
  24893. var arrayList = new ArrayList();
  24894. for (var i = 0, len = array.length; i < len; i++) {
  24895. arrayList.add(array[i]);
  24896. }
  24897. return arrayList
  24898. };
  24899. var Dimension = function Dimension () {};
  24900. var staticAccessors$14 = { P: { configurable: true },L: { configurable: true },A: { configurable: true },FALSE: { configurable: true },TRUE: { configurable: true },DONTCARE: { configurable: true },SYM_FALSE: { configurable: true },SYM_TRUE: { configurable: true },SYM_DONTCARE: { configurable: true },SYM_P: { configurable: true },SYM_L: { configurable: true },SYM_A: { configurable: true } };
  24901. staticAccessors$14.P.get = function () { return 0 };
  24902. staticAccessors$14.L.get = function () { return 1 };
  24903. staticAccessors$14.A.get = function () { return 2 };
  24904. staticAccessors$14.FALSE.get = function () { return -1 };
  24905. staticAccessors$14.TRUE.get = function () { return -2 };
  24906. staticAccessors$14.DONTCARE.get = function () { return -3 };
  24907. staticAccessors$14.SYM_FALSE.get = function () { return 'F' };
  24908. staticAccessors$14.SYM_TRUE.get = function () { return 'T' };
  24909. staticAccessors$14.SYM_DONTCARE.get = function () { return '*' };
  24910. staticAccessors$14.SYM_P.get = function () { return '0' };
  24911. staticAccessors$14.SYM_L.get = function () { return '1' };
  24912. staticAccessors$14.SYM_A.get = function () { return '2' };
  24913. Dimension.prototype.interfaces_ = function interfaces_ () {
  24914. return []
  24915. };
  24916. Dimension.prototype.getClass = function getClass () {
  24917. return Dimension
  24918. };
  24919. Dimension.toDimensionSymbol = function toDimensionSymbol (dimensionValue) {
  24920. switch (dimensionValue) {
  24921. case Dimension.FALSE:
  24922. return Dimension.SYM_FALSE
  24923. case Dimension.TRUE:
  24924. return Dimension.SYM_TRUE
  24925. case Dimension.DONTCARE:
  24926. return Dimension.SYM_DONTCARE
  24927. case Dimension.P:
  24928. return Dimension.SYM_P
  24929. case Dimension.L:
  24930. return Dimension.SYM_L
  24931. case Dimension.A:
  24932. return Dimension.SYM_A
  24933. default:
  24934. }
  24935. throw new IllegalArgumentException('Unknown dimension value: ' + dimensionValue)
  24936. };
  24937. Dimension.toDimensionValue = function toDimensionValue (dimensionSymbol) {
  24938. switch (Character.toUpperCase(dimensionSymbol)) {
  24939. case Dimension.SYM_FALSE:
  24940. return Dimension.FALSE
  24941. case Dimension.SYM_TRUE:
  24942. return Dimension.TRUE
  24943. case Dimension.SYM_DONTCARE:
  24944. return Dimension.DONTCARE
  24945. case Dimension.SYM_P:
  24946. return Dimension.P
  24947. case Dimension.SYM_L:
  24948. return Dimension.L
  24949. case Dimension.SYM_A:
  24950. return Dimension.A
  24951. default:
  24952. }
  24953. throw new IllegalArgumentException('Unknown dimension symbol: ' + dimensionSymbol)
  24954. };
  24955. Object.defineProperties( Dimension, staticAccessors$14 );
  24956. var GeometryFilter = function GeometryFilter () {};
  24957. GeometryFilter.prototype.filter = function filter (geom) {};
  24958. GeometryFilter.prototype.interfaces_ = function interfaces_ () {
  24959. return []
  24960. };
  24961. GeometryFilter.prototype.getClass = function getClass () {
  24962. return GeometryFilter
  24963. };
  24964. var CoordinateSequenceFilter = function CoordinateSequenceFilter () {};
  24965. CoordinateSequenceFilter.prototype.filter = function filter (seq, i) {};
  24966. CoordinateSequenceFilter.prototype.isDone = function isDone () {};
  24967. CoordinateSequenceFilter.prototype.isGeometryChanged = function isGeometryChanged () {};
  24968. CoordinateSequenceFilter.prototype.interfaces_ = function interfaces_ () {
  24969. return []
  24970. };
  24971. CoordinateSequenceFilter.prototype.getClass = function getClass () {
  24972. return CoordinateSequenceFilter
  24973. };
  24974. var GeometryCollection = (function (Geometry$$1) {
  24975. function GeometryCollection (geometries, factory) {
  24976. Geometry$$1.call(this, factory);
  24977. this._geometries = geometries || [];
  24978. if (Geometry$$1.hasNullElements(this._geometries)) {
  24979. throw new IllegalArgumentException('geometries must not contain null elements')
  24980. }
  24981. }
  24982. if ( Geometry$$1 ) GeometryCollection.__proto__ = Geometry$$1;
  24983. GeometryCollection.prototype = Object.create( Geometry$$1 && Geometry$$1.prototype );
  24984. GeometryCollection.prototype.constructor = GeometryCollection;
  24985. var staticAccessors = { serialVersionUID: { configurable: true } };
  24986. GeometryCollection.prototype.computeEnvelopeInternal = function computeEnvelopeInternal () {
  24987. var this$1 = this;
  24988. var envelope = new Envelope();
  24989. for (var i = 0; i < this._geometries.length; i++) {
  24990. envelope.expandToInclude(this$1._geometries[i].getEnvelopeInternal());
  24991. }
  24992. return envelope
  24993. };
  24994. GeometryCollection.prototype.getGeometryN = function getGeometryN (n) {
  24995. return this._geometries[n]
  24996. };
  24997. GeometryCollection.prototype.getSortIndex = function getSortIndex () {
  24998. return Geometry$$1.SORTINDEX_GEOMETRYCOLLECTION
  24999. };
  25000. GeometryCollection.prototype.getCoordinates = function getCoordinates () {
  25001. var this$1 = this;
  25002. var coordinates = new Array(this.getNumPoints()).fill(null);
  25003. var k = -1;
  25004. for (var i = 0; i < this._geometries.length; i++) {
  25005. var childCoordinates = this$1._geometries[i].getCoordinates();
  25006. for (var j = 0; j < childCoordinates.length; j++) {
  25007. k++;
  25008. coordinates[k] = childCoordinates[j];
  25009. }
  25010. }
  25011. return coordinates
  25012. };
  25013. GeometryCollection.prototype.getArea = function getArea () {
  25014. var this$1 = this;
  25015. var area = 0.0;
  25016. for (var i = 0; i < this._geometries.length; i++) {
  25017. area += this$1._geometries[i].getArea();
  25018. }
  25019. return area
  25020. };
  25021. GeometryCollection.prototype.equalsExact = function equalsExact () {
  25022. var this$1 = this;
  25023. if (arguments.length === 2) {
  25024. var other = arguments[0];
  25025. var tolerance = arguments[1];
  25026. if (!this.isEquivalentClass(other)) {
  25027. return false
  25028. }
  25029. var otherCollection = other;
  25030. if (this._geometries.length !== otherCollection._geometries.length) {
  25031. return false
  25032. }
  25033. for (var i = 0; i < this._geometries.length; i++) {
  25034. if (!this$1._geometries[i].equalsExact(otherCollection._geometries[i], tolerance)) {
  25035. return false
  25036. }
  25037. }
  25038. return true
  25039. } else { return Geometry$$1.prototype.equalsExact.apply(this, arguments) }
  25040. };
  25041. GeometryCollection.prototype.normalize = function normalize () {
  25042. var this$1 = this;
  25043. for (var i = 0; i < this._geometries.length; i++) {
  25044. this$1._geometries[i].normalize();
  25045. }
  25046. Arrays.sort(this._geometries);
  25047. };
  25048. GeometryCollection.prototype.getCoordinate = function getCoordinate () {
  25049. if (this.isEmpty()) { return null }
  25050. return this._geometries[0].getCoordinate()
  25051. };
  25052. GeometryCollection.prototype.getBoundaryDimension = function getBoundaryDimension () {
  25053. var this$1 = this;
  25054. var dimension = Dimension.FALSE;
  25055. for (var i = 0; i < this._geometries.length; i++) {
  25056. dimension = Math.max(dimension, this$1._geometries[i].getBoundaryDimension());
  25057. }
  25058. return dimension
  25059. };
  25060. GeometryCollection.prototype.getDimension = function getDimension () {
  25061. var this$1 = this;
  25062. var dimension = Dimension.FALSE;
  25063. for (var i = 0; i < this._geometries.length; i++) {
  25064. dimension = Math.max(dimension, this$1._geometries[i].getDimension());
  25065. }
  25066. return dimension
  25067. };
  25068. GeometryCollection.prototype.getLength = function getLength () {
  25069. var this$1 = this;
  25070. var sum = 0.0;
  25071. for (var i = 0; i < this._geometries.length; i++) {
  25072. sum += this$1._geometries[i].getLength();
  25073. }
  25074. return sum
  25075. };
  25076. GeometryCollection.prototype.getNumPoints = function getNumPoints () {
  25077. var this$1 = this;
  25078. var numPoints = 0;
  25079. for (var i = 0; i < this._geometries.length; i++) {
  25080. numPoints += this$1._geometries[i].getNumPoints();
  25081. }
  25082. return numPoints
  25083. };
  25084. GeometryCollection.prototype.getNumGeometries = function getNumGeometries () {
  25085. return this._geometries.length
  25086. };
  25087. GeometryCollection.prototype.reverse = function reverse () {
  25088. var this$1 = this;
  25089. var n = this._geometries.length;
  25090. var revGeoms = new Array(n).fill(null);
  25091. for (var i = 0; i < this._geometries.length; i++) {
  25092. revGeoms[i] = this$1._geometries[i].reverse();
  25093. }
  25094. return this.getFactory().createGeometryCollection(revGeoms)
  25095. };
  25096. GeometryCollection.prototype.compareToSameClass = function compareToSameClass () {
  25097. var this$1 = this;
  25098. if (arguments.length === 1) {
  25099. var o = arguments[0];
  25100. var theseElements = new TreeSet(Arrays.asList(this._geometries));
  25101. var otherElements = new TreeSet(Arrays.asList(o._geometries));
  25102. return this.compare(theseElements, otherElements)
  25103. } else if (arguments.length === 2) {
  25104. var o$1 = arguments[0];
  25105. var comp = arguments[1];
  25106. var gc = o$1;
  25107. var n1 = this.getNumGeometries();
  25108. var n2 = gc.getNumGeometries();
  25109. var i = 0;
  25110. while (i < n1 && i < n2) {
  25111. var thisGeom = this$1.getGeometryN(i);
  25112. var otherGeom = gc.getGeometryN(i);
  25113. var holeComp = thisGeom.compareToSameClass(otherGeom, comp);
  25114. if (holeComp !== 0) { return holeComp }
  25115. i++;
  25116. }
  25117. if (i < n1) { return 1 }
  25118. if (i < n2) { return -1 }
  25119. return 0
  25120. }
  25121. };
  25122. GeometryCollection.prototype.apply = function apply () {
  25123. var this$1 = this;
  25124. if (hasInterface(arguments[0], CoordinateFilter)) {
  25125. var filter = arguments[0];
  25126. for (var i = 0; i < this._geometries.length; i++) {
  25127. this$1._geometries[i].apply(filter);
  25128. }
  25129. } else if (hasInterface(arguments[0], CoordinateSequenceFilter)) {
  25130. var filter$1 = arguments[0];
  25131. if (this._geometries.length === 0) { return null }
  25132. for (var i$1 = 0; i$1 < this._geometries.length; i$1++) {
  25133. this$1._geometries[i$1].apply(filter$1);
  25134. if (filter$1.isDone()) {
  25135. break
  25136. }
  25137. }
  25138. if (filter$1.isGeometryChanged()) { this.geometryChanged(); }
  25139. } else if (hasInterface(arguments[0], GeometryFilter)) {
  25140. var filter$2 = arguments[0];
  25141. filter$2.filter(this);
  25142. for (var i$2 = 0; i$2 < this._geometries.length; i$2++) {
  25143. this$1._geometries[i$2].apply(filter$2);
  25144. }
  25145. } else if (hasInterface(arguments[0], GeometryComponentFilter)) {
  25146. var filter$3 = arguments[0];
  25147. filter$3.filter(this);
  25148. for (var i$3 = 0; i$3 < this._geometries.length; i$3++) {
  25149. this$1._geometries[i$3].apply(filter$3);
  25150. }
  25151. }
  25152. };
  25153. GeometryCollection.prototype.getBoundary = function getBoundary () {
  25154. this.checkNotGeometryCollection(this);
  25155. Assert.shouldNeverReachHere();
  25156. return null
  25157. };
  25158. GeometryCollection.prototype.clone = function clone () {
  25159. var this$1 = this;
  25160. var gc = Geometry$$1.prototype.clone.call(this);
  25161. gc._geometries = new Array(this._geometries.length).fill(null);
  25162. for (var i = 0; i < this._geometries.length; i++) {
  25163. gc._geometries[i] = this$1._geometries[i].clone();
  25164. }
  25165. return gc
  25166. };
  25167. GeometryCollection.prototype.getGeometryType = function getGeometryType () {
  25168. return 'GeometryCollection'
  25169. };
  25170. GeometryCollection.prototype.copy = function copy () {
  25171. var this$1 = this;
  25172. var geometries = new Array(this._geometries.length).fill(null);
  25173. for (var i = 0; i < geometries.length; i++) {
  25174. geometries[i] = this$1._geometries[i].copy();
  25175. }
  25176. return new GeometryCollection(geometries, this._factory)
  25177. };
  25178. GeometryCollection.prototype.isEmpty = function isEmpty () {
  25179. var this$1 = this;
  25180. for (var i = 0; i < this._geometries.length; i++) {
  25181. if (!this$1._geometries[i].isEmpty()) {
  25182. return false
  25183. }
  25184. }
  25185. return true
  25186. };
  25187. GeometryCollection.prototype.interfaces_ = function interfaces_ () {
  25188. return []
  25189. };
  25190. GeometryCollection.prototype.getClass = function getClass () {
  25191. return GeometryCollection
  25192. };
  25193. staticAccessors.serialVersionUID.get = function () { return -5694727726395021467 };
  25194. Object.defineProperties( GeometryCollection, staticAccessors );
  25195. return GeometryCollection;
  25196. }(Geometry));
  25197. var MultiLineString = (function (GeometryCollection$$1) {
  25198. function MultiLineString () {
  25199. GeometryCollection$$1.apply(this, arguments);
  25200. }
  25201. if ( GeometryCollection$$1 ) MultiLineString.__proto__ = GeometryCollection$$1;
  25202. MultiLineString.prototype = Object.create( GeometryCollection$$1 && GeometryCollection$$1.prototype );
  25203. MultiLineString.prototype.constructor = MultiLineString;
  25204. var staticAccessors = { serialVersionUID: { configurable: true } };
  25205. MultiLineString.prototype.getSortIndex = function getSortIndex () {
  25206. return Geometry.SORTINDEX_MULTILINESTRING
  25207. };
  25208. MultiLineString.prototype.equalsExact = function equalsExact () {
  25209. if (arguments.length === 2) {
  25210. var other = arguments[0];
  25211. var tolerance = arguments[1];
  25212. if (!this.isEquivalentClass(other)) {
  25213. return false
  25214. }
  25215. return GeometryCollection$$1.prototype.equalsExact.call(this, other, tolerance)
  25216. } else { return GeometryCollection$$1.prototype.equalsExact.apply(this, arguments) }
  25217. };
  25218. MultiLineString.prototype.getBoundaryDimension = function getBoundaryDimension () {
  25219. if (this.isClosed()) {
  25220. return Dimension.FALSE
  25221. }
  25222. return 0
  25223. };
  25224. MultiLineString.prototype.isClosed = function isClosed () {
  25225. var this$1 = this;
  25226. if (this.isEmpty()) {
  25227. return false
  25228. }
  25229. for (var i = 0; i < this._geometries.length; i++) {
  25230. if (!this$1._geometries[i].isClosed()) {
  25231. return false
  25232. }
  25233. }
  25234. return true
  25235. };
  25236. MultiLineString.prototype.getDimension = function getDimension () {
  25237. return 1
  25238. };
  25239. MultiLineString.prototype.reverse = function reverse () {
  25240. var this$1 = this;
  25241. var nLines = this._geometries.length;
  25242. var revLines = new Array(nLines).fill(null);
  25243. for (var i = 0; i < this._geometries.length; i++) {
  25244. revLines[nLines - 1 - i] = this$1._geometries[i].reverse();
  25245. }
  25246. return this.getFactory().createMultiLineString(revLines)
  25247. };
  25248. MultiLineString.prototype.getBoundary = function getBoundary () {
  25249. return new BoundaryOp(this).getBoundary()
  25250. };
  25251. MultiLineString.prototype.getGeometryType = function getGeometryType () {
  25252. return 'MultiLineString'
  25253. };
  25254. MultiLineString.prototype.copy = function copy () {
  25255. var this$1 = this;
  25256. var lineStrings = new Array(this._geometries.length).fill(null);
  25257. for (var i = 0; i < lineStrings.length; i++) {
  25258. lineStrings[i] = this$1._geometries[i].copy();
  25259. }
  25260. return new MultiLineString(lineStrings, this._factory)
  25261. };
  25262. MultiLineString.prototype.interfaces_ = function interfaces_ () {
  25263. return [Lineal]
  25264. };
  25265. MultiLineString.prototype.getClass = function getClass () {
  25266. return MultiLineString
  25267. };
  25268. staticAccessors.serialVersionUID.get = function () { return 8166665132445433741 };
  25269. Object.defineProperties( MultiLineString, staticAccessors );
  25270. return MultiLineString;
  25271. }(GeometryCollection));
  25272. var BoundaryOp = function BoundaryOp () {
  25273. this._geom = null;
  25274. this._geomFact = null;
  25275. this._bnRule = null;
  25276. this._endpointMap = null;
  25277. if (arguments.length === 1) {
  25278. var geom = arguments[0];
  25279. var bnRule = BoundaryNodeRule.MOD2_BOUNDARY_RULE;
  25280. this._geom = geom;
  25281. this._geomFact = geom.getFactory();
  25282. this._bnRule = bnRule;
  25283. } else if (arguments.length === 2) {
  25284. var geom$1 = arguments[0];
  25285. var bnRule$1 = arguments[1];
  25286. this._geom = geom$1;
  25287. this._geomFact = geom$1.getFactory();
  25288. this._bnRule = bnRule$1;
  25289. }
  25290. };
  25291. BoundaryOp.prototype.boundaryMultiLineString = function boundaryMultiLineString (mLine) {
  25292. if (this._geom.isEmpty()) {
  25293. return this.getEmptyMultiPoint()
  25294. }
  25295. var bdyPts = this.computeBoundaryCoordinates(mLine);
  25296. if (bdyPts.length === 1) {
  25297. return this._geomFact.createPoint(bdyPts[0])
  25298. }
  25299. return this._geomFact.createMultiPointFromCoords(bdyPts)
  25300. };
  25301. BoundaryOp.prototype.getBoundary = function getBoundary () {
  25302. if (this._geom instanceof LineString$1) { return this.boundaryLineString(this._geom) }
  25303. if (this._geom instanceof MultiLineString) { return this.boundaryMultiLineString(this._geom) }
  25304. return this._geom.getBoundary()
  25305. };
  25306. BoundaryOp.prototype.boundaryLineString = function boundaryLineString (line) {
  25307. if (this._geom.isEmpty()) {
  25308. return this.getEmptyMultiPoint()
  25309. }
  25310. if (line.isClosed()) {
  25311. var closedEndpointOnBoundary = this._bnRule.isInBoundary(2);
  25312. if (closedEndpointOnBoundary) {
  25313. return line.getStartPoint()
  25314. } else {
  25315. return this._geomFact.createMultiPoint()
  25316. }
  25317. }
  25318. return this._geomFact.createMultiPoint([line.getStartPoint(), line.getEndPoint()])
  25319. };
  25320. BoundaryOp.prototype.getEmptyMultiPoint = function getEmptyMultiPoint () {
  25321. return this._geomFact.createMultiPoint()
  25322. };
  25323. BoundaryOp.prototype.computeBoundaryCoordinates = function computeBoundaryCoordinates (mLine) {
  25324. var this$1 = this;
  25325. var bdyPts = new ArrayList();
  25326. this._endpointMap = new TreeMap();
  25327. for (var i = 0; i < mLine.getNumGeometries(); i++) {
  25328. var line = mLine.getGeometryN(i);
  25329. if (line.getNumPoints() === 0) { continue }
  25330. this$1.addEndpoint(line.getCoordinateN(0));
  25331. this$1.addEndpoint(line.getCoordinateN(line.getNumPoints() - 1));
  25332. }
  25333. for (var it = this._endpointMap.entrySet().iterator(); it.hasNext();) {
  25334. var entry = it.next();
  25335. var counter = entry.getValue();
  25336. var valence = counter.count;
  25337. if (this$1._bnRule.isInBoundary(valence)) {
  25338. bdyPts.add(entry.getKey());
  25339. }
  25340. }
  25341. return CoordinateArrays.toCoordinateArray(bdyPts)
  25342. };
  25343. BoundaryOp.prototype.addEndpoint = function addEndpoint (pt) {
  25344. var counter = this._endpointMap.get(pt);
  25345. if (counter === null) {
  25346. counter = new Counter();
  25347. this._endpointMap.put(pt, counter);
  25348. }
  25349. counter.count++;
  25350. };
  25351. BoundaryOp.prototype.interfaces_ = function interfaces_ () {
  25352. return []
  25353. };
  25354. BoundaryOp.prototype.getClass = function getClass () {
  25355. return BoundaryOp
  25356. };
  25357. BoundaryOp.getBoundary = function getBoundary () {
  25358. if (arguments.length === 1) {
  25359. var g = arguments[0];
  25360. var bop = new BoundaryOp(g);
  25361. return bop.getBoundary()
  25362. } else if (arguments.length === 2) {
  25363. var g$1 = arguments[0];
  25364. var bnRule = arguments[1];
  25365. var bop$1 = new BoundaryOp(g$1, bnRule);
  25366. return bop$1.getBoundary()
  25367. }
  25368. };
  25369. var Counter = function Counter () {
  25370. this.count = null;
  25371. };
  25372. Counter.prototype.interfaces_ = function interfaces_ () {
  25373. return []
  25374. };
  25375. Counter.prototype.getClass = function getClass () {
  25376. return Counter
  25377. };
  25378. // boundary
  25379. function PrintStream () {}
  25380. function StringReader () {}
  25381. var DecimalFormat = function DecimalFormat () {};
  25382. function ByteArrayOutputStream () {}
  25383. function IOException () {}
  25384. function LineNumberReader () {}
  25385. var StringUtil = function StringUtil () {};
  25386. var staticAccessors$15 = { NEWLINE: { configurable: true },SIMPLE_ORDINATE_FORMAT: { configurable: true } };
  25387. StringUtil.prototype.interfaces_ = function interfaces_ () {
  25388. return []
  25389. };
  25390. StringUtil.prototype.getClass = function getClass () {
  25391. return StringUtil
  25392. };
  25393. StringUtil.chars = function chars (c, n) {
  25394. var ch = new Array(n).fill(null);
  25395. for (var i = 0; i < n; i++) {
  25396. ch[i] = c;
  25397. }
  25398. return String(ch)
  25399. };
  25400. StringUtil.getStackTrace = function getStackTrace () {
  25401. if (arguments.length === 1) {
  25402. var t = arguments[0];
  25403. var os = new ByteArrayOutputStream();
  25404. var ps = new PrintStream(os);
  25405. t.printStackTrace(ps);
  25406. return os.toString()
  25407. } else if (arguments.length === 2) {
  25408. var t$1 = arguments[0];
  25409. var depth = arguments[1];
  25410. var stackTrace = '';
  25411. var stringReader = new StringReader(StringUtil.getStackTrace(t$1));
  25412. var lineNumberReader = new LineNumberReader(stringReader);
  25413. for (var i = 0; i < depth; i++) {
  25414. try {
  25415. stackTrace += lineNumberReader.readLine() + StringUtil.NEWLINE;
  25416. } catch (e) {
  25417. if (e instanceof IOException) {
  25418. Assert.shouldNeverReachHere();
  25419. } else { throw e }
  25420. } finally {}
  25421. }
  25422. return stackTrace
  25423. }
  25424. };
  25425. StringUtil.split = function split (s, separator) {
  25426. var separatorlen = separator.length;
  25427. var tokenList = new ArrayList();
  25428. var tmpString = '' + s;
  25429. var pos = tmpString.indexOf(separator);
  25430. while (pos >= 0) {
  25431. var token = tmpString.substring(0, pos);
  25432. tokenList.add(token);
  25433. tmpString = tmpString.substring(pos + separatorlen);
  25434. pos = tmpString.indexOf(separator);
  25435. }
  25436. if (tmpString.length > 0) { tokenList.add(tmpString); }
  25437. var res = new Array(tokenList.size()).fill(null);
  25438. for (var i = 0; i < res.length; i++) {
  25439. res[i] = tokenList.get(i);
  25440. }
  25441. return res
  25442. };
  25443. StringUtil.toString = function toString () {
  25444. if (arguments.length === 1) {
  25445. var d = arguments[0];
  25446. return StringUtil.SIMPLE_ORDINATE_FORMAT.format(d)
  25447. }
  25448. };
  25449. StringUtil.spaces = function spaces (n) {
  25450. return StringUtil.chars(' ', n)
  25451. };
  25452. staticAccessors$15.NEWLINE.get = function () { return System.getProperty('line.separator') };
  25453. staticAccessors$15.SIMPLE_ORDINATE_FORMAT.get = function () { return new DecimalFormat('0.#') };
  25454. Object.defineProperties( StringUtil, staticAccessors$15 );
  25455. var CoordinateSequences = function CoordinateSequences () {};
  25456. CoordinateSequences.prototype.interfaces_ = function interfaces_ () {
  25457. return []
  25458. };
  25459. CoordinateSequences.prototype.getClass = function getClass () {
  25460. return CoordinateSequences
  25461. };
  25462. CoordinateSequences.copyCoord = function copyCoord (src, srcPos, dest, destPos) {
  25463. var minDim = Math.min(src.getDimension(), dest.getDimension());
  25464. for (var dim = 0; dim < minDim; dim++) {
  25465. dest.setOrdinate(destPos, dim, src.getOrdinate(srcPos, dim));
  25466. }
  25467. };
  25468. CoordinateSequences.isRing = function isRing (seq) {
  25469. var n = seq.size();
  25470. if (n === 0) { return true }
  25471. if (n <= 3) { return false }
  25472. return seq.getOrdinate(0, CoordinateSequence.X) === seq.getOrdinate(n - 1, CoordinateSequence.X) && seq.getOrdinate(0, CoordinateSequence.Y) === seq.getOrdinate(n - 1, CoordinateSequence.Y)
  25473. };
  25474. CoordinateSequences.isEqual = function isEqual (cs1, cs2) {
  25475. var cs1Size = cs1.size();
  25476. var cs2Size = cs2.size();
  25477. if (cs1Size !== cs2Size) { return false }
  25478. var dim = Math.min(cs1.getDimension(), cs2.getDimension());
  25479. for (var i = 0; i < cs1Size; i++) {
  25480. for (var d = 0; d < dim; d++) {
  25481. var v1 = cs1.getOrdinate(i, d);
  25482. var v2 = cs2.getOrdinate(i, d);
  25483. if (cs1.getOrdinate(i, d) === cs2.getOrdinate(i, d)) { continue }
  25484. if (Double.isNaN(v1) && Double.isNaN(v2)) { continue }
  25485. return false
  25486. }
  25487. }
  25488. return true
  25489. };
  25490. CoordinateSequences.extend = function extend (fact, seq, size) {
  25491. var newseq = fact.create(size, seq.getDimension());
  25492. var n = seq.size();
  25493. CoordinateSequences.copy(seq, 0, newseq, 0, n);
  25494. if (n > 0) {
  25495. for (var i = n; i < size; i++) { CoordinateSequences.copy(seq, n - 1, newseq, i, 1); }
  25496. }
  25497. return newseq
  25498. };
  25499. CoordinateSequences.reverse = function reverse (seq) {
  25500. var last = seq.size() - 1;
  25501. var mid = Math.trunc(last / 2);
  25502. for (var i = 0; i <= mid; i++) {
  25503. CoordinateSequences.swap(seq, i, last - i);
  25504. }
  25505. };
  25506. CoordinateSequences.swap = function swap (seq, i, j) {
  25507. if (i === j) { return null }
  25508. for (var dim = 0; dim < seq.getDimension(); dim++) {
  25509. var tmp = seq.getOrdinate(i, dim);
  25510. seq.setOrdinate(i, dim, seq.getOrdinate(j, dim));
  25511. seq.setOrdinate(j, dim, tmp);
  25512. }
  25513. };
  25514. CoordinateSequences.copy = function copy (src, srcPos, dest, destPos, length) {
  25515. for (var i = 0; i < length; i++) {
  25516. CoordinateSequences.copyCoord(src, srcPos + i, dest, destPos + i);
  25517. }
  25518. };
  25519. CoordinateSequences.toString = function toString () {
  25520. if (arguments.length === 1) {
  25521. var cs = arguments[0];
  25522. var size = cs.size();
  25523. if (size === 0) { return '()' }
  25524. var dim = cs.getDimension();
  25525. var buf = new StringBuffer();
  25526. buf.append('(');
  25527. for (var i = 0; i < size; i++) {
  25528. if (i > 0) { buf.append(' '); }
  25529. for (var d = 0; d < dim; d++) {
  25530. if (d > 0) { buf.append(','); }
  25531. buf.append(StringUtil.toString(cs.getOrdinate(i, d)));
  25532. }
  25533. }
  25534. buf.append(')');
  25535. return buf.toString()
  25536. }
  25537. };
  25538. CoordinateSequences.ensureValidRing = function ensureValidRing (fact, seq) {
  25539. var n = seq.size();
  25540. if (n === 0) { return seq }
  25541. if (n <= 3) { return CoordinateSequences.createClosedRing(fact, seq, 4) }
  25542. var isClosed = seq.getOrdinate(0, CoordinateSequence.X) === seq.getOrdinate(n - 1, CoordinateSequence.X) && seq.getOrdinate(0, CoordinateSequence.Y) === seq.getOrdinate(n - 1, CoordinateSequence.Y);
  25543. if (isClosed) { return seq }
  25544. return CoordinateSequences.createClosedRing(fact, seq, n + 1)
  25545. };
  25546. CoordinateSequences.createClosedRing = function createClosedRing (fact, seq, size) {
  25547. var newseq = fact.create(size, seq.getDimension());
  25548. var n = seq.size();
  25549. CoordinateSequences.copy(seq, 0, newseq, 0, n);
  25550. for (var i = n; i < size; i++) { CoordinateSequences.copy(seq, 0, newseq, i, 1); }
  25551. return newseq
  25552. };
  25553. var LineString$1 = (function (Geometry$$1) {
  25554. function LineString (points, factory) {
  25555. Geometry$$1.call(this, factory);
  25556. this._points = null;
  25557. this.init(points);
  25558. }
  25559. if ( Geometry$$1 ) LineString.__proto__ = Geometry$$1;
  25560. LineString.prototype = Object.create( Geometry$$1 && Geometry$$1.prototype );
  25561. LineString.prototype.constructor = LineString;
  25562. var staticAccessors = { serialVersionUID: { configurable: true } };
  25563. LineString.prototype.computeEnvelopeInternal = function computeEnvelopeInternal () {
  25564. if (this.isEmpty()) {
  25565. return new Envelope()
  25566. }
  25567. return this._points.expandEnvelope(new Envelope())
  25568. };
  25569. LineString.prototype.isRing = function isRing () {
  25570. return this.isClosed() && this.isSimple()
  25571. };
  25572. LineString.prototype.getSortIndex = function getSortIndex () {
  25573. return Geometry$$1.SORTINDEX_LINESTRING
  25574. };
  25575. LineString.prototype.getCoordinates = function getCoordinates () {
  25576. return this._points.toCoordinateArray()
  25577. };
  25578. LineString.prototype.equalsExact = function equalsExact () {
  25579. var this$1 = this;
  25580. if (arguments.length === 2) {
  25581. var other = arguments[0];
  25582. var tolerance = arguments[1];
  25583. if (!this.isEquivalentClass(other)) {
  25584. return false
  25585. }
  25586. var otherLineString = other;
  25587. if (this._points.size() !== otherLineString._points.size()) {
  25588. return false
  25589. }
  25590. for (var i = 0; i < this._points.size(); i++) {
  25591. if (!this$1.equal(this$1._points.getCoordinate(i), otherLineString._points.getCoordinate(i), tolerance)) {
  25592. return false
  25593. }
  25594. }
  25595. return true
  25596. } else { return Geometry$$1.prototype.equalsExact.apply(this, arguments) }
  25597. };
  25598. LineString.prototype.normalize = function normalize () {
  25599. var this$1 = this;
  25600. for (var i = 0; i < Math.trunc(this._points.size() / 2); i++) {
  25601. var j = this$1._points.size() - 1 - i;
  25602. if (!this$1._points.getCoordinate(i).equals(this$1._points.getCoordinate(j))) {
  25603. if (this$1._points.getCoordinate(i).compareTo(this$1._points.getCoordinate(j)) > 0) {
  25604. CoordinateSequences.reverse(this$1._points);
  25605. }
  25606. return null
  25607. }
  25608. }
  25609. };
  25610. LineString.prototype.getCoordinate = function getCoordinate () {
  25611. if (this.isEmpty()) { return null }
  25612. return this._points.getCoordinate(0)
  25613. };
  25614. LineString.prototype.getBoundaryDimension = function getBoundaryDimension () {
  25615. if (this.isClosed()) {
  25616. return Dimension.FALSE
  25617. }
  25618. return 0
  25619. };
  25620. LineString.prototype.isClosed = function isClosed () {
  25621. if (this.isEmpty()) {
  25622. return false
  25623. }
  25624. return this.getCoordinateN(0).equals2D(this.getCoordinateN(this.getNumPoints() - 1))
  25625. };
  25626. LineString.prototype.getEndPoint = function getEndPoint () {
  25627. if (this.isEmpty()) {
  25628. return null
  25629. }
  25630. return this.getPointN(this.getNumPoints() - 1)
  25631. };
  25632. LineString.prototype.getDimension = function getDimension () {
  25633. return 1
  25634. };
  25635. LineString.prototype.getLength = function getLength () {
  25636. return CGAlgorithms.computeLength(this._points)
  25637. };
  25638. LineString.prototype.getNumPoints = function getNumPoints () {
  25639. return this._points.size()
  25640. };
  25641. LineString.prototype.reverse = function reverse () {
  25642. var seq = this._points.copy();
  25643. CoordinateSequences.reverse(seq);
  25644. var revLine = this.getFactory().createLineString(seq);
  25645. return revLine
  25646. };
  25647. LineString.prototype.compareToSameClass = function compareToSameClass () {
  25648. var this$1 = this;
  25649. if (arguments.length === 1) {
  25650. var o = arguments[0];
  25651. var line = o;
  25652. var i = 0;
  25653. var j = 0;
  25654. while (i < this._points.size() && j < line._points.size()) {
  25655. var comparison = this$1._points.getCoordinate(i).compareTo(line._points.getCoordinate(j));
  25656. if (comparison !== 0) {
  25657. return comparison
  25658. }
  25659. i++;
  25660. j++;
  25661. }
  25662. if (i < this._points.size()) {
  25663. return 1
  25664. }
  25665. if (j < line._points.size()) {
  25666. return -1
  25667. }
  25668. return 0
  25669. } else if (arguments.length === 2) {
  25670. var o$1 = arguments[0];
  25671. var comp = arguments[1];
  25672. var line$1 = o$1;
  25673. return comp.compare(this._points, line$1._points)
  25674. }
  25675. };
  25676. LineString.prototype.apply = function apply () {
  25677. var this$1 = this;
  25678. if (hasInterface(arguments[0], CoordinateFilter)) {
  25679. var filter = arguments[0];
  25680. for (var i = 0; i < this._points.size(); i++) {
  25681. filter.filter(this$1._points.getCoordinate(i));
  25682. }
  25683. } else if (hasInterface(arguments[0], CoordinateSequenceFilter)) {
  25684. var filter$1 = arguments[0];
  25685. if (this._points.size() === 0) { return null }
  25686. for (var i$1 = 0; i$1 < this._points.size(); i$1++) {
  25687. filter$1.filter(this$1._points, i$1);
  25688. if (filter$1.isDone()) { break }
  25689. }
  25690. if (filter$1.isGeometryChanged()) { this.geometryChanged(); }
  25691. } else if (hasInterface(arguments[0], GeometryFilter)) {
  25692. var filter$2 = arguments[0];
  25693. filter$2.filter(this);
  25694. } else if (hasInterface(arguments[0], GeometryComponentFilter)) {
  25695. var filter$3 = arguments[0];
  25696. filter$3.filter(this);
  25697. }
  25698. };
  25699. LineString.prototype.getBoundary = function getBoundary () {
  25700. return new BoundaryOp(this).getBoundary()
  25701. };
  25702. LineString.prototype.isEquivalentClass = function isEquivalentClass (other) {
  25703. return other instanceof LineString
  25704. };
  25705. LineString.prototype.clone = function clone () {
  25706. var ls = Geometry$$1.prototype.clone.call(this);
  25707. ls._points = this._points.clone();
  25708. return ls
  25709. };
  25710. LineString.prototype.getCoordinateN = function getCoordinateN (n) {
  25711. return this._points.getCoordinate(n)
  25712. };
  25713. LineString.prototype.getGeometryType = function getGeometryType () {
  25714. return 'LineString'
  25715. };
  25716. LineString.prototype.copy = function copy () {
  25717. return new LineString(this._points.copy(), this._factory)
  25718. };
  25719. LineString.prototype.getCoordinateSequence = function getCoordinateSequence () {
  25720. return this._points
  25721. };
  25722. LineString.prototype.isEmpty = function isEmpty () {
  25723. return this._points.size() === 0
  25724. };
  25725. LineString.prototype.init = function init (points) {
  25726. if (points === null) {
  25727. points = this.getFactory().getCoordinateSequenceFactory().create([]);
  25728. }
  25729. if (points.size() === 1) {
  25730. throw new IllegalArgumentException('Invalid number of points in LineString (found ' + points.size() + ' - must be 0 or >= 2)')
  25731. }
  25732. this._points = points;
  25733. };
  25734. LineString.prototype.isCoordinate = function isCoordinate (pt) {
  25735. var this$1 = this;
  25736. for (var i = 0; i < this._points.size(); i++) {
  25737. if (this$1._points.getCoordinate(i).equals(pt)) {
  25738. return true
  25739. }
  25740. }
  25741. return false
  25742. };
  25743. LineString.prototype.getStartPoint = function getStartPoint () {
  25744. if (this.isEmpty()) {
  25745. return null
  25746. }
  25747. return this.getPointN(0)
  25748. };
  25749. LineString.prototype.getPointN = function getPointN (n) {
  25750. return this.getFactory().createPoint(this._points.getCoordinate(n))
  25751. };
  25752. LineString.prototype.interfaces_ = function interfaces_ () {
  25753. return [Lineal]
  25754. };
  25755. LineString.prototype.getClass = function getClass () {
  25756. return LineString
  25757. };
  25758. staticAccessors.serialVersionUID.get = function () { return 3110669828065365560 };
  25759. Object.defineProperties( LineString, staticAccessors );
  25760. return LineString;
  25761. }(Geometry));
  25762. var Puntal = function Puntal () {};
  25763. Puntal.prototype.interfaces_ = function interfaces_ () {
  25764. return []
  25765. };
  25766. Puntal.prototype.getClass = function getClass () {
  25767. return Puntal
  25768. };
  25769. var Point = (function (Geometry$$1) {
  25770. function Point (coordinates, factory) {
  25771. Geometry$$1.call(this, factory);
  25772. this._coordinates = coordinates || null;
  25773. this.init(this._coordinates);
  25774. }
  25775. if ( Geometry$$1 ) Point.__proto__ = Geometry$$1;
  25776. Point.prototype = Object.create( Geometry$$1 && Geometry$$1.prototype );
  25777. Point.prototype.constructor = Point;
  25778. var staticAccessors = { serialVersionUID: { configurable: true } };
  25779. Point.prototype.computeEnvelopeInternal = function computeEnvelopeInternal () {
  25780. if (this.isEmpty()) {
  25781. return new Envelope()
  25782. }
  25783. var env = new Envelope();
  25784. env.expandToInclude(this._coordinates.getX(0), this._coordinates.getY(0));
  25785. return env
  25786. };
  25787. Point.prototype.getSortIndex = function getSortIndex () {
  25788. return Geometry$$1.SORTINDEX_POINT
  25789. };
  25790. Point.prototype.getCoordinates = function getCoordinates () {
  25791. return this.isEmpty() ? [] : [this.getCoordinate()]
  25792. };
  25793. Point.prototype.equalsExact = function equalsExact () {
  25794. if (arguments.length === 2) {
  25795. var other = arguments[0];
  25796. var tolerance = arguments[1];
  25797. if (!this.isEquivalentClass(other)) {
  25798. return false
  25799. }
  25800. if (this.isEmpty() && other.isEmpty()) {
  25801. return true
  25802. }
  25803. if (this.isEmpty() !== other.isEmpty()) {
  25804. return false
  25805. }
  25806. return this.equal(other.getCoordinate(), this.getCoordinate(), tolerance)
  25807. } else { return Geometry$$1.prototype.equalsExact.apply(this, arguments) }
  25808. };
  25809. Point.prototype.normalize = function normalize () {};
  25810. Point.prototype.getCoordinate = function getCoordinate () {
  25811. return this._coordinates.size() !== 0 ? this._coordinates.getCoordinate(0) : null
  25812. };
  25813. Point.prototype.getBoundaryDimension = function getBoundaryDimension () {
  25814. return Dimension.FALSE
  25815. };
  25816. Point.prototype.getDimension = function getDimension () {
  25817. return 0
  25818. };
  25819. Point.prototype.getNumPoints = function getNumPoints () {
  25820. return this.isEmpty() ? 0 : 1
  25821. };
  25822. Point.prototype.reverse = function reverse () {
  25823. return this.copy()
  25824. };
  25825. Point.prototype.getX = function getX () {
  25826. if (this.getCoordinate() === null) {
  25827. throw new Error('getX called on empty Point')
  25828. }
  25829. return this.getCoordinate().x
  25830. };
  25831. Point.prototype.compareToSameClass = function compareToSameClass () {
  25832. if (arguments.length === 1) {
  25833. var other = arguments[0];
  25834. var point$1 = other;
  25835. return this.getCoordinate().compareTo(point$1.getCoordinate())
  25836. } else if (arguments.length === 2) {
  25837. var other$1 = arguments[0];
  25838. var comp = arguments[1];
  25839. var point = other$1;
  25840. return comp.compare(this._coordinates, point._coordinates)
  25841. }
  25842. };
  25843. Point.prototype.apply = function apply () {
  25844. if (hasInterface(arguments[0], CoordinateFilter)) {
  25845. var filter = arguments[0];
  25846. if (this.isEmpty()) {
  25847. return null
  25848. }
  25849. filter.filter(this.getCoordinate());
  25850. } else if (hasInterface(arguments[0], CoordinateSequenceFilter)) {
  25851. var filter$1 = arguments[0];
  25852. if (this.isEmpty()) { return null }
  25853. filter$1.filter(this._coordinates, 0);
  25854. if (filter$1.isGeometryChanged()) { this.geometryChanged(); }
  25855. } else if (hasInterface(arguments[0], GeometryFilter)) {
  25856. var filter$2 = arguments[0];
  25857. filter$2.filter(this);
  25858. } else if (hasInterface(arguments[0], GeometryComponentFilter)) {
  25859. var filter$3 = arguments[0];
  25860. filter$3.filter(this);
  25861. }
  25862. };
  25863. Point.prototype.getBoundary = function getBoundary () {
  25864. return this.getFactory().createGeometryCollection(null)
  25865. };
  25866. Point.prototype.clone = function clone () {
  25867. var p = Geometry$$1.prototype.clone.call(this);
  25868. p._coordinates = this._coordinates.clone();
  25869. return p
  25870. };
  25871. Point.prototype.getGeometryType = function getGeometryType () {
  25872. return 'Point'
  25873. };
  25874. Point.prototype.copy = function copy () {
  25875. return new Point(this._coordinates.copy(), this._factory)
  25876. };
  25877. Point.prototype.getCoordinateSequence = function getCoordinateSequence () {
  25878. return this._coordinates
  25879. };
  25880. Point.prototype.getY = function getY () {
  25881. if (this.getCoordinate() === null) {
  25882. throw new Error('getY called on empty Point')
  25883. }
  25884. return this.getCoordinate().y
  25885. };
  25886. Point.prototype.isEmpty = function isEmpty () {
  25887. return this._coordinates.size() === 0
  25888. };
  25889. Point.prototype.init = function init (coordinates) {
  25890. if (coordinates === null) {
  25891. coordinates = this.getFactory().getCoordinateSequenceFactory().create([]);
  25892. }
  25893. Assert.isTrue(coordinates.size() <= 1);
  25894. this._coordinates = coordinates;
  25895. };
  25896. Point.prototype.isSimple = function isSimple () {
  25897. return true
  25898. };
  25899. Point.prototype.interfaces_ = function interfaces_ () {
  25900. return [Puntal]
  25901. };
  25902. Point.prototype.getClass = function getClass () {
  25903. return Point
  25904. };
  25905. staticAccessors.serialVersionUID.get = function () { return 4902022702746614570 };
  25906. Object.defineProperties( Point, staticAccessors );
  25907. return Point;
  25908. }(Geometry));
  25909. var Polygonal = function Polygonal () {};
  25910. Polygonal.prototype.interfaces_ = function interfaces_ () {
  25911. return []
  25912. };
  25913. Polygonal.prototype.getClass = function getClass () {
  25914. return Polygonal
  25915. };
  25916. var Polygon = (function (Geometry$$1) {
  25917. function Polygon (shell, holes, factory) {
  25918. Geometry$$1.call(this, factory);
  25919. this._shell = null;
  25920. this._holes = null;
  25921. if (shell === null) {
  25922. shell = this.getFactory().createLinearRing();
  25923. }
  25924. if (holes === null) {
  25925. holes = [];
  25926. }
  25927. if (Geometry$$1.hasNullElements(holes)) {
  25928. throw new IllegalArgumentException('holes must not contain null elements')
  25929. }
  25930. if (shell.isEmpty() && Geometry$$1.hasNonEmptyElements(holes)) {
  25931. throw new IllegalArgumentException('shell is empty but holes are not')
  25932. }
  25933. this._shell = shell;
  25934. this._holes = holes;
  25935. }
  25936. if ( Geometry$$1 ) Polygon.__proto__ = Geometry$$1;
  25937. Polygon.prototype = Object.create( Geometry$$1 && Geometry$$1.prototype );
  25938. Polygon.prototype.constructor = Polygon;
  25939. var staticAccessors = { serialVersionUID: { configurable: true } };
  25940. Polygon.prototype.computeEnvelopeInternal = function computeEnvelopeInternal () {
  25941. return this._shell.getEnvelopeInternal()
  25942. };
  25943. Polygon.prototype.getSortIndex = function getSortIndex () {
  25944. return Geometry$$1.SORTINDEX_POLYGON
  25945. };
  25946. Polygon.prototype.getCoordinates = function getCoordinates () {
  25947. var this$1 = this;
  25948. if (this.isEmpty()) {
  25949. return []
  25950. }
  25951. var coordinates = new Array(this.getNumPoints()).fill(null);
  25952. var k = -1;
  25953. var shellCoordinates = this._shell.getCoordinates();
  25954. for (var x = 0; x < shellCoordinates.length; x++) {
  25955. k++;
  25956. coordinates[k] = shellCoordinates[x];
  25957. }
  25958. for (var i = 0; i < this._holes.length; i++) {
  25959. var childCoordinates = this$1._holes[i].getCoordinates();
  25960. for (var j = 0; j < childCoordinates.length; j++) {
  25961. k++;
  25962. coordinates[k] = childCoordinates[j];
  25963. }
  25964. }
  25965. return coordinates
  25966. };
  25967. Polygon.prototype.getArea = function getArea () {
  25968. var this$1 = this;
  25969. var area = 0.0;
  25970. area += Math.abs(CGAlgorithms.signedArea(this._shell.getCoordinateSequence()));
  25971. for (var i = 0; i < this._holes.length; i++) {
  25972. area -= Math.abs(CGAlgorithms.signedArea(this$1._holes[i].getCoordinateSequence()));
  25973. }
  25974. return area
  25975. };
  25976. Polygon.prototype.isRectangle = function isRectangle () {
  25977. if (this.getNumInteriorRing() !== 0) { return false }
  25978. if (this._shell === null) { return false }
  25979. if (this._shell.getNumPoints() !== 5) { return false }
  25980. var seq = this._shell.getCoordinateSequence();
  25981. var env = this.getEnvelopeInternal();
  25982. for (var i = 0; i < 5; i++) {
  25983. var x = seq.getX(i);
  25984. if (!(x === env.getMinX() || x === env.getMaxX())) { return false }
  25985. var y = seq.getY(i);
  25986. if (!(y === env.getMinY() || y === env.getMaxY())) { return false }
  25987. }
  25988. var prevX = seq.getX(0);
  25989. var prevY = seq.getY(0);
  25990. for (var i$1 = 1; i$1 <= 4; i$1++) {
  25991. var x$1 = seq.getX(i$1);
  25992. var y$1 = seq.getY(i$1);
  25993. var xChanged = x$1 !== prevX;
  25994. var yChanged = y$1 !== prevY;
  25995. if (xChanged === yChanged) { return false }
  25996. prevX = x$1;
  25997. prevY = y$1;
  25998. }
  25999. return true
  26000. };
  26001. Polygon.prototype.equalsExact = function equalsExact () {
  26002. var this$1 = this;
  26003. if (arguments.length === 2) {
  26004. var other = arguments[0];
  26005. var tolerance = arguments[1];
  26006. if (!this.isEquivalentClass(other)) {
  26007. return false
  26008. }
  26009. var otherPolygon = other;
  26010. var thisShell = this._shell;
  26011. var otherPolygonShell = otherPolygon._shell;
  26012. if (!thisShell.equalsExact(otherPolygonShell, tolerance)) {
  26013. return false
  26014. }
  26015. if (this._holes.length !== otherPolygon._holes.length) {
  26016. return false
  26017. }
  26018. for (var i = 0; i < this._holes.length; i++) {
  26019. if (!this$1._holes[i].equalsExact(otherPolygon._holes[i], tolerance)) {
  26020. return false
  26021. }
  26022. }
  26023. return true
  26024. } else { return Geometry$$1.prototype.equalsExact.apply(this, arguments) }
  26025. };
  26026. Polygon.prototype.normalize = function normalize () {
  26027. var this$1 = this;
  26028. if (arguments.length === 0) {
  26029. this.normalize(this._shell, true);
  26030. for (var i = 0; i < this._holes.length; i++) {
  26031. this$1.normalize(this$1._holes[i], false);
  26032. }
  26033. Arrays.sort(this._holes);
  26034. } else if (arguments.length === 2) {
  26035. var ring = arguments[0];
  26036. var clockwise = arguments[1];
  26037. if (ring.isEmpty()) {
  26038. return null
  26039. }
  26040. var uniqueCoordinates = new Array(ring.getCoordinates().length - 1).fill(null);
  26041. System.arraycopy(ring.getCoordinates(), 0, uniqueCoordinates, 0, uniqueCoordinates.length);
  26042. var minCoordinate = CoordinateArrays.minCoordinate(ring.getCoordinates());
  26043. CoordinateArrays.scroll(uniqueCoordinates, minCoordinate);
  26044. System.arraycopy(uniqueCoordinates, 0, ring.getCoordinates(), 0, uniqueCoordinates.length);
  26045. ring.getCoordinates()[uniqueCoordinates.length] = uniqueCoordinates[0];
  26046. if (CGAlgorithms.isCCW(ring.getCoordinates()) === clockwise) {
  26047. CoordinateArrays.reverse(ring.getCoordinates());
  26048. }
  26049. }
  26050. };
  26051. Polygon.prototype.getCoordinate = function getCoordinate () {
  26052. return this._shell.getCoordinate()
  26053. };
  26054. Polygon.prototype.getNumInteriorRing = function getNumInteriorRing () {
  26055. return this._holes.length
  26056. };
  26057. Polygon.prototype.getBoundaryDimension = function getBoundaryDimension () {
  26058. return 1
  26059. };
  26060. Polygon.prototype.getDimension = function getDimension () {
  26061. return 2
  26062. };
  26063. Polygon.prototype.getLength = function getLength () {
  26064. var this$1 = this;
  26065. var len = 0.0;
  26066. len += this._shell.getLength();
  26067. for (var i = 0; i < this._holes.length; i++) {
  26068. len += this$1._holes[i].getLength();
  26069. }
  26070. return len
  26071. };
  26072. Polygon.prototype.getNumPoints = function getNumPoints () {
  26073. var this$1 = this;
  26074. var numPoints = this._shell.getNumPoints();
  26075. for (var i = 0; i < this._holes.length; i++) {
  26076. numPoints += this$1._holes[i].getNumPoints();
  26077. }
  26078. return numPoints
  26079. };
  26080. Polygon.prototype.reverse = function reverse () {
  26081. var this$1 = this;
  26082. var poly = this.copy();
  26083. poly._shell = this._shell.copy().reverse();
  26084. poly._holes = new Array(this._holes.length).fill(null);
  26085. for (var i = 0; i < this._holes.length; i++) {
  26086. poly._holes[i] = this$1._holes[i].copy().reverse();
  26087. }
  26088. return poly
  26089. };
  26090. Polygon.prototype.convexHull = function convexHull () {
  26091. return this.getExteriorRing().convexHull()
  26092. };
  26093. Polygon.prototype.compareToSameClass = function compareToSameClass () {
  26094. var this$1 = this;
  26095. if (arguments.length === 1) {
  26096. var o = arguments[0];
  26097. var thisShell = this._shell;
  26098. var otherShell = o._shell;
  26099. return thisShell.compareToSameClass(otherShell)
  26100. } else if (arguments.length === 2) {
  26101. var o$1 = arguments[0];
  26102. var comp = arguments[1];
  26103. var poly = o$1;
  26104. var thisShell$1 = this._shell;
  26105. var otherShell$1 = poly._shell;
  26106. var shellComp = thisShell$1.compareToSameClass(otherShell$1, comp);
  26107. if (shellComp !== 0) { return shellComp }
  26108. var nHole1 = this.getNumInteriorRing();
  26109. var nHole2 = poly.getNumInteriorRing();
  26110. var i = 0;
  26111. while (i < nHole1 && i < nHole2) {
  26112. var thisHole = this$1.getInteriorRingN(i);
  26113. var otherHole = poly.getInteriorRingN(i);
  26114. var holeComp = thisHole.compareToSameClass(otherHole, comp);
  26115. if (holeComp !== 0) { return holeComp }
  26116. i++;
  26117. }
  26118. if (i < nHole1) { return 1 }
  26119. if (i < nHole2) { return -1 }
  26120. return 0
  26121. }
  26122. };
  26123. Polygon.prototype.apply = function apply (filter) {
  26124. var this$1 = this;
  26125. if (hasInterface(filter, CoordinateFilter)) {
  26126. this._shell.apply(filter);
  26127. for (var i$1 = 0; i$1 < this._holes.length; i$1++) {
  26128. this$1._holes[i$1].apply(filter);
  26129. }
  26130. } else if (hasInterface(filter, CoordinateSequenceFilter)) {
  26131. this._shell.apply(filter);
  26132. if (!filter.isDone()) {
  26133. for (var i$2 = 0; i$2 < this._holes.length; i$2++) {
  26134. this$1._holes[i$2].apply(filter);
  26135. if (filter.isDone()) { break }
  26136. }
  26137. }
  26138. if (filter.isGeometryChanged()) { this.geometryChanged(); }
  26139. } else if (hasInterface(filter, GeometryFilter)) {
  26140. filter.filter(this);
  26141. } else if (hasInterface(filter, GeometryComponentFilter)) {
  26142. filter.filter(this);
  26143. this._shell.apply(filter);
  26144. for (var i = 0; i < this._holes.length; i++) {
  26145. this$1._holes[i].apply(filter);
  26146. }
  26147. }
  26148. };
  26149. Polygon.prototype.getBoundary = function getBoundary () {
  26150. var this$1 = this;
  26151. if (this.isEmpty()) {
  26152. return this.getFactory().createMultiLineString()
  26153. }
  26154. var rings = new Array(this._holes.length + 1).fill(null);
  26155. rings[0] = this._shell;
  26156. for (var i = 0; i < this._holes.length; i++) {
  26157. rings[i + 1] = this$1._holes[i];
  26158. }
  26159. if (rings.length <= 1) { return this.getFactory().createLinearRing(rings[0].getCoordinateSequence()) }
  26160. return this.getFactory().createMultiLineString(rings)
  26161. };
  26162. Polygon.prototype.clone = function clone () {
  26163. var this$1 = this;
  26164. var poly = Geometry$$1.prototype.clone.call(this);
  26165. poly._shell = this._shell.clone();
  26166. poly._holes = new Array(this._holes.length).fill(null);
  26167. for (var i = 0; i < this._holes.length; i++) {
  26168. poly._holes[i] = this$1._holes[i].clone();
  26169. }
  26170. return poly
  26171. };
  26172. Polygon.prototype.getGeometryType = function getGeometryType () {
  26173. return 'Polygon'
  26174. };
  26175. Polygon.prototype.copy = function copy () {
  26176. var this$1 = this;
  26177. var shell = this._shell.copy();
  26178. var holes = new Array(this._holes.length).fill(null);
  26179. for (var i = 0; i < holes.length; i++) {
  26180. holes[i] = this$1._holes[i].copy();
  26181. }
  26182. return new Polygon(shell, holes, this._factory)
  26183. };
  26184. Polygon.prototype.getExteriorRing = function getExteriorRing () {
  26185. return this._shell
  26186. };
  26187. Polygon.prototype.isEmpty = function isEmpty () {
  26188. return this._shell.isEmpty()
  26189. };
  26190. Polygon.prototype.getInteriorRingN = function getInteriorRingN (n) {
  26191. return this._holes[n]
  26192. };
  26193. Polygon.prototype.interfaces_ = function interfaces_ () {
  26194. return [Polygonal]
  26195. };
  26196. Polygon.prototype.getClass = function getClass () {
  26197. return Polygon
  26198. };
  26199. staticAccessors.serialVersionUID.get = function () { return -3494792200821764533 };
  26200. Object.defineProperties( Polygon, staticAccessors );
  26201. return Polygon;
  26202. }(Geometry));
  26203. var MultiPoint = (function (GeometryCollection$$1) {
  26204. function MultiPoint () {
  26205. GeometryCollection$$1.apply(this, arguments);
  26206. }
  26207. if ( GeometryCollection$$1 ) MultiPoint.__proto__ = GeometryCollection$$1;
  26208. MultiPoint.prototype = Object.create( GeometryCollection$$1 && GeometryCollection$$1.prototype );
  26209. MultiPoint.prototype.constructor = MultiPoint;
  26210. var staticAccessors = { serialVersionUID: { configurable: true } };
  26211. MultiPoint.prototype.getSortIndex = function getSortIndex () {
  26212. return Geometry.SORTINDEX_MULTIPOINT
  26213. };
  26214. MultiPoint.prototype.isValid = function isValid () {
  26215. return true
  26216. };
  26217. MultiPoint.prototype.equalsExact = function equalsExact () {
  26218. if (arguments.length === 2) {
  26219. var other = arguments[0];
  26220. var tolerance = arguments[1];
  26221. if (!this.isEquivalentClass(other)) {
  26222. return false
  26223. }
  26224. return GeometryCollection$$1.prototype.equalsExact.call(this, other, tolerance)
  26225. } else { return GeometryCollection$$1.prototype.equalsExact.apply(this, arguments) }
  26226. };
  26227. MultiPoint.prototype.getCoordinate = function getCoordinate () {
  26228. if (arguments.length === 1) {
  26229. var n = arguments[0];
  26230. return this._geometries[n].getCoordinate()
  26231. } else { return GeometryCollection$$1.prototype.getCoordinate.apply(this, arguments) }
  26232. };
  26233. MultiPoint.prototype.getBoundaryDimension = function getBoundaryDimension () {
  26234. return Dimension.FALSE
  26235. };
  26236. MultiPoint.prototype.getDimension = function getDimension () {
  26237. return 0
  26238. };
  26239. MultiPoint.prototype.getBoundary = function getBoundary () {
  26240. return this.getFactory().createGeometryCollection(null)
  26241. };
  26242. MultiPoint.prototype.getGeometryType = function getGeometryType () {
  26243. return 'MultiPoint'
  26244. };
  26245. MultiPoint.prototype.copy = function copy () {
  26246. var this$1 = this;
  26247. var points = new Array(this._geometries.length).fill(null);
  26248. for (var i = 0; i < points.length; i++) {
  26249. points[i] = this$1._geometries[i].copy();
  26250. }
  26251. return new MultiPoint(points, this._factory)
  26252. };
  26253. MultiPoint.prototype.interfaces_ = function interfaces_ () {
  26254. return [Puntal]
  26255. };
  26256. MultiPoint.prototype.getClass = function getClass () {
  26257. return MultiPoint
  26258. };
  26259. staticAccessors.serialVersionUID.get = function () { return -8048474874175355449 };
  26260. Object.defineProperties( MultiPoint, staticAccessors );
  26261. return MultiPoint;
  26262. }(GeometryCollection));
  26263. var LinearRing = (function (LineString$$1) {
  26264. function LinearRing (points, factory) {
  26265. if (points instanceof Coordinate && factory instanceof GeometryFactory) {
  26266. points = factory.getCoordinateSequenceFactory().create(points);
  26267. }
  26268. LineString$$1.call(this, points, factory);
  26269. this.validateConstruction();
  26270. }
  26271. if ( LineString$$1 ) LinearRing.__proto__ = LineString$$1;
  26272. LinearRing.prototype = Object.create( LineString$$1 && LineString$$1.prototype );
  26273. LinearRing.prototype.constructor = LinearRing;
  26274. var staticAccessors = { MINIMUM_VALID_SIZE: { configurable: true },serialVersionUID: { configurable: true } };
  26275. LinearRing.prototype.getSortIndex = function getSortIndex () {
  26276. return Geometry.SORTINDEX_LINEARRING
  26277. };
  26278. LinearRing.prototype.getBoundaryDimension = function getBoundaryDimension () {
  26279. return Dimension.FALSE
  26280. };
  26281. LinearRing.prototype.isClosed = function isClosed () {
  26282. if (this.isEmpty()) {
  26283. return true
  26284. }
  26285. return LineString$$1.prototype.isClosed.call(this)
  26286. };
  26287. LinearRing.prototype.reverse = function reverse () {
  26288. var seq = this._points.copy();
  26289. CoordinateSequences.reverse(seq);
  26290. var rev = this.getFactory().createLinearRing(seq);
  26291. return rev
  26292. };
  26293. LinearRing.prototype.validateConstruction = function validateConstruction () {
  26294. if (!this.isEmpty() && !LineString$$1.prototype.isClosed.call(this)) {
  26295. throw new IllegalArgumentException('Points of LinearRing do not form a closed linestring')
  26296. }
  26297. if (this.getCoordinateSequence().size() >= 1 && this.getCoordinateSequence().size() < LinearRing.MINIMUM_VALID_SIZE) {
  26298. throw new IllegalArgumentException('Invalid number of points in LinearRing (found ' + this.getCoordinateSequence().size() + ' - must be 0 or >= 4)')
  26299. }
  26300. };
  26301. LinearRing.prototype.getGeometryType = function getGeometryType () {
  26302. return 'LinearRing'
  26303. };
  26304. LinearRing.prototype.copy = function copy () {
  26305. return new LinearRing(this._points.copy(), this._factory)
  26306. };
  26307. LinearRing.prototype.interfaces_ = function interfaces_ () {
  26308. return []
  26309. };
  26310. LinearRing.prototype.getClass = function getClass () {
  26311. return LinearRing
  26312. };
  26313. staticAccessors.MINIMUM_VALID_SIZE.get = function () { return 4 };
  26314. staticAccessors.serialVersionUID.get = function () { return -4261142084085851829 };
  26315. Object.defineProperties( LinearRing, staticAccessors );
  26316. return LinearRing;
  26317. }(LineString$1));
  26318. var MultiPolygon = (function (GeometryCollection$$1) {
  26319. function MultiPolygon () {
  26320. GeometryCollection$$1.apply(this, arguments);
  26321. }
  26322. if ( GeometryCollection$$1 ) MultiPolygon.__proto__ = GeometryCollection$$1;
  26323. MultiPolygon.prototype = Object.create( GeometryCollection$$1 && GeometryCollection$$1.prototype );
  26324. MultiPolygon.prototype.constructor = MultiPolygon;
  26325. var staticAccessors = { serialVersionUID: { configurable: true } };
  26326. MultiPolygon.prototype.getSortIndex = function getSortIndex () {
  26327. return Geometry.SORTINDEX_MULTIPOLYGON
  26328. };
  26329. MultiPolygon.prototype.equalsExact = function equalsExact () {
  26330. if (arguments.length === 2) {
  26331. var other = arguments[0];
  26332. var tolerance = arguments[1];
  26333. if (!this.isEquivalentClass(other)) {
  26334. return false
  26335. }
  26336. return GeometryCollection$$1.prototype.equalsExact.call(this, other, tolerance)
  26337. } else { return GeometryCollection$$1.prototype.equalsExact.apply(this, arguments) }
  26338. };
  26339. MultiPolygon.prototype.getBoundaryDimension = function getBoundaryDimension () {
  26340. return 1
  26341. };
  26342. MultiPolygon.prototype.getDimension = function getDimension () {
  26343. return 2
  26344. };
  26345. MultiPolygon.prototype.reverse = function reverse () {
  26346. var this$1 = this;
  26347. var n = this._geometries.length;
  26348. var revGeoms = new Array(n).fill(null);
  26349. for (var i = 0; i < this._geometries.length; i++) {
  26350. revGeoms[i] = this$1._geometries[i].reverse();
  26351. }
  26352. return this.getFactory().createMultiPolygon(revGeoms)
  26353. };
  26354. MultiPolygon.prototype.getBoundary = function getBoundary () {
  26355. var this$1 = this;
  26356. if (this.isEmpty()) {
  26357. return this.getFactory().createMultiLineString()
  26358. }
  26359. var allRings = new ArrayList();
  26360. for (var i = 0; i < this._geometries.length; i++) {
  26361. var polygon = this$1._geometries[i];
  26362. var rings = polygon.getBoundary();
  26363. for (var j = 0; j < rings.getNumGeometries(); j++) {
  26364. allRings.add(rings.getGeometryN(j));
  26365. }
  26366. }
  26367. var allRingsArray = new Array(allRings.size()).fill(null);
  26368. return this.getFactory().createMultiLineString(allRings.toArray(allRingsArray))
  26369. };
  26370. MultiPolygon.prototype.getGeometryType = function getGeometryType () {
  26371. return 'MultiPolygon'
  26372. };
  26373. MultiPolygon.prototype.copy = function copy () {
  26374. var this$1 = this;
  26375. var polygons = new Array(this._geometries.length).fill(null);
  26376. for (var i = 0; i < polygons.length; i++) {
  26377. polygons[i] = this$1._geometries[i].copy();
  26378. }
  26379. return new MultiPolygon(polygons, this._factory)
  26380. };
  26381. MultiPolygon.prototype.interfaces_ = function interfaces_ () {
  26382. return [Polygonal]
  26383. };
  26384. MultiPolygon.prototype.getClass = function getClass () {
  26385. return MultiPolygon
  26386. };
  26387. staticAccessors.serialVersionUID.get = function () { return -551033529766975875 };
  26388. Object.defineProperties( MultiPolygon, staticAccessors );
  26389. return MultiPolygon;
  26390. }(GeometryCollection));
  26391. var GeometryEditor = function GeometryEditor (factory) {
  26392. this._factory = factory || null;
  26393. this._isUserDataCopied = false;
  26394. };
  26395. var staticAccessors$16 = { NoOpGeometryOperation: { configurable: true },CoordinateOperation: { configurable: true },CoordinateSequenceOperation: { configurable: true } };
  26396. GeometryEditor.prototype.setCopyUserData = function setCopyUserData (isUserDataCopied) {
  26397. this._isUserDataCopied = isUserDataCopied;
  26398. };
  26399. GeometryEditor.prototype.edit = function edit (geometry, operation) {
  26400. if (geometry === null) { return null }
  26401. var result = this.editInternal(geometry, operation);
  26402. if (this._isUserDataCopied) {
  26403. result.setUserData(geometry.getUserData());
  26404. }
  26405. return result
  26406. };
  26407. GeometryEditor.prototype.editInternal = function editInternal (geometry, operation) {
  26408. if (this._factory === null) { this._factory = geometry.getFactory(); }
  26409. if (geometry instanceof GeometryCollection) {
  26410. return this.editGeometryCollection(geometry, operation)
  26411. }
  26412. if (geometry instanceof Polygon) {
  26413. return this.editPolygon(geometry, operation)
  26414. }
  26415. if (geometry instanceof Point) {
  26416. return operation.edit(geometry, this._factory)
  26417. }
  26418. if (geometry instanceof LineString$1) {
  26419. return operation.edit(geometry, this._factory)
  26420. }
  26421. Assert.shouldNeverReachHere('Unsupported Geometry class: ' + geometry.getClass().getName());
  26422. return null
  26423. };
  26424. GeometryEditor.prototype.editGeometryCollection = function editGeometryCollection (collection, operation) {
  26425. var this$1 = this;
  26426. var collectionForType = operation.edit(collection, this._factory);
  26427. var geometries = new ArrayList();
  26428. for (var i = 0; i < collectionForType.getNumGeometries(); i++) {
  26429. var geometry = this$1.edit(collectionForType.getGeometryN(i), operation);
  26430. if (geometry === null || geometry.isEmpty()) {
  26431. continue
  26432. }
  26433. geometries.add(geometry);
  26434. }
  26435. if (collectionForType.getClass() === MultiPoint) {
  26436. return this._factory.createMultiPoint(geometries.toArray([]))
  26437. }
  26438. if (collectionForType.getClass() === MultiLineString) {
  26439. return this._factory.createMultiLineString(geometries.toArray([]))
  26440. }
  26441. if (collectionForType.getClass() === MultiPolygon) {
  26442. return this._factory.createMultiPolygon(geometries.toArray([]))
  26443. }
  26444. return this._factory.createGeometryCollection(geometries.toArray([]))
  26445. };
  26446. GeometryEditor.prototype.editPolygon = function editPolygon (polygon, operation) {
  26447. var this$1 = this;
  26448. var newPolygon = operation.edit(polygon, this._factory);
  26449. if (newPolygon === null) { newPolygon = this._factory.createPolygon(null); }
  26450. if (newPolygon.isEmpty()) {
  26451. return newPolygon
  26452. }
  26453. var shell = this.edit(newPolygon.getExteriorRing(), operation);
  26454. if (shell === null || shell.isEmpty()) {
  26455. return this._factory.createPolygon()
  26456. }
  26457. var holes = new ArrayList();
  26458. for (var i = 0; i < newPolygon.getNumInteriorRing(); i++) {
  26459. var hole = this$1.edit(newPolygon.getInteriorRingN(i), operation);
  26460. if (hole === null || hole.isEmpty()) {
  26461. continue
  26462. }
  26463. holes.add(hole);
  26464. }
  26465. return this._factory.createPolygon(shell, holes.toArray([]))
  26466. };
  26467. GeometryEditor.prototype.interfaces_ = function interfaces_ () {
  26468. return []
  26469. };
  26470. GeometryEditor.prototype.getClass = function getClass () {
  26471. return GeometryEditor
  26472. };
  26473. GeometryEditor.GeometryEditorOperation = function GeometryEditorOperation () {};
  26474. staticAccessors$16.NoOpGeometryOperation.get = function () { return NoOpGeometryOperation };
  26475. staticAccessors$16.CoordinateOperation.get = function () { return CoordinateOperation };
  26476. staticAccessors$16.CoordinateSequenceOperation.get = function () { return CoordinateSequenceOperation };
  26477. Object.defineProperties( GeometryEditor, staticAccessors$16 );
  26478. var NoOpGeometryOperation = function NoOpGeometryOperation () {};
  26479. NoOpGeometryOperation.prototype.edit = function edit (geometry, factory) {
  26480. return geometry
  26481. };
  26482. NoOpGeometryOperation.prototype.interfaces_ = function interfaces_ () {
  26483. return [GeometryEditor.GeometryEditorOperation]
  26484. };
  26485. NoOpGeometryOperation.prototype.getClass = function getClass () {
  26486. return NoOpGeometryOperation
  26487. };
  26488. var CoordinateOperation = function CoordinateOperation () {};
  26489. CoordinateOperation.prototype.edit = function edit (geometry, factory) {
  26490. var coords = this.editCoordinates(geometry.getCoordinates(), geometry);
  26491. if (coords === null) { return geometry }
  26492. if (geometry instanceof LinearRing) {
  26493. return factory.createLinearRing(coords)
  26494. }
  26495. if (geometry instanceof LineString$1) {
  26496. return factory.createLineString(coords)
  26497. }
  26498. if (geometry instanceof Point) {
  26499. if (coords.length > 0) {
  26500. return factory.createPoint(coords[0])
  26501. } else {
  26502. return factory.createPoint()
  26503. }
  26504. }
  26505. return geometry
  26506. };
  26507. CoordinateOperation.prototype.interfaces_ = function interfaces_ () {
  26508. return [GeometryEditor.GeometryEditorOperation]
  26509. };
  26510. CoordinateOperation.prototype.getClass = function getClass () {
  26511. return CoordinateOperation
  26512. };
  26513. var CoordinateSequenceOperation = function CoordinateSequenceOperation () {};
  26514. CoordinateSequenceOperation.prototype.edit = function edit (geometry, factory) {
  26515. if (geometry instanceof LinearRing) {
  26516. return factory.createLinearRing(this.edit(geometry.getCoordinateSequence(), geometry))
  26517. }
  26518. if (geometry instanceof LineString$1) {
  26519. return factory.createLineString(this.edit(geometry.getCoordinateSequence(), geometry))
  26520. }
  26521. if (geometry instanceof Point) {
  26522. return factory.createPoint(this.edit(geometry.getCoordinateSequence(), geometry))
  26523. }
  26524. return geometry
  26525. };
  26526. CoordinateSequenceOperation.prototype.interfaces_ = function interfaces_ () {
  26527. return [GeometryEditor.GeometryEditorOperation]
  26528. };
  26529. CoordinateSequenceOperation.prototype.getClass = function getClass () {
  26530. return CoordinateSequenceOperation
  26531. };
  26532. var CoordinateArraySequence = function CoordinateArraySequence () {
  26533. var this$1 = this;
  26534. this._dimension = 3;
  26535. this._coordinates = null;
  26536. if (arguments.length === 1) {
  26537. if (arguments[0] instanceof Array) {
  26538. this._coordinates = arguments[0];
  26539. this._dimension = 3;
  26540. } else if (Number.isInteger(arguments[0])) {
  26541. var size = arguments[0];
  26542. this._coordinates = new Array(size).fill(null);
  26543. for (var i = 0; i < size; i++) {
  26544. this$1._coordinates[i] = new Coordinate();
  26545. }
  26546. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  26547. var coordSeq = arguments[0];
  26548. if (coordSeq === null) {
  26549. this._coordinates = new Array(0).fill(null);
  26550. return null
  26551. }
  26552. this._dimension = coordSeq.getDimension();
  26553. this._coordinates = new Array(coordSeq.size()).fill(null);
  26554. for (var i$1 = 0; i$1 < this._coordinates.length; i$1++) {
  26555. this$1._coordinates[i$1] = coordSeq.getCoordinateCopy(i$1);
  26556. }
  26557. }
  26558. } else if (arguments.length === 2) {
  26559. if (arguments[0] instanceof Array && Number.isInteger(arguments[1])) {
  26560. var coordinates = arguments[0];
  26561. var dimension = arguments[1];
  26562. this._coordinates = coordinates;
  26563. this._dimension = dimension;
  26564. if (coordinates === null) { this._coordinates = new Array(0).fill(null); }
  26565. } else if (Number.isInteger(arguments[0]) && Number.isInteger(arguments[1])) {
  26566. var size$1 = arguments[0];
  26567. var dimension$1 = arguments[1];
  26568. this._coordinates = new Array(size$1).fill(null);
  26569. this._dimension = dimension$1;
  26570. for (var i$2 = 0; i$2 < size$1; i$2++) {
  26571. this$1._coordinates[i$2] = new Coordinate();
  26572. }
  26573. }
  26574. }
  26575. };
  26576. var staticAccessors$18 = { serialVersionUID: { configurable: true } };
  26577. CoordinateArraySequence.prototype.setOrdinate = function setOrdinate (index, ordinateIndex, value) {
  26578. switch (ordinateIndex) {
  26579. case CoordinateSequence.X:
  26580. this._coordinates[index].x = value;
  26581. break
  26582. case CoordinateSequence.Y:
  26583. this._coordinates[index].y = value;
  26584. break
  26585. case CoordinateSequence.Z:
  26586. this._coordinates[index].z = value;
  26587. break
  26588. default:
  26589. throw new IllegalArgumentException('invalid ordinateIndex')
  26590. }
  26591. };
  26592. CoordinateArraySequence.prototype.size = function size () {
  26593. return this._coordinates.length
  26594. };
  26595. CoordinateArraySequence.prototype.getOrdinate = function getOrdinate (index, ordinateIndex) {
  26596. switch (ordinateIndex) {
  26597. case CoordinateSequence.X:
  26598. return this._coordinates[index].x
  26599. case CoordinateSequence.Y:
  26600. return this._coordinates[index].y
  26601. case CoordinateSequence.Z:
  26602. return this._coordinates[index].z
  26603. default:
  26604. }
  26605. return Double.NaN
  26606. };
  26607. CoordinateArraySequence.prototype.getCoordinate = function getCoordinate () {
  26608. if (arguments.length === 1) {
  26609. var i = arguments[0];
  26610. return this._coordinates[i]
  26611. } else if (arguments.length === 2) {
  26612. var index = arguments[0];
  26613. var coord = arguments[1];
  26614. coord.x = this._coordinates[index].x;
  26615. coord.y = this._coordinates[index].y;
  26616. coord.z = this._coordinates[index].z;
  26617. }
  26618. };
  26619. CoordinateArraySequence.prototype.getCoordinateCopy = function getCoordinateCopy (i) {
  26620. return new Coordinate(this._coordinates[i])
  26621. };
  26622. CoordinateArraySequence.prototype.getDimension = function getDimension () {
  26623. return this._dimension
  26624. };
  26625. CoordinateArraySequence.prototype.getX = function getX (index) {
  26626. return this._coordinates[index].x
  26627. };
  26628. CoordinateArraySequence.prototype.clone = function clone () {
  26629. var this$1 = this;
  26630. var cloneCoordinates = new Array(this.size()).fill(null);
  26631. for (var i = 0; i < this._coordinates.length; i++) {
  26632. cloneCoordinates[i] = this$1._coordinates[i].clone();
  26633. }
  26634. return new CoordinateArraySequence(cloneCoordinates, this._dimension)
  26635. };
  26636. CoordinateArraySequence.prototype.expandEnvelope = function expandEnvelope (env) {
  26637. var this$1 = this;
  26638. for (var i = 0; i < this._coordinates.length; i++) {
  26639. env.expandToInclude(this$1._coordinates[i]);
  26640. }
  26641. return env
  26642. };
  26643. CoordinateArraySequence.prototype.copy = function copy () {
  26644. var this$1 = this;
  26645. var cloneCoordinates = new Array(this.size()).fill(null);
  26646. for (var i = 0; i < this._coordinates.length; i++) {
  26647. cloneCoordinates[i] = this$1._coordinates[i].copy();
  26648. }
  26649. return new CoordinateArraySequence(cloneCoordinates, this._dimension)
  26650. };
  26651. CoordinateArraySequence.prototype.toString = function toString () {
  26652. var this$1 = this;
  26653. if (this._coordinates.length > 0) {
  26654. var strBuf = new StringBuffer(17 * this._coordinates.length);
  26655. strBuf.append('(');
  26656. strBuf.append(this._coordinates[0]);
  26657. for (var i = 1; i < this._coordinates.length; i++) {
  26658. strBuf.append(', ');
  26659. strBuf.append(this$1._coordinates[i]);
  26660. }
  26661. strBuf.append(')');
  26662. return strBuf.toString()
  26663. } else {
  26664. return '()'
  26665. }
  26666. };
  26667. CoordinateArraySequence.prototype.getY = function getY (index) {
  26668. return this._coordinates[index].y
  26669. };
  26670. CoordinateArraySequence.prototype.toCoordinateArray = function toCoordinateArray () {
  26671. return this._coordinates
  26672. };
  26673. CoordinateArraySequence.prototype.interfaces_ = function interfaces_ () {
  26674. return [CoordinateSequence, Serializable]
  26675. };
  26676. CoordinateArraySequence.prototype.getClass = function getClass () {
  26677. return CoordinateArraySequence
  26678. };
  26679. staticAccessors$18.serialVersionUID.get = function () { return -915438501601840650 };
  26680. Object.defineProperties( CoordinateArraySequence, staticAccessors$18 );
  26681. var CoordinateArraySequenceFactory = function CoordinateArraySequenceFactory () {};
  26682. var staticAccessors$17 = { serialVersionUID: { configurable: true },instanceObject: { configurable: true } };
  26683. CoordinateArraySequenceFactory.prototype.readResolve = function readResolve () {
  26684. return CoordinateArraySequenceFactory.instance()
  26685. };
  26686. CoordinateArraySequenceFactory.prototype.create = function create () {
  26687. if (arguments.length === 1) {
  26688. if (arguments[0] instanceof Array) {
  26689. var coordinates = arguments[0];
  26690. return new CoordinateArraySequence(coordinates)
  26691. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  26692. var coordSeq = arguments[0];
  26693. return new CoordinateArraySequence(coordSeq)
  26694. }
  26695. } else if (arguments.length === 2) {
  26696. var size = arguments[0];
  26697. var dimension = arguments[1];
  26698. if (dimension > 3) { dimension = 3; }
  26699. if (dimension < 2) { return new CoordinateArraySequence(size) }
  26700. return new CoordinateArraySequence(size, dimension)
  26701. }
  26702. };
  26703. CoordinateArraySequenceFactory.prototype.interfaces_ = function interfaces_ () {
  26704. return [CoordinateSequenceFactory, Serializable]
  26705. };
  26706. CoordinateArraySequenceFactory.prototype.getClass = function getClass () {
  26707. return CoordinateArraySequenceFactory
  26708. };
  26709. CoordinateArraySequenceFactory.instance = function instance () {
  26710. return CoordinateArraySequenceFactory.instanceObject
  26711. };
  26712. staticAccessors$17.serialVersionUID.get = function () { return -4099577099607551657 };
  26713. staticAccessors$17.instanceObject.get = function () { return new CoordinateArraySequenceFactory() };
  26714. Object.defineProperties( CoordinateArraySequenceFactory, staticAccessors$17 );
  26715. /**
  26716. * @see http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html
  26717. *
  26718. * @extends {javascript.util.Map}
  26719. * @constructor
  26720. * @private
  26721. */
  26722. var HashMap = (function (MapInterface) {
  26723. function HashMap () {
  26724. MapInterface.call(this);
  26725. this.map_ = new Map();
  26726. }
  26727. if ( MapInterface ) HashMap.__proto__ = MapInterface;
  26728. HashMap.prototype = Object.create( MapInterface && MapInterface.prototype );
  26729. HashMap.prototype.constructor = HashMap;
  26730. /**
  26731. * @override
  26732. */
  26733. HashMap.prototype.get = function get (key) {
  26734. return this.map_.get(key) || null
  26735. };
  26736. /**
  26737. * @override
  26738. */
  26739. HashMap.prototype.put = function put (key, value) {
  26740. this.map_.set(key, value);
  26741. return value
  26742. };
  26743. /**
  26744. * @override
  26745. */
  26746. HashMap.prototype.values = function values () {
  26747. var arrayList = new ArrayList();
  26748. var it = this.map_.values();
  26749. var o = it.next();
  26750. while (!o.done) {
  26751. arrayList.add(o.value);
  26752. o = it.next();
  26753. }
  26754. return arrayList
  26755. };
  26756. /**
  26757. * @override
  26758. */
  26759. HashMap.prototype.entrySet = function entrySet () {
  26760. var hashSet = new HashSet();
  26761. this.map_.entries().forEach(function (entry) { return hashSet.add(entry); });
  26762. return hashSet
  26763. };
  26764. /**
  26765. * @override
  26766. */
  26767. HashMap.prototype.size = function size () {
  26768. return this.map_.size()
  26769. };
  26770. return HashMap;
  26771. }(Map$1));
  26772. var PrecisionModel = function PrecisionModel () {
  26773. this._modelType = null;
  26774. this._scale = null;
  26775. if (arguments.length === 0) {
  26776. this._modelType = PrecisionModel.FLOATING;
  26777. } else if (arguments.length === 1) {
  26778. if (arguments[0] instanceof Type) {
  26779. var modelType = arguments[0];
  26780. this._modelType = modelType;
  26781. if (modelType === PrecisionModel.FIXED) {
  26782. this.setScale(1.0);
  26783. }
  26784. } else if (typeof arguments[0] === 'number') {
  26785. var scale = arguments[0];
  26786. this._modelType = PrecisionModel.FIXED;
  26787. this.setScale(scale);
  26788. } else if (arguments[0] instanceof PrecisionModel) {
  26789. var pm = arguments[0];
  26790. this._modelType = pm._modelType;
  26791. this._scale = pm._scale;
  26792. }
  26793. }
  26794. };
  26795. var staticAccessors$19 = { serialVersionUID: { configurable: true },maximumPreciseValue: { configurable: true } };
  26796. PrecisionModel.prototype.equals = function equals (other) {
  26797. if (!(other instanceof PrecisionModel)) {
  26798. return false
  26799. }
  26800. var otherPrecisionModel = other;
  26801. return this._modelType === otherPrecisionModel._modelType && this._scale === otherPrecisionModel._scale
  26802. };
  26803. PrecisionModel.prototype.compareTo = function compareTo (o) {
  26804. var other = o;
  26805. var sigDigits = this.getMaximumSignificantDigits();
  26806. var otherSigDigits = other.getMaximumSignificantDigits();
  26807. return new Integer(sigDigits).compareTo(new Integer(otherSigDigits))
  26808. };
  26809. PrecisionModel.prototype.getScale = function getScale () {
  26810. return this._scale
  26811. };
  26812. PrecisionModel.prototype.isFloating = function isFloating () {
  26813. return this._modelType === PrecisionModel.FLOATING || this._modelType === PrecisionModel.FLOATING_SINGLE
  26814. };
  26815. PrecisionModel.prototype.getType = function getType () {
  26816. return this._modelType
  26817. };
  26818. PrecisionModel.prototype.toString = function toString () {
  26819. var description = 'UNKNOWN';
  26820. if (this._modelType === PrecisionModel.FLOATING) {
  26821. description = 'Floating';
  26822. } else if (this._modelType === PrecisionModel.FLOATING_SINGLE) {
  26823. description = 'Floating-Single';
  26824. } else if (this._modelType === PrecisionModel.FIXED) {
  26825. description = 'Fixed (Scale=' + this.getScale() + ')';
  26826. }
  26827. return description
  26828. };
  26829. PrecisionModel.prototype.makePrecise = function makePrecise () {
  26830. if (typeof arguments[0] === 'number') {
  26831. var val = arguments[0];
  26832. if (Double.isNaN(val)) { return val }
  26833. if (this._modelType === PrecisionModel.FLOATING_SINGLE) {
  26834. var floatSingleVal = val;
  26835. return floatSingleVal
  26836. }
  26837. if (this._modelType === PrecisionModel.FIXED) {
  26838. return Math.round(val * this._scale) / this._scale
  26839. }
  26840. return val
  26841. } else if (arguments[0] instanceof Coordinate) {
  26842. var coord = arguments[0];
  26843. if (this._modelType === PrecisionModel.FLOATING) { return null }
  26844. coord.x = this.makePrecise(coord.x);
  26845. coord.y = this.makePrecise(coord.y);
  26846. }
  26847. };
  26848. PrecisionModel.prototype.getMaximumSignificantDigits = function getMaximumSignificantDigits () {
  26849. var maxSigDigits = 16;
  26850. if (this._modelType === PrecisionModel.FLOATING) {
  26851. maxSigDigits = 16;
  26852. } else if (this._modelType === PrecisionModel.FLOATING_SINGLE) {
  26853. maxSigDigits = 6;
  26854. } else if (this._modelType === PrecisionModel.FIXED) {
  26855. maxSigDigits = 1 + Math.trunc(Math.ceil(Math.log(this.getScale()) / Math.log(10)));
  26856. }
  26857. return maxSigDigits
  26858. };
  26859. PrecisionModel.prototype.setScale = function setScale (scale) {
  26860. this._scale = Math.abs(scale);
  26861. };
  26862. PrecisionModel.prototype.interfaces_ = function interfaces_ () {
  26863. return [Serializable, Comparable]
  26864. };
  26865. PrecisionModel.prototype.getClass = function getClass () {
  26866. return PrecisionModel
  26867. };
  26868. PrecisionModel.mostPrecise = function mostPrecise (pm1, pm2) {
  26869. if (pm1.compareTo(pm2) >= 0) { return pm1 }
  26870. return pm2
  26871. };
  26872. staticAccessors$19.serialVersionUID.get = function () { return 7777263578777803835 };
  26873. staticAccessors$19.maximumPreciseValue.get = function () { return 9007199254740992.0 };
  26874. Object.defineProperties( PrecisionModel, staticAccessors$19 );
  26875. var Type = function Type (name) {
  26876. this._name = name || null;
  26877. Type.nameToTypeMap.put(name, this);
  26878. };
  26879. var staticAccessors$1$1 = { serialVersionUID: { configurable: true },nameToTypeMap: { configurable: true } };
  26880. Type.prototype.readResolve = function readResolve () {
  26881. return Type.nameToTypeMap.get(this._name)
  26882. };
  26883. Type.prototype.toString = function toString () {
  26884. return this._name
  26885. };
  26886. Type.prototype.interfaces_ = function interfaces_ () {
  26887. return [Serializable]
  26888. };
  26889. Type.prototype.getClass = function getClass () {
  26890. return Type
  26891. };
  26892. staticAccessors$1$1.serialVersionUID.get = function () { return -5528602631731589822 };
  26893. staticAccessors$1$1.nameToTypeMap.get = function () { return new HashMap() };
  26894. Object.defineProperties( Type, staticAccessors$1$1 );
  26895. PrecisionModel.Type = Type;
  26896. PrecisionModel.FIXED = new Type('FIXED');
  26897. PrecisionModel.FLOATING = new Type('FLOATING');
  26898. PrecisionModel.FLOATING_SINGLE = new Type('FLOATING SINGLE');
  26899. var GeometryFactory = function GeometryFactory () {
  26900. this._precisionModel = new PrecisionModel();
  26901. this._SRID = 0;
  26902. this._coordinateSequenceFactory = GeometryFactory.getDefaultCoordinateSequenceFactory();
  26903. if (arguments.length === 0) {
  26904. } else if (arguments.length === 1) {
  26905. if (hasInterface(arguments[0], CoordinateSequenceFactory)) {
  26906. this._coordinateSequenceFactory = arguments[0];
  26907. } else if (arguments[0] instanceof PrecisionModel) {
  26908. this._precisionModel = arguments[0];
  26909. }
  26910. } else if (arguments.length === 2) {
  26911. this._precisionModel = arguments[0];
  26912. this._SRID = arguments[1];
  26913. } else if (arguments.length === 3) {
  26914. this._precisionModel = arguments[0];
  26915. this._SRID = arguments[1];
  26916. this._coordinateSequenceFactory = arguments[2];
  26917. }
  26918. };
  26919. var staticAccessors$2 = { serialVersionUID: { configurable: true } };
  26920. GeometryFactory.prototype.toGeometry = function toGeometry (envelope) {
  26921. if (envelope.isNull()) {
  26922. return this.createPoint(null)
  26923. }
  26924. if (envelope.getMinX() === envelope.getMaxX() && envelope.getMinY() === envelope.getMaxY()) {
  26925. return this.createPoint(new Coordinate(envelope.getMinX(), envelope.getMinY()))
  26926. }
  26927. if (envelope.getMinX() === envelope.getMaxX() || envelope.getMinY() === envelope.getMaxY()) {
  26928. return this.createLineString([new Coordinate(envelope.getMinX(), envelope.getMinY()), new Coordinate(envelope.getMaxX(), envelope.getMaxY())])
  26929. }
  26930. return this.createPolygon(this.createLinearRing([new Coordinate(envelope.getMinX(), envelope.getMinY()), new Coordinate(envelope.getMinX(), envelope.getMaxY()), new Coordinate(envelope.getMaxX(), envelope.getMaxY()), new Coordinate(envelope.getMaxX(), envelope.getMinY()), new Coordinate(envelope.getMinX(), envelope.getMinY())]), null)
  26931. };
  26932. GeometryFactory.prototype.createLineString = function createLineString (coordinates) {
  26933. if (!coordinates) { return new LineString$1(this.getCoordinateSequenceFactory().create([]), this) }
  26934. else if (coordinates instanceof Array) { return new LineString$1(this.getCoordinateSequenceFactory().create(coordinates), this) }
  26935. else if (hasInterface(coordinates, CoordinateSequence)) { return new LineString$1(coordinates, this) }
  26936. };
  26937. GeometryFactory.prototype.createMultiLineString = function createMultiLineString () {
  26938. if (arguments.length === 0) {
  26939. return new MultiLineString(null, this)
  26940. } else if (arguments.length === 1) {
  26941. var lineStrings = arguments[0];
  26942. return new MultiLineString(lineStrings, this)
  26943. }
  26944. };
  26945. GeometryFactory.prototype.buildGeometry = function buildGeometry (geomList) {
  26946. var geomClass = null;
  26947. var isHeterogeneous = false;
  26948. var hasGeometryCollection = false;
  26949. for (var i = geomList.iterator(); i.hasNext();) {
  26950. var geom = i.next();
  26951. var partClass = geom.getClass();
  26952. if (geomClass === null) {
  26953. geomClass = partClass;
  26954. }
  26955. if (partClass !== geomClass) {
  26956. isHeterogeneous = true;
  26957. }
  26958. if (geom.isGeometryCollectionOrDerived()) { hasGeometryCollection = true; }
  26959. }
  26960. if (geomClass === null) {
  26961. return this.createGeometryCollection()
  26962. }
  26963. if (isHeterogeneous || hasGeometryCollection) {
  26964. return this.createGeometryCollection(GeometryFactory.toGeometryArray(geomList))
  26965. }
  26966. var geom0 = geomList.iterator().next();
  26967. var isCollection = geomList.size() > 1;
  26968. if (isCollection) {
  26969. if (geom0 instanceof Polygon) {
  26970. return this.createMultiPolygon(GeometryFactory.toPolygonArray(geomList))
  26971. } else if (geom0 instanceof LineString$1) {
  26972. return this.createMultiLineString(GeometryFactory.toLineStringArray(geomList))
  26973. } else if (geom0 instanceof Point) {
  26974. return this.createMultiPoint(GeometryFactory.toPointArray(geomList))
  26975. }
  26976. Assert.shouldNeverReachHere('Unhandled class: ' + geom0.getClass().getName());
  26977. }
  26978. return geom0
  26979. };
  26980. GeometryFactory.prototype.createMultiPointFromCoords = function createMultiPointFromCoords (coordinates) {
  26981. return this.createMultiPoint(coordinates !== null ? this.getCoordinateSequenceFactory().create(coordinates) : null)
  26982. };
  26983. GeometryFactory.prototype.createPoint = function createPoint () {
  26984. if (arguments.length === 0) {
  26985. return this.createPoint(this.getCoordinateSequenceFactory().create([]))
  26986. } else if (arguments.length === 1) {
  26987. if (arguments[0] instanceof Coordinate) {
  26988. var coordinate = arguments[0];
  26989. return this.createPoint(coordinate !== null ? this.getCoordinateSequenceFactory().create([coordinate]) : null)
  26990. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  26991. var coordinates = arguments[0];
  26992. return new Point(coordinates, this)
  26993. }
  26994. }
  26995. };
  26996. GeometryFactory.prototype.getCoordinateSequenceFactory = function getCoordinateSequenceFactory () {
  26997. return this._coordinateSequenceFactory
  26998. };
  26999. GeometryFactory.prototype.createPolygon = function createPolygon () {
  27000. if (arguments.length === 0) {
  27001. return new Polygon(null, null, this)
  27002. } else if (arguments.length === 1) {
  27003. if (hasInterface(arguments[0], CoordinateSequence)) {
  27004. var coordinates = arguments[0];
  27005. return this.createPolygon(this.createLinearRing(coordinates))
  27006. } else if (arguments[0] instanceof Array) {
  27007. var coordinates$1 = arguments[0];
  27008. return this.createPolygon(this.createLinearRing(coordinates$1))
  27009. } else if (arguments[0] instanceof LinearRing) {
  27010. var shell = arguments[0];
  27011. return this.createPolygon(shell, null)
  27012. }
  27013. } else if (arguments.length === 2) {
  27014. var shell$1 = arguments[0];
  27015. var holes = arguments[1];
  27016. return new Polygon(shell$1, holes, this)
  27017. }
  27018. };
  27019. GeometryFactory.prototype.getSRID = function getSRID () {
  27020. return this._SRID
  27021. };
  27022. GeometryFactory.prototype.createGeometryCollection = function createGeometryCollection () {
  27023. if (arguments.length === 0) {
  27024. return new GeometryCollection(null, this)
  27025. } else if (arguments.length === 1) {
  27026. var geometries = arguments[0];
  27027. return new GeometryCollection(geometries, this)
  27028. }
  27029. };
  27030. GeometryFactory.prototype.createGeometry = function createGeometry (g) {
  27031. var editor = new GeometryEditor(this);
  27032. return editor.edit(g, {
  27033. edit: function () {
  27034. if (arguments.length === 2) {
  27035. var coordSeq = arguments[0];
  27036. // const geometry = arguments[1]
  27037. return this._coordinateSequenceFactory.create(coordSeq)
  27038. }
  27039. }
  27040. })
  27041. };
  27042. GeometryFactory.prototype.getPrecisionModel = function getPrecisionModel () {
  27043. return this._precisionModel
  27044. };
  27045. GeometryFactory.prototype.createLinearRing = function createLinearRing () {
  27046. if (arguments.length === 0) {
  27047. return this.createLinearRing(this.getCoordinateSequenceFactory().create([]))
  27048. } else if (arguments.length === 1) {
  27049. if (arguments[0] instanceof Array) {
  27050. var coordinates = arguments[0];
  27051. return this.createLinearRing(coordinates !== null ? this.getCoordinateSequenceFactory().create(coordinates) : null)
  27052. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  27053. var coordinates$1 = arguments[0];
  27054. return new LinearRing(coordinates$1, this)
  27055. }
  27056. }
  27057. };
  27058. GeometryFactory.prototype.createMultiPolygon = function createMultiPolygon () {
  27059. if (arguments.length === 0) {
  27060. return new MultiPolygon(null, this)
  27061. } else if (arguments.length === 1) {
  27062. var polygons = arguments[0];
  27063. return new MultiPolygon(polygons, this)
  27064. }
  27065. };
  27066. GeometryFactory.prototype.createMultiPoint = function createMultiPoint () {
  27067. var this$1 = this;
  27068. if (arguments.length === 0) {
  27069. return new MultiPoint(null, this)
  27070. } else if (arguments.length === 1) {
  27071. if (arguments[0] instanceof Array) {
  27072. var point = arguments[0];
  27073. return new MultiPoint(point, this)
  27074. } else if (arguments[0] instanceof Array) {
  27075. var coordinates = arguments[0];
  27076. return this.createMultiPoint(coordinates !== null ? this.getCoordinateSequenceFactory().create(coordinates) : null)
  27077. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  27078. var coordinates$1 = arguments[0];
  27079. if (coordinates$1 === null) {
  27080. return this.createMultiPoint(new Array(0).fill(null))
  27081. }
  27082. var points = new Array(coordinates$1.size()).fill(null);
  27083. for (var i = 0; i < coordinates$1.size(); i++) {
  27084. var ptSeq = this$1.getCoordinateSequenceFactory().create(1, coordinates$1.getDimension());
  27085. CoordinateSequences.copy(coordinates$1, i, ptSeq, 0, 1);
  27086. points[i] = this$1.createPoint(ptSeq);
  27087. }
  27088. return this.createMultiPoint(points)
  27089. }
  27090. }
  27091. };
  27092. GeometryFactory.prototype.interfaces_ = function interfaces_ () {
  27093. return [Serializable]
  27094. };
  27095. GeometryFactory.prototype.getClass = function getClass () {
  27096. return GeometryFactory
  27097. };
  27098. GeometryFactory.toMultiPolygonArray = function toMultiPolygonArray (multiPolygons) {
  27099. var multiPolygonArray = new Array(multiPolygons.size()).fill(null);
  27100. return multiPolygons.toArray(multiPolygonArray)
  27101. };
  27102. GeometryFactory.toGeometryArray = function toGeometryArray (geometries) {
  27103. if (geometries === null) { return null }
  27104. var geometryArray = new Array(geometries.size()).fill(null);
  27105. return geometries.toArray(geometryArray)
  27106. };
  27107. GeometryFactory.getDefaultCoordinateSequenceFactory = function getDefaultCoordinateSequenceFactory () {
  27108. return CoordinateArraySequenceFactory.instance()
  27109. };
  27110. GeometryFactory.toMultiLineStringArray = function toMultiLineStringArray (multiLineStrings) {
  27111. var multiLineStringArray = new Array(multiLineStrings.size()).fill(null);
  27112. return multiLineStrings.toArray(multiLineStringArray)
  27113. };
  27114. GeometryFactory.toLineStringArray = function toLineStringArray (lineStrings) {
  27115. var lineStringArray = new Array(lineStrings.size()).fill(null);
  27116. return lineStrings.toArray(lineStringArray)
  27117. };
  27118. GeometryFactory.toMultiPointArray = function toMultiPointArray (multiPoints) {
  27119. var multiPointArray = new Array(multiPoints.size()).fill(null);
  27120. return multiPoints.toArray(multiPointArray)
  27121. };
  27122. GeometryFactory.toLinearRingArray = function toLinearRingArray (linearRings) {
  27123. var linearRingArray = new Array(linearRings.size()).fill(null);
  27124. return linearRings.toArray(linearRingArray)
  27125. };
  27126. GeometryFactory.toPointArray = function toPointArray (points) {
  27127. var pointArray = new Array(points.size()).fill(null);
  27128. return points.toArray(pointArray)
  27129. };
  27130. GeometryFactory.toPolygonArray = function toPolygonArray (polygons) {
  27131. var polygonArray = new Array(polygons.size()).fill(null);
  27132. return polygons.toArray(polygonArray)
  27133. };
  27134. GeometryFactory.createPointFromInternalCoord = function createPointFromInternalCoord (coord, exemplar) {
  27135. exemplar.getPrecisionModel().makePrecise(coord);
  27136. return exemplar.getFactory().createPoint(coord)
  27137. };
  27138. staticAccessors$2.serialVersionUID.get = function () { return -6820524753094095635 };
  27139. Object.defineProperties( GeometryFactory, staticAccessors$2 );
  27140. var geometryTypes = ['Point', 'MultiPoint', 'LineString', 'MultiLineString', 'Polygon', 'MultiPolygon'];
  27141. /**
  27142. * Class for reading and writing Well-Known Text.Create a new parser for GeoJSON
  27143. * NOTE: Adapted from OpenLayers 2.11 implementation.
  27144. */
  27145. /**
  27146. * Create a new parser for GeoJSON
  27147. *
  27148. * @param {GeometryFactory} geometryFactory
  27149. * @return An instance of GeoJsonParser.
  27150. * @constructor
  27151. * @private
  27152. */
  27153. var GeoJSONParser = function GeoJSONParser (geometryFactory) {
  27154. this.geometryFactory = geometryFactory || new GeometryFactory();
  27155. };
  27156. /**
  27157. * Deserialize a GeoJSON object and return the Geometry or Feature(Collection) with JSTS Geometries
  27158. *
  27159. * @param {}
  27160. * A GeoJSON object.
  27161. * @return {} A Geometry instance or object representing a Feature(Collection) with Geometry instances.
  27162. * @private
  27163. */
  27164. GeoJSONParser.prototype.read = function read (json) {
  27165. var obj;
  27166. if (typeof json === 'string') {
  27167. obj = JSON.parse(json);
  27168. } else {
  27169. obj = json;
  27170. }
  27171. var type = obj.type;
  27172. if (!parse[type]) {
  27173. throw new Error('Unknown GeoJSON type: ' + obj.type)
  27174. }
  27175. if (geometryTypes.indexOf(type) !== -1) {
  27176. return parse[type].apply(this, [obj.coordinates])
  27177. } else if (type === 'GeometryCollection') {
  27178. return parse[type].apply(this, [obj.geometries])
  27179. }
  27180. // feature or feature collection
  27181. return parse[type].apply(this, [obj])
  27182. };
  27183. /**
  27184. * Serialize a Geometry object into GeoJSON
  27185. *
  27186. * @param {Geometry}
  27187. * geometry A Geometry or array of Geometries.
  27188. * @return {Object} A GeoJSON object represting the input Geometry/Geometries.
  27189. * @private
  27190. */
  27191. GeoJSONParser.prototype.write = function write (geometry) {
  27192. var type = geometry.getGeometryType();
  27193. if (!extract$1$1[type]) {
  27194. throw new Error('Geometry is not supported')
  27195. }
  27196. return extract$1$1[type].apply(this, [geometry])
  27197. };
  27198. var parse = {
  27199. /**
  27200. * Parse a GeoJSON Feature object
  27201. *
  27202. * @param {Object}
  27203. * obj Object to parse.
  27204. *
  27205. * @return {Object} Feature with geometry/bbox converted to JSTS Geometries.
  27206. */
  27207. Feature: function (obj) {
  27208. var feature = {};
  27209. // copy features
  27210. for (var key in obj) {
  27211. feature[key] = obj[key];
  27212. }
  27213. // parse geometry
  27214. if (obj.geometry) {
  27215. var type = obj.geometry.type;
  27216. if (!parse[type]) {
  27217. throw new Error('Unknown GeoJSON type: ' + obj.type)
  27218. }
  27219. feature.geometry = this.read(obj.geometry);
  27220. }
  27221. // bbox
  27222. if (obj.bbox) {
  27223. feature.bbox = parse.bbox.apply(this, [obj.bbox]);
  27224. }
  27225. return feature
  27226. },
  27227. /**
  27228. * Parse a GeoJSON FeatureCollection object
  27229. *
  27230. * @param {Object}
  27231. * obj Object to parse.
  27232. *
  27233. * @return {Object} FeatureCollection with geometry/bbox converted to JSTS Geometries.
  27234. */
  27235. FeatureCollection: function (obj) {
  27236. var this$1 = this;
  27237. var featureCollection = {};
  27238. if (obj.features) {
  27239. featureCollection.features = [];
  27240. for (var i = 0; i < obj.features.length; ++i) {
  27241. featureCollection.features.push(this$1.read(obj.features[i]));
  27242. }
  27243. }
  27244. if (obj.bbox) {
  27245. featureCollection.bbox = this.parse.bbox.apply(this, [obj.bbox]);
  27246. }
  27247. return featureCollection
  27248. },
  27249. /**
  27250. * Convert the ordinates in an array to an array of Coordinates
  27251. *
  27252. * @param {Array}
  27253. * array Array with {Number}s.
  27254. *
  27255. * @return {Array} Array with Coordinates.
  27256. */
  27257. coordinates: function (array) {
  27258. var coordinates = [];
  27259. for (var i = 0; i < array.length; ++i) {
  27260. var sub = array[i];
  27261. coordinates.push(new Coordinate(sub[0], sub[1]));
  27262. }
  27263. return coordinates
  27264. },
  27265. /**
  27266. * Convert the bbox to a LinearRing
  27267. *
  27268. * @param {Array}
  27269. * array Array with [xMin, yMin, xMax, yMax].
  27270. *
  27271. * @return {Array} Array with Coordinates.
  27272. */
  27273. bbox: function (array) {
  27274. return this.geometryFactory.createLinearRing([
  27275. new Coordinate(array[0], array[1]),
  27276. new Coordinate(array[2], array[1]),
  27277. new Coordinate(array[2], array[3]),
  27278. new Coordinate(array[0], array[3]),
  27279. new Coordinate(array[0], array[1])
  27280. ])
  27281. },
  27282. /**
  27283. * Convert an Array with ordinates to a Point
  27284. *
  27285. * @param {Array}
  27286. * array Array with ordinates.
  27287. *
  27288. * @return {Point} Point.
  27289. */
  27290. Point: function (array) {
  27291. var coordinate = new Coordinate(array[0], array[1]);
  27292. return this.geometryFactory.createPoint(coordinate)
  27293. },
  27294. /**
  27295. * Convert an Array with coordinates to a MultiPoint
  27296. *
  27297. * @param {Array}
  27298. * array Array with coordinates.
  27299. *
  27300. * @return {MultiPoint} MultiPoint.
  27301. */
  27302. MultiPoint: function (array) {
  27303. var this$1 = this;
  27304. var points = [];
  27305. for (var i = 0; i < array.length; ++i) {
  27306. points.push(parse.Point.apply(this$1, [array[i]]));
  27307. }
  27308. return this.geometryFactory.createMultiPoint(points)
  27309. },
  27310. /**
  27311. * Convert an Array with coordinates to a LineString
  27312. *
  27313. * @param {Array}
  27314. * array Array with coordinates.
  27315. *
  27316. * @return {LineString} LineString.
  27317. */
  27318. LineString: function (array) {
  27319. var coordinates = parse.coordinates.apply(this, [array]);
  27320. return this.geometryFactory.createLineString(coordinates)
  27321. },
  27322. /**
  27323. * Convert an Array with coordinates to a MultiLineString
  27324. *
  27325. * @param {Array}
  27326. * array Array with coordinates.
  27327. *
  27328. * @return {MultiLineString} MultiLineString.
  27329. */
  27330. MultiLineString: function (array) {
  27331. var this$1 = this;
  27332. var lineStrings = [];
  27333. for (var i = 0; i < array.length; ++i) {
  27334. lineStrings.push(parse.LineString.apply(this$1, [array[i]]));
  27335. }
  27336. return this.geometryFactory.createMultiLineString(lineStrings)
  27337. },
  27338. /**
  27339. * Convert an Array to a Polygon
  27340. *
  27341. * @param {Array}
  27342. * array Array with shell and holes.
  27343. *
  27344. * @return {Polygon} Polygon.
  27345. */
  27346. Polygon: function (array) {
  27347. var this$1 = this;
  27348. var shellCoordinates = parse.coordinates.apply(this, [array[0]]);
  27349. var shell = this.geometryFactory.createLinearRing(shellCoordinates);
  27350. var holes = [];
  27351. for (var i = 1; i < array.length; ++i) {
  27352. var hole = array[i];
  27353. var coordinates = parse.coordinates.apply(this$1, [hole]);
  27354. var linearRing = this$1.geometryFactory.createLinearRing(coordinates);
  27355. holes.push(linearRing);
  27356. }
  27357. return this.geometryFactory.createPolygon(shell, holes)
  27358. },
  27359. /**
  27360. * Convert an Array to a MultiPolygon
  27361. *
  27362. * @param {Array}
  27363. * array Array of arrays with shell and rings.
  27364. *
  27365. * @return {MultiPolygon} MultiPolygon.
  27366. */
  27367. MultiPolygon: function (array) {
  27368. var this$1 = this;
  27369. var polygons = [];
  27370. for (var i = 0; i < array.length; ++i) {
  27371. var polygon = array[i];
  27372. polygons.push(parse.Polygon.apply(this$1, [polygon]));
  27373. }
  27374. return this.geometryFactory.createMultiPolygon(polygons)
  27375. },
  27376. /**
  27377. * Convert an Array to a GeometryCollection
  27378. *
  27379. * @param {Array}
  27380. * array Array of GeoJSON geometries.
  27381. *
  27382. * @return {GeometryCollection} GeometryCollection.
  27383. */
  27384. GeometryCollection: function (array) {
  27385. var this$1 = this;
  27386. var geometries = [];
  27387. for (var i = 0; i < array.length; ++i) {
  27388. var geometry = array[i];
  27389. geometries.push(this$1.read(geometry));
  27390. }
  27391. return this.geometryFactory.createGeometryCollection(geometries)
  27392. }
  27393. };
  27394. var extract$1$1 = {
  27395. /**
  27396. * Convert a Coordinate to an Array
  27397. *
  27398. * @param {Coordinate}
  27399. * coordinate Coordinate to convert.
  27400. *
  27401. * @return {Array} Array of ordinates.
  27402. */
  27403. coordinate: function (coordinate) {
  27404. return [coordinate.x, coordinate.y]
  27405. },
  27406. /**
  27407. * Convert a Point to a GeoJSON object
  27408. *
  27409. * @param {Point}
  27410. * point Point to convert.
  27411. *
  27412. * @return {Array} Array of 2 ordinates (paired to a coordinate).
  27413. */
  27414. Point: function (point) {
  27415. var array = extract$1$1.coordinate.apply(this, [point.getCoordinate()]);
  27416. return {
  27417. type: 'Point',
  27418. coordinates: array
  27419. }
  27420. },
  27421. /**
  27422. * Convert a MultiPoint to a GeoJSON object
  27423. *
  27424. * @param {MultiPoint}
  27425. * multipoint MultiPoint to convert.
  27426. *
  27427. * @return {Array} Array of coordinates.
  27428. */
  27429. MultiPoint: function (multipoint) {
  27430. var this$1 = this;
  27431. var array = [];
  27432. for (var i = 0; i < multipoint._geometries.length; ++i) {
  27433. var point = multipoint._geometries[i];
  27434. var geoJson = extract$1$1.Point.apply(this$1, [point]);
  27435. array.push(geoJson.coordinates);
  27436. }
  27437. return {
  27438. type: 'MultiPoint',
  27439. coordinates: array
  27440. }
  27441. },
  27442. /**
  27443. * Convert a LineString to a GeoJSON object
  27444. *
  27445. * @param {LineString}
  27446. * linestring LineString to convert.
  27447. *
  27448. * @return {Array} Array of coordinates.
  27449. */
  27450. LineString: function (linestring) {
  27451. var this$1 = this;
  27452. var array = [];
  27453. var coordinates = linestring.getCoordinates();
  27454. for (var i = 0; i < coordinates.length; ++i) {
  27455. var coordinate = coordinates[i];
  27456. array.push(extract$1$1.coordinate.apply(this$1, [coordinate]));
  27457. }
  27458. return {
  27459. type: 'LineString',
  27460. coordinates: array
  27461. }
  27462. },
  27463. /**
  27464. * Convert a MultiLineString to a GeoJSON object
  27465. *
  27466. * @param {MultiLineString}
  27467. * multilinestring MultiLineString to convert.
  27468. *
  27469. * @return {Array} Array of Array of coordinates.
  27470. */
  27471. MultiLineString: function (multilinestring) {
  27472. var this$1 = this;
  27473. var array = [];
  27474. for (var i = 0; i < multilinestring._geometries.length; ++i) {
  27475. var linestring = multilinestring._geometries[i];
  27476. var geoJson = extract$1$1.LineString.apply(this$1, [linestring]);
  27477. array.push(geoJson.coordinates);
  27478. }
  27479. return {
  27480. type: 'MultiLineString',
  27481. coordinates: array
  27482. }
  27483. },
  27484. /**
  27485. * Convert a Polygon to a GeoJSON object
  27486. *
  27487. * @param {Polygon}
  27488. * polygon Polygon to convert.
  27489. *
  27490. * @return {Array} Array with shell, holes.
  27491. */
  27492. Polygon: function (polygon) {
  27493. var this$1 = this;
  27494. var array = [];
  27495. var shellGeoJson = extract$1$1.LineString.apply(this, [polygon._shell]);
  27496. array.push(shellGeoJson.coordinates);
  27497. for (var i = 0; i < polygon._holes.length; ++i) {
  27498. var hole = polygon._holes[i];
  27499. var holeGeoJson = extract$1$1.LineString.apply(this$1, [hole]);
  27500. array.push(holeGeoJson.coordinates);
  27501. }
  27502. return {
  27503. type: 'Polygon',
  27504. coordinates: array
  27505. }
  27506. },
  27507. /**
  27508. * Convert a MultiPolygon to a GeoJSON object
  27509. *
  27510. * @param {MultiPolygon}
  27511. * multipolygon MultiPolygon to convert.
  27512. *
  27513. * @return {Array} Array of polygons.
  27514. */
  27515. MultiPolygon: function (multipolygon) {
  27516. var this$1 = this;
  27517. var array = [];
  27518. for (var i = 0; i < multipolygon._geometries.length; ++i) {
  27519. var polygon = multipolygon._geometries[i];
  27520. var geoJson = extract$1$1.Polygon.apply(this$1, [polygon]);
  27521. array.push(geoJson.coordinates);
  27522. }
  27523. return {
  27524. type: 'MultiPolygon',
  27525. coordinates: array
  27526. }
  27527. },
  27528. /**
  27529. * Convert a GeometryCollection to a GeoJSON object
  27530. *
  27531. * @param {GeometryCollection}
  27532. * collection GeometryCollection to convert.
  27533. *
  27534. * @return {Array} Array of geometries.
  27535. */
  27536. GeometryCollection: function (collection) {
  27537. var this$1 = this;
  27538. var array = [];
  27539. for (var i = 0; i < collection._geometries.length; ++i) {
  27540. var geometry = collection._geometries[i];
  27541. var type = geometry.getGeometryType();
  27542. array.push(extract$1$1[type].apply(this$1, [geometry]));
  27543. }
  27544. return {
  27545. type: 'GeometryCollection',
  27546. geometries: array
  27547. }
  27548. }
  27549. };
  27550. /**
  27551. * Converts a geometry in GeoJSON to a {@link Geometry}.
  27552. */
  27553. /**
  27554. * A <code>GeoJSONReader</code> is parameterized by a <code>GeometryFactory</code>,
  27555. * to allow it to create <code>Geometry</code> objects of the appropriate
  27556. * implementation. In particular, the <code>GeometryFactory</code> determines
  27557. * the <code>PrecisionModel</code> and <code>SRID</code> that is used.
  27558. *
  27559. * @param {GeometryFactory} geometryFactory
  27560. * @constructor
  27561. */
  27562. var GeoJSONReader = function GeoJSONReader (geometryFactory) {
  27563. this.geometryFactory = geometryFactory || new GeometryFactory();
  27564. this.precisionModel = this.geometryFactory.getPrecisionModel();
  27565. this.parser = new GeoJSONParser(this.geometryFactory);
  27566. };
  27567. /**
  27568. * Reads a GeoJSON representation of a {@link Geometry}
  27569. *
  27570. * Will also parse GeoJSON Features/FeatureCollections as custom objects.
  27571. *
  27572. * @param {Object|String} geoJson a GeoJSON Object or String.
  27573. * @return {Geometry|Object} a <code>Geometry or Feature/FeatureCollection representation.</code>
  27574. * @memberof GeoJSONReader
  27575. */
  27576. GeoJSONReader.prototype.read = function read (geoJson) {
  27577. var geometry = this.parser.read(geoJson);
  27578. if (this.precisionModel.getType() === PrecisionModel.FIXED) {
  27579. this.reducePrecision(geometry);
  27580. }
  27581. return geometry
  27582. };
  27583. // NOTE: this is a hack
  27584. GeoJSONReader.prototype.reducePrecision = function reducePrecision (geometry) {
  27585. var this$1 = this;
  27586. var i, len;
  27587. if (geometry.coordinate) {
  27588. this.precisionModel.makePrecise(geometry.coordinate);
  27589. } else if (geometry.points) {
  27590. for (i = 0, len = geometry.points.length; i < len; i++) {
  27591. this$1.precisionModel.makePrecise(geometry.points[i]);
  27592. }
  27593. } else if (geometry.geometries) {
  27594. for (i = 0, len = geometry.geometries.length; i < len; i++) {
  27595. this$1.reducePrecision(geometry.geometries[i]);
  27596. }
  27597. }
  27598. };
  27599. /**
  27600. * @module GeoJSONWriter
  27601. */
  27602. /**
  27603. * Writes the GeoJSON representation of a {@link Geometry}. The
  27604. * The GeoJSON format is defined <A
  27605. * HREF="http://geojson.org/geojson-spec.html">here</A>.
  27606. */
  27607. /**
  27608. * The <code>GeoJSONWriter</code> outputs coordinates rounded to the precision
  27609. * model. Only the maximum number of decimal places necessary to represent the
  27610. * ordinates to the required precision will be output.
  27611. *
  27612. * @param {GeometryFactory} geometryFactory
  27613. * @constructor
  27614. */
  27615. var GeoJSONWriter = function GeoJSONWriter () {
  27616. this.parser = new GeoJSONParser(this.geometryFactory);
  27617. };
  27618. /**
  27619. * Converts a <code>Geometry</code> to its GeoJSON representation.
  27620. *
  27621. * @param {Geometry}
  27622. * geometry a <code>Geometry</code> to process.
  27623. * @return {Object} The GeoJSON representation of the Geometry.
  27624. * @memberof GeoJSONWriter
  27625. */
  27626. GeoJSONWriter.prototype.write = function write (geometry) {
  27627. return this.parser.write(geometry)
  27628. };
  27629. /* eslint-disable no-undef */
  27630. // io
  27631. var Position = function Position () {};
  27632. var staticAccessors$20 = { ON: { configurable: true },LEFT: { configurable: true },RIGHT: { configurable: true } };
  27633. Position.prototype.interfaces_ = function interfaces_ () {
  27634. return []
  27635. };
  27636. Position.prototype.getClass = function getClass () {
  27637. return Position
  27638. };
  27639. Position.opposite = function opposite (position) {
  27640. if (position === Position.LEFT) { return Position.RIGHT }
  27641. if (position === Position.RIGHT) { return Position.LEFT }
  27642. return position
  27643. };
  27644. staticAccessors$20.ON.get = function () { return 0 };
  27645. staticAccessors$20.LEFT.get = function () { return 1 };
  27646. staticAccessors$20.RIGHT.get = function () { return 2 };
  27647. Object.defineProperties( Position, staticAccessors$20 );
  27648. /**
  27649. * @param {string=} message Optional message
  27650. * @extends {Error}
  27651. * @constructor
  27652. * @private
  27653. */
  27654. function EmptyStackException (message) {
  27655. this.message = message || '';
  27656. }
  27657. EmptyStackException.prototype = new Error();
  27658. /**
  27659. * @type {string}
  27660. */
  27661. EmptyStackException.prototype.name = 'EmptyStackException';
  27662. /**
  27663. * @see http://download.oracle.com/javase/6/docs/api/java/util/Stack.html
  27664. *
  27665. * @extends {List}
  27666. * @constructor
  27667. * @private
  27668. */
  27669. function Stack () {
  27670. /**
  27671. * @type {Array}
  27672. * @private
  27673. */
  27674. this.array_ = [];
  27675. }
  27676. Stack.prototype = new List();
  27677. /**
  27678. * @override
  27679. */
  27680. Stack.prototype.add = function (e) {
  27681. this.array_.push(e);
  27682. return true
  27683. };
  27684. /**
  27685. * @override
  27686. */
  27687. Stack.prototype.get = function (index) {
  27688. if (index < 0 || index >= this.size()) {
  27689. throw new Error()
  27690. }
  27691. return this.array_[index]
  27692. };
  27693. /**
  27694. * Pushes an item onto the top of this stack.
  27695. * @param {Object} e
  27696. * @return {Object}
  27697. */
  27698. Stack.prototype.push = function (e) {
  27699. this.array_.push(e);
  27700. return e
  27701. };
  27702. /**
  27703. * Pushes an item onto the top of this stack.
  27704. * @param {Object} e
  27705. * @return {Object}
  27706. */
  27707. Stack.prototype.pop = function (e) {
  27708. if (this.array_.length === 0) {
  27709. throw new EmptyStackException()
  27710. }
  27711. return this.array_.pop()
  27712. };
  27713. /**
  27714. * Looks at the object at the top of this stack without removing it from the
  27715. * stack.
  27716. * @return {Object}
  27717. */
  27718. Stack.prototype.peek = function () {
  27719. if (this.array_.length === 0) {
  27720. throw new EmptyStackException()
  27721. }
  27722. return this.array_[this.array_.length - 1]
  27723. };
  27724. /**
  27725. * Tests if this stack is empty.
  27726. * @return {boolean} true if and only if this stack contains no items; false
  27727. * otherwise.
  27728. */
  27729. Stack.prototype.empty = function () {
  27730. if (this.array_.length === 0) {
  27731. return true
  27732. } else {
  27733. return false
  27734. }
  27735. };
  27736. /**
  27737. * @return {boolean}
  27738. */
  27739. Stack.prototype.isEmpty = function () {
  27740. return this.empty()
  27741. };
  27742. /**
  27743. * Returns the 1-based position where an object is on this stack. If the object
  27744. * o occurs as an item in this stack, this method returns the distance from the
  27745. * top of the stack of the occurrence nearest the top of the stack; the topmost
  27746. * item on the stack is considered to be at distance 1. The equals method is
  27747. * used to compare o to the items in this stack.
  27748. *
  27749. * NOTE: does not currently actually use equals. (=== is used)
  27750. *
  27751. * @param {Object} o
  27752. * @return {number} the 1-based position from the top of the stack where the
  27753. * object is located; the return value -1 indicates that the object is
  27754. * not on the stack.
  27755. */
  27756. Stack.prototype.search = function (o) {
  27757. return this.array_.indexOf(o)
  27758. };
  27759. /**
  27760. * @return {number}
  27761. * @export
  27762. */
  27763. Stack.prototype.size = function () {
  27764. return this.array_.length
  27765. };
  27766. /**
  27767. * @return {Array}
  27768. */
  27769. Stack.prototype.toArray = function () {
  27770. var this$1 = this;
  27771. var array = [];
  27772. for (var i = 0, len = this.array_.length; i < len; i++) {
  27773. array.push(this$1.array_[i]);
  27774. }
  27775. return array
  27776. };
  27777. var RightmostEdgeFinder = function RightmostEdgeFinder () {
  27778. this._minIndex = -1;
  27779. this._minCoord = null;
  27780. this._minDe = null;
  27781. this._orientedDe = null;
  27782. };
  27783. RightmostEdgeFinder.prototype.getCoordinate = function getCoordinate () {
  27784. return this._minCoord
  27785. };
  27786. RightmostEdgeFinder.prototype.getRightmostSide = function getRightmostSide (de, index) {
  27787. var side = this.getRightmostSideOfSegment(de, index);
  27788. if (side < 0) { side = this.getRightmostSideOfSegment(de, index - 1); }
  27789. if (side < 0) {
  27790. this._minCoord = null;
  27791. this.checkForRightmostCoordinate(de);
  27792. }
  27793. return side
  27794. };
  27795. RightmostEdgeFinder.prototype.findRightmostEdgeAtVertex = function findRightmostEdgeAtVertex () {
  27796. var pts = this._minDe.getEdge().getCoordinates();
  27797. Assert.isTrue(this._minIndex > 0 && this._minIndex < pts.length, 'rightmost point expected to be interior vertex of edge');
  27798. var pPrev = pts[this._minIndex - 1];
  27799. var pNext = pts[this._minIndex + 1];
  27800. var orientation = CGAlgorithms.computeOrientation(this._minCoord, pNext, pPrev);
  27801. var usePrev = false;
  27802. if (pPrev.y < this._minCoord.y && pNext.y < this._minCoord.y && orientation === CGAlgorithms.COUNTERCLOCKWISE) {
  27803. usePrev = true;
  27804. } else if (pPrev.y > this._minCoord.y && pNext.y > this._minCoord.y && orientation === CGAlgorithms.CLOCKWISE) {
  27805. usePrev = true;
  27806. }
  27807. if (usePrev) {
  27808. this._minIndex = this._minIndex - 1;
  27809. }
  27810. };
  27811. RightmostEdgeFinder.prototype.getRightmostSideOfSegment = function getRightmostSideOfSegment (de, i) {
  27812. var e = de.getEdge();
  27813. var coord = e.getCoordinates();
  27814. if (i < 0 || i + 1 >= coord.length) { return -1 }
  27815. if (coord[i].y === coord[i + 1].y) { return -1 }
  27816. var pos = Position.LEFT;
  27817. if (coord[i].y < coord[i + 1].y) { pos = Position.RIGHT; }
  27818. return pos
  27819. };
  27820. RightmostEdgeFinder.prototype.getEdge = function getEdge () {
  27821. return this._orientedDe
  27822. };
  27823. RightmostEdgeFinder.prototype.checkForRightmostCoordinate = function checkForRightmostCoordinate (de) {
  27824. var this$1 = this;
  27825. var coord = de.getEdge().getCoordinates();
  27826. for (var i = 0; i < coord.length - 1; i++) {
  27827. if (this$1._minCoord === null || coord[i].x > this$1._minCoord.x) {
  27828. this$1._minDe = de;
  27829. this$1._minIndex = i;
  27830. this$1._minCoord = coord[i];
  27831. }
  27832. }
  27833. };
  27834. RightmostEdgeFinder.prototype.findRightmostEdgeAtNode = function findRightmostEdgeAtNode () {
  27835. var node = this._minDe.getNode();
  27836. var star = node.getEdges();
  27837. this._minDe = star.getRightmostEdge();
  27838. if (!this._minDe.isForward()) {
  27839. this._minDe = this._minDe.getSym();
  27840. this._minIndex = this._minDe.getEdge().getCoordinates().length - 1;
  27841. }
  27842. };
  27843. RightmostEdgeFinder.prototype.findEdge = function findEdge (dirEdgeList) {
  27844. var this$1 = this;
  27845. for (var i = dirEdgeList.iterator(); i.hasNext();) {
  27846. var de = i.next();
  27847. if (!de.isForward()) { continue }
  27848. this$1.checkForRightmostCoordinate(de);
  27849. }
  27850. Assert.isTrue(this._minIndex !== 0 || this._minCoord.equals(this._minDe.getCoordinate()), 'inconsistency in rightmost processing');
  27851. if (this._minIndex === 0) {
  27852. this.findRightmostEdgeAtNode();
  27853. } else {
  27854. this.findRightmostEdgeAtVertex();
  27855. }
  27856. this._orientedDe = this._minDe;
  27857. var rightmostSide = this.getRightmostSide(this._minDe, this._minIndex);
  27858. if (rightmostSide === Position.LEFT) {
  27859. this._orientedDe = this._minDe.getSym();
  27860. }
  27861. };
  27862. RightmostEdgeFinder.prototype.interfaces_ = function interfaces_ () {
  27863. return []
  27864. };
  27865. RightmostEdgeFinder.prototype.getClass = function getClass () {
  27866. return RightmostEdgeFinder
  27867. };
  27868. var TopologyException = (function (RuntimeException$$1) {
  27869. function TopologyException (msg, pt) {
  27870. RuntimeException$$1.call(this, TopologyException.msgWithCoord(msg, pt));
  27871. this.pt = pt ? new Coordinate(pt) : null;
  27872. this.name = 'TopologyException';
  27873. }
  27874. if ( RuntimeException$$1 ) TopologyException.__proto__ = RuntimeException$$1;
  27875. TopologyException.prototype = Object.create( RuntimeException$$1 && RuntimeException$$1.prototype );
  27876. TopologyException.prototype.constructor = TopologyException;
  27877. TopologyException.prototype.getCoordinate = function getCoordinate () {
  27878. return this.pt
  27879. };
  27880. TopologyException.prototype.interfaces_ = function interfaces_ () {
  27881. return []
  27882. };
  27883. TopologyException.prototype.getClass = function getClass () {
  27884. return TopologyException
  27885. };
  27886. TopologyException.msgWithCoord = function msgWithCoord (msg, pt) {
  27887. if (!pt) { return msg + ' [ ' + pt + ' ]' }
  27888. return msg
  27889. };
  27890. return TopologyException;
  27891. }(RuntimeException));
  27892. var LinkedList = function LinkedList () {
  27893. this.array_ = [];
  27894. };
  27895. LinkedList.prototype.addLast = function addLast (e) {
  27896. this.array_.push(e);
  27897. };
  27898. LinkedList.prototype.removeFirst = function removeFirst () {
  27899. return this.array_.shift()
  27900. };
  27901. LinkedList.prototype.isEmpty = function isEmpty () {
  27902. return this.array_.length === 0
  27903. };
  27904. var BufferSubgraph = function BufferSubgraph () {
  27905. this._finder = null;
  27906. this._dirEdgeList = new ArrayList();
  27907. this._nodes = new ArrayList();
  27908. this._rightMostCoord = null;
  27909. this._env = null;
  27910. this._finder = new RightmostEdgeFinder();
  27911. };
  27912. BufferSubgraph.prototype.clearVisitedEdges = function clearVisitedEdges () {
  27913. for (var it = this._dirEdgeList.iterator(); it.hasNext();) {
  27914. var de = it.next();
  27915. de.setVisited(false);
  27916. }
  27917. };
  27918. BufferSubgraph.prototype.getRightmostCoordinate = function getRightmostCoordinate () {
  27919. return this._rightMostCoord
  27920. };
  27921. BufferSubgraph.prototype.computeNodeDepth = function computeNodeDepth (n) {
  27922. var this$1 = this;
  27923. var startEdge = null;
  27924. for (var i = n.getEdges().iterator(); i.hasNext();) {
  27925. var de = i.next();
  27926. if (de.isVisited() || de.getSym().isVisited()) {
  27927. startEdge = de;
  27928. break
  27929. }
  27930. }
  27931. if (startEdge === null) { throw new TopologyException('unable to find edge to compute depths at ' + n.getCoordinate()) }
  27932. n.getEdges().computeDepths(startEdge);
  27933. for (var i$1 = n.getEdges().iterator(); i$1.hasNext();) {
  27934. var de$1 = i$1.next();
  27935. de$1.setVisited(true);
  27936. this$1.copySymDepths(de$1);
  27937. }
  27938. };
  27939. BufferSubgraph.prototype.computeDepth = function computeDepth (outsideDepth) {
  27940. this.clearVisitedEdges();
  27941. var de = this._finder.getEdge();
  27942. // const n = de.getNode()
  27943. // const label = de.getLabel()
  27944. de.setEdgeDepths(Position.RIGHT, outsideDepth);
  27945. this.copySymDepths(de);
  27946. this.computeDepths(de);
  27947. };
  27948. BufferSubgraph.prototype.create = function create (node) {
  27949. this.addReachable(node);
  27950. this._finder.findEdge(this._dirEdgeList);
  27951. this._rightMostCoord = this._finder.getCoordinate();
  27952. };
  27953. BufferSubgraph.prototype.findResultEdges = function findResultEdges () {
  27954. for (var it = this._dirEdgeList.iterator(); it.hasNext();) {
  27955. var de = it.next();
  27956. if (de.getDepth(Position.RIGHT) >= 1 && de.getDepth(Position.LEFT) <= 0 && !de.isInteriorAreaEdge()) {
  27957. de.setInResult(true);
  27958. }
  27959. }
  27960. };
  27961. BufferSubgraph.prototype.computeDepths = function computeDepths (startEdge) {
  27962. var this$1 = this;
  27963. var nodesVisited = new HashSet();
  27964. var nodeQueue = new LinkedList();
  27965. var startNode = startEdge.getNode();
  27966. nodeQueue.addLast(startNode);
  27967. nodesVisited.add(startNode);
  27968. startEdge.setVisited(true);
  27969. while (!nodeQueue.isEmpty()) {
  27970. var n = nodeQueue.removeFirst();
  27971. nodesVisited.add(n);
  27972. this$1.computeNodeDepth(n);
  27973. for (var i = n.getEdges().iterator(); i.hasNext();) {
  27974. var de = i.next();
  27975. var sym = de.getSym();
  27976. if (sym.isVisited()) { continue }
  27977. var adjNode = sym.getNode();
  27978. if (!nodesVisited.contains(adjNode)) {
  27979. nodeQueue.addLast(adjNode);
  27980. nodesVisited.add(adjNode);
  27981. }
  27982. }
  27983. }
  27984. };
  27985. BufferSubgraph.prototype.compareTo = function compareTo (o) {
  27986. var graph = o;
  27987. if (this._rightMostCoord.x < graph._rightMostCoord.x) {
  27988. return -1
  27989. }
  27990. if (this._rightMostCoord.x > graph._rightMostCoord.x) {
  27991. return 1
  27992. }
  27993. return 0
  27994. };
  27995. BufferSubgraph.prototype.getEnvelope = function getEnvelope () {
  27996. if (this._env === null) {
  27997. var edgeEnv = new Envelope();
  27998. for (var it = this._dirEdgeList.iterator(); it.hasNext();) {
  27999. var dirEdge = it.next();
  28000. var pts = dirEdge.getEdge().getCoordinates();
  28001. for (var i = 0; i < pts.length - 1; i++) {
  28002. edgeEnv.expandToInclude(pts[i]);
  28003. }
  28004. }
  28005. this._env = edgeEnv;
  28006. }
  28007. return this._env
  28008. };
  28009. BufferSubgraph.prototype.addReachable = function addReachable (startNode) {
  28010. var this$1 = this;
  28011. var nodeStack = new Stack();
  28012. nodeStack.add(startNode);
  28013. while (!nodeStack.empty()) {
  28014. var node = nodeStack.pop();
  28015. this$1.add(node, nodeStack);
  28016. }
  28017. };
  28018. BufferSubgraph.prototype.copySymDepths = function copySymDepths (de) {
  28019. var sym = de.getSym();
  28020. sym.setDepth(Position.LEFT, de.getDepth(Position.RIGHT));
  28021. sym.setDepth(Position.RIGHT, de.getDepth(Position.LEFT));
  28022. };
  28023. BufferSubgraph.prototype.add = function add (node, nodeStack) {
  28024. var this$1 = this;
  28025. node.setVisited(true);
  28026. this._nodes.add(node);
  28027. for (var i = node.getEdges().iterator(); i.hasNext();) {
  28028. var de = i.next();
  28029. this$1._dirEdgeList.add(de);
  28030. var sym = de.getSym();
  28031. var symNode = sym.getNode();
  28032. if (!symNode.isVisited()) { nodeStack.push(symNode); }
  28033. }
  28034. };
  28035. BufferSubgraph.prototype.getNodes = function getNodes () {
  28036. return this._nodes
  28037. };
  28038. BufferSubgraph.prototype.getDirectedEdges = function getDirectedEdges () {
  28039. return this._dirEdgeList
  28040. };
  28041. BufferSubgraph.prototype.interfaces_ = function interfaces_ () {
  28042. return [Comparable]
  28043. };
  28044. BufferSubgraph.prototype.getClass = function getClass () {
  28045. return BufferSubgraph
  28046. };
  28047. var TopologyLocation = function TopologyLocation () {
  28048. var this$1 = this;
  28049. this.location = null;
  28050. if (arguments.length === 1) {
  28051. if (arguments[0] instanceof Array) {
  28052. var location = arguments[0];
  28053. this.init(location.length);
  28054. } else if (Number.isInteger(arguments[0])) {
  28055. var on = arguments[0];
  28056. this.init(1);
  28057. this.location[Position.ON] = on;
  28058. } else if (arguments[0] instanceof TopologyLocation) {
  28059. var gl = arguments[0];
  28060. this.init(gl.location.length);
  28061. if (gl !== null) {
  28062. for (var i = 0; i < this.location.length; i++) {
  28063. this$1.location[i] = gl.location[i];
  28064. }
  28065. }
  28066. }
  28067. } else if (arguments.length === 3) {
  28068. var on$1 = arguments[0];
  28069. var left = arguments[1];
  28070. var right = arguments[2];
  28071. this.init(3);
  28072. this.location[Position.ON] = on$1;
  28073. this.location[Position.LEFT] = left;
  28074. this.location[Position.RIGHT] = right;
  28075. }
  28076. };
  28077. TopologyLocation.prototype.setAllLocations = function setAllLocations (locValue) {
  28078. var this$1 = this;
  28079. for (var i = 0; i < this.location.length; i++) {
  28080. this$1.location[i] = locValue;
  28081. }
  28082. };
  28083. TopologyLocation.prototype.isNull = function isNull () {
  28084. var this$1 = this;
  28085. for (var i = 0; i < this.location.length; i++) {
  28086. if (this$1.location[i] !== Location.NONE) { return false }
  28087. }
  28088. return true
  28089. };
  28090. TopologyLocation.prototype.setAllLocationsIfNull = function setAllLocationsIfNull (locValue) {
  28091. var this$1 = this;
  28092. for (var i = 0; i < this.location.length; i++) {
  28093. if (this$1.location[i] === Location.NONE) { this$1.location[i] = locValue; }
  28094. }
  28095. };
  28096. TopologyLocation.prototype.isLine = function isLine () {
  28097. return this.location.length === 1
  28098. };
  28099. TopologyLocation.prototype.merge = function merge (gl) {
  28100. var this$1 = this;
  28101. if (gl.location.length > this.location.length) {
  28102. var newLoc = new Array(3).fill(null);
  28103. newLoc[Position.ON] = this.location[Position.ON];
  28104. newLoc[Position.LEFT] = Location.NONE;
  28105. newLoc[Position.RIGHT] = Location.NONE;
  28106. this.location = newLoc;
  28107. }
  28108. for (var i = 0; i < this.location.length; i++) {
  28109. if (this$1.location[i] === Location.NONE && i < gl.location.length) { this$1.location[i] = gl.location[i]; }
  28110. }
  28111. };
  28112. TopologyLocation.prototype.getLocations = function getLocations () {
  28113. return this.location
  28114. };
  28115. TopologyLocation.prototype.flip = function flip () {
  28116. if (this.location.length <= 1) { return null }
  28117. var temp = this.location[Position.LEFT];
  28118. this.location[Position.LEFT] = this.location[Position.RIGHT];
  28119. this.location[Position.RIGHT] = temp;
  28120. };
  28121. TopologyLocation.prototype.toString = function toString () {
  28122. var buf = new StringBuffer();
  28123. if (this.location.length > 1) { buf.append(Location.toLocationSymbol(this.location[Position.LEFT])); }
  28124. buf.append(Location.toLocationSymbol(this.location[Position.ON]));
  28125. if (this.location.length > 1) { buf.append(Location.toLocationSymbol(this.location[Position.RIGHT])); }
  28126. return buf.toString()
  28127. };
  28128. TopologyLocation.prototype.setLocations = function setLocations (on, left, right) {
  28129. this.location[Position.ON] = on;
  28130. this.location[Position.LEFT] = left;
  28131. this.location[Position.RIGHT] = right;
  28132. };
  28133. TopologyLocation.prototype.get = function get (posIndex) {
  28134. if (posIndex < this.location.length) { return this.location[posIndex] }
  28135. return Location.NONE
  28136. };
  28137. TopologyLocation.prototype.isArea = function isArea () {
  28138. return this.location.length > 1
  28139. };
  28140. TopologyLocation.prototype.isAnyNull = function isAnyNull () {
  28141. var this$1 = this;
  28142. for (var i = 0; i < this.location.length; i++) {
  28143. if (this$1.location[i] === Location.NONE) { return true }
  28144. }
  28145. return false
  28146. };
  28147. TopologyLocation.prototype.setLocation = function setLocation () {
  28148. if (arguments.length === 1) {
  28149. var locValue = arguments[0];
  28150. this.setLocation(Position.ON, locValue);
  28151. } else if (arguments.length === 2) {
  28152. var locIndex = arguments[0];
  28153. var locValue$1 = arguments[1];
  28154. this.location[locIndex] = locValue$1;
  28155. }
  28156. };
  28157. TopologyLocation.prototype.init = function init (size) {
  28158. this.location = new Array(size).fill(null);
  28159. this.setAllLocations(Location.NONE);
  28160. };
  28161. TopologyLocation.prototype.isEqualOnSide = function isEqualOnSide (le, locIndex) {
  28162. return this.location[locIndex] === le.location[locIndex]
  28163. };
  28164. TopologyLocation.prototype.allPositionsEqual = function allPositionsEqual (loc) {
  28165. var this$1 = this;
  28166. for (var i = 0; i < this.location.length; i++) {
  28167. if (this$1.location[i] !== loc) { return false }
  28168. }
  28169. return true
  28170. };
  28171. TopologyLocation.prototype.interfaces_ = function interfaces_ () {
  28172. return []
  28173. };
  28174. TopologyLocation.prototype.getClass = function getClass () {
  28175. return TopologyLocation
  28176. };
  28177. var Label = function Label () {
  28178. this.elt = new Array(2).fill(null);
  28179. if (arguments.length === 1) {
  28180. if (Number.isInteger(arguments[0])) {
  28181. var onLoc = arguments[0];
  28182. this.elt[0] = new TopologyLocation(onLoc);
  28183. this.elt[1] = new TopologyLocation(onLoc);
  28184. } else if (arguments[0] instanceof Label) {
  28185. var lbl = arguments[0];
  28186. this.elt[0] = new TopologyLocation(lbl.elt[0]);
  28187. this.elt[1] = new TopologyLocation(lbl.elt[1]);
  28188. }
  28189. } else if (arguments.length === 2) {
  28190. var geomIndex = arguments[0];
  28191. var onLoc$1 = arguments[1];
  28192. this.elt[0] = new TopologyLocation(Location.NONE);
  28193. this.elt[1] = new TopologyLocation(Location.NONE);
  28194. this.elt[geomIndex].setLocation(onLoc$1);
  28195. } else if (arguments.length === 3) {
  28196. var onLoc$2 = arguments[0];
  28197. var leftLoc = arguments[1];
  28198. var rightLoc = arguments[2];
  28199. this.elt[0] = new TopologyLocation(onLoc$2, leftLoc, rightLoc);
  28200. this.elt[1] = new TopologyLocation(onLoc$2, leftLoc, rightLoc);
  28201. } else if (arguments.length === 4) {
  28202. var geomIndex$1 = arguments[0];
  28203. var onLoc$3 = arguments[1];
  28204. var leftLoc$1 = arguments[2];
  28205. var rightLoc$1 = arguments[3];
  28206. this.elt[0] = new TopologyLocation(Location.NONE, Location.NONE, Location.NONE);
  28207. this.elt[1] = new TopologyLocation(Location.NONE, Location.NONE, Location.NONE);
  28208. this.elt[geomIndex$1].setLocations(onLoc$3, leftLoc$1, rightLoc$1);
  28209. }
  28210. };
  28211. Label.prototype.getGeometryCount = function getGeometryCount () {
  28212. var count = 0;
  28213. if (!this.elt[0].isNull()) { count++; }
  28214. if (!this.elt[1].isNull()) { count++; }
  28215. return count
  28216. };
  28217. Label.prototype.setAllLocations = function setAllLocations (geomIndex, location) {
  28218. this.elt[geomIndex].setAllLocations(location);
  28219. };
  28220. Label.prototype.isNull = function isNull (geomIndex) {
  28221. return this.elt[geomIndex].isNull()
  28222. };
  28223. Label.prototype.setAllLocationsIfNull = function setAllLocationsIfNull () {
  28224. if (arguments.length === 1) {
  28225. var location = arguments[0];
  28226. this.setAllLocationsIfNull(0, location);
  28227. this.setAllLocationsIfNull(1, location);
  28228. } else if (arguments.length === 2) {
  28229. var geomIndex = arguments[0];
  28230. var location$1 = arguments[1];
  28231. this.elt[geomIndex].setAllLocationsIfNull(location$1);
  28232. }
  28233. };
  28234. Label.prototype.isLine = function isLine (geomIndex) {
  28235. return this.elt[geomIndex].isLine()
  28236. };
  28237. Label.prototype.merge = function merge (lbl) {
  28238. var this$1 = this;
  28239. for (var i = 0; i < 2; i++) {
  28240. if (this$1.elt[i] === null && lbl.elt[i] !== null) {
  28241. this$1.elt[i] = new TopologyLocation(lbl.elt[i]);
  28242. } else {
  28243. this$1.elt[i].merge(lbl.elt[i]);
  28244. }
  28245. }
  28246. };
  28247. Label.prototype.flip = function flip () {
  28248. this.elt[0].flip();
  28249. this.elt[1].flip();
  28250. };
  28251. Label.prototype.getLocation = function getLocation () {
  28252. if (arguments.length === 1) {
  28253. var geomIndex = arguments[0];
  28254. return this.elt[geomIndex].get(Position.ON)
  28255. } else if (arguments.length === 2) {
  28256. var geomIndex$1 = arguments[0];
  28257. var posIndex = arguments[1];
  28258. return this.elt[geomIndex$1].get(posIndex)
  28259. }
  28260. };
  28261. Label.prototype.toString = function toString () {
  28262. var buf = new StringBuffer();
  28263. if (this.elt[0] !== null) {
  28264. buf.append('A:');
  28265. buf.append(this.elt[0].toString());
  28266. }
  28267. if (this.elt[1] !== null) {
  28268. buf.append(' B:');
  28269. buf.append(this.elt[1].toString());
  28270. }
  28271. return buf.toString()
  28272. };
  28273. Label.prototype.isArea = function isArea () {
  28274. if (arguments.length === 0) {
  28275. return this.elt[0].isArea() || this.elt[1].isArea()
  28276. } else if (arguments.length === 1) {
  28277. var geomIndex = arguments[0];
  28278. return this.elt[geomIndex].isArea()
  28279. }
  28280. };
  28281. Label.prototype.isAnyNull = function isAnyNull (geomIndex) {
  28282. return this.elt[geomIndex].isAnyNull()
  28283. };
  28284. Label.prototype.setLocation = function setLocation () {
  28285. if (arguments.length === 2) {
  28286. var geomIndex = arguments[0];
  28287. var location = arguments[1];
  28288. this.elt[geomIndex].setLocation(Position.ON, location);
  28289. } else if (arguments.length === 3) {
  28290. var geomIndex$1 = arguments[0];
  28291. var posIndex = arguments[1];
  28292. var location$1 = arguments[2];
  28293. this.elt[geomIndex$1].setLocation(posIndex, location$1);
  28294. }
  28295. };
  28296. Label.prototype.isEqualOnSide = function isEqualOnSide (lbl, side) {
  28297. return this.elt[0].isEqualOnSide(lbl.elt[0], side) && this.elt[1].isEqualOnSide(lbl.elt[1], side)
  28298. };
  28299. Label.prototype.allPositionsEqual = function allPositionsEqual (geomIndex, loc) {
  28300. return this.elt[geomIndex].allPositionsEqual(loc)
  28301. };
  28302. Label.prototype.toLine = function toLine (geomIndex) {
  28303. if (this.elt[geomIndex].isArea()) { this.elt[geomIndex] = new TopologyLocation(this.elt[geomIndex].location[0]); }
  28304. };
  28305. Label.prototype.interfaces_ = function interfaces_ () {
  28306. return []
  28307. };
  28308. Label.prototype.getClass = function getClass () {
  28309. return Label
  28310. };
  28311. Label.toLineLabel = function toLineLabel (label) {
  28312. var lineLabel = new Label(Location.NONE);
  28313. for (var i = 0; i < 2; i++) {
  28314. lineLabel.setLocation(i, label.getLocation(i));
  28315. }
  28316. return lineLabel
  28317. };
  28318. var EdgeRing$1 = function EdgeRing () {
  28319. this._startDe = null;
  28320. this._maxNodeDegree = -1;
  28321. this._edges = new ArrayList();
  28322. this._pts = new ArrayList();
  28323. this._label = new Label(Location.NONE);
  28324. this._ring = null;
  28325. this._isHole = null;
  28326. this._shell = null;
  28327. this._holes = new ArrayList();
  28328. this._geometryFactory = null;
  28329. var start = arguments[0];
  28330. var geometryFactory = arguments[1];
  28331. this._geometryFactory = geometryFactory;
  28332. this.computePoints(start);
  28333. this.computeRing();
  28334. };
  28335. EdgeRing$1.prototype.computeRing = function computeRing () {
  28336. var this$1 = this;
  28337. if (this._ring !== null) { return null }
  28338. var coord = new Array(this._pts.size()).fill(null);
  28339. for (var i = 0; i < this._pts.size(); i++) {
  28340. coord[i] = this$1._pts.get(i);
  28341. }
  28342. this._ring = this._geometryFactory.createLinearRing(coord);
  28343. this._isHole = CGAlgorithms.isCCW(this._ring.getCoordinates());
  28344. };
  28345. EdgeRing$1.prototype.isIsolated = function isIsolated () {
  28346. return this._label.getGeometryCount() === 1
  28347. };
  28348. EdgeRing$1.prototype.computePoints = function computePoints (start) {
  28349. var this$1 = this;
  28350. this._startDe = start;
  28351. var de = start;
  28352. var isFirstEdge = true;
  28353. do {
  28354. if (de === null) { throw new TopologyException('Found null DirectedEdge') }
  28355. if (de.getEdgeRing() === this$1) { throw new TopologyException('Directed Edge visited twice during ring-building at ' + de.getCoordinate()) }
  28356. this$1._edges.add(de);
  28357. var label = de.getLabel();
  28358. Assert.isTrue(label.isArea());
  28359. this$1.mergeLabel(label);
  28360. this$1.addPoints(de.getEdge(), de.isForward(), isFirstEdge);
  28361. isFirstEdge = false;
  28362. this$1.setEdgeRing(de, this$1);
  28363. de = this$1.getNext(de);
  28364. } while (de !== this._startDe)
  28365. };
  28366. EdgeRing$1.prototype.getLinearRing = function getLinearRing () {
  28367. return this._ring
  28368. };
  28369. EdgeRing$1.prototype.getCoordinate = function getCoordinate (i) {
  28370. return this._pts.get(i)
  28371. };
  28372. EdgeRing$1.prototype.computeMaxNodeDegree = function computeMaxNodeDegree () {
  28373. var this$1 = this;
  28374. this._maxNodeDegree = 0;
  28375. var de = this._startDe;
  28376. do {
  28377. var node = de.getNode();
  28378. var degree = node.getEdges().getOutgoingDegree(this$1);
  28379. if (degree > this$1._maxNodeDegree) { this$1._maxNodeDegree = degree; }
  28380. de = this$1.getNext(de);
  28381. } while (de !== this._startDe)
  28382. this._maxNodeDegree *= 2;
  28383. };
  28384. EdgeRing$1.prototype.addPoints = function addPoints (edge, isForward, isFirstEdge) {
  28385. var this$1 = this;
  28386. var edgePts = edge.getCoordinates();
  28387. if (isForward) {
  28388. var startIndex = 1;
  28389. if (isFirstEdge) { startIndex = 0; }
  28390. for (var i = startIndex; i < edgePts.length; i++) {
  28391. this$1._pts.add(edgePts[i]);
  28392. }
  28393. } else {
  28394. var startIndex$1 = edgePts.length - 2;
  28395. if (isFirstEdge) { startIndex$1 = edgePts.length - 1; }
  28396. for (var i$1 = startIndex$1; i$1 >= 0; i$1--) {
  28397. this$1._pts.add(edgePts[i$1]);
  28398. }
  28399. }
  28400. };
  28401. EdgeRing$1.prototype.isHole = function isHole () {
  28402. return this._isHole
  28403. };
  28404. EdgeRing$1.prototype.setInResult = function setInResult () {
  28405. var de = this._startDe;
  28406. do {
  28407. de.getEdge().setInResult(true);
  28408. de = de.getNext();
  28409. } while (de !== this._startDe)
  28410. };
  28411. EdgeRing$1.prototype.containsPoint = function containsPoint (p) {
  28412. var shell = this.getLinearRing();
  28413. var env = shell.getEnvelopeInternal();
  28414. if (!env.contains(p)) { return false }
  28415. if (!CGAlgorithms.isPointInRing(p, shell.getCoordinates())) { return false }
  28416. for (var i = this._holes.iterator(); i.hasNext();) {
  28417. var hole = i.next();
  28418. if (hole.containsPoint(p)) { return false }
  28419. }
  28420. return true
  28421. };
  28422. EdgeRing$1.prototype.addHole = function addHole (ring) {
  28423. this._holes.add(ring);
  28424. };
  28425. EdgeRing$1.prototype.isShell = function isShell () {
  28426. return this._shell === null
  28427. };
  28428. EdgeRing$1.prototype.getLabel = function getLabel () {
  28429. return this._label
  28430. };
  28431. EdgeRing$1.prototype.getEdges = function getEdges () {
  28432. return this._edges
  28433. };
  28434. EdgeRing$1.prototype.getMaxNodeDegree = function getMaxNodeDegree () {
  28435. if (this._maxNodeDegree < 0) { this.computeMaxNodeDegree(); }
  28436. return this._maxNodeDegree
  28437. };
  28438. EdgeRing$1.prototype.getShell = function getShell () {
  28439. return this._shell
  28440. };
  28441. EdgeRing$1.prototype.mergeLabel = function mergeLabel () {
  28442. if (arguments.length === 1) {
  28443. var deLabel = arguments[0];
  28444. this.mergeLabel(deLabel, 0);
  28445. this.mergeLabel(deLabel, 1);
  28446. } else if (arguments.length === 2) {
  28447. var deLabel$1 = arguments[0];
  28448. var geomIndex = arguments[1];
  28449. var loc = deLabel$1.getLocation(geomIndex, Position.RIGHT);
  28450. if (loc === Location.NONE) { return null }
  28451. if (this._label.getLocation(geomIndex) === Location.NONE) {
  28452. this._label.setLocation(geomIndex, loc);
  28453. return null
  28454. }
  28455. }
  28456. };
  28457. EdgeRing$1.prototype.setShell = function setShell (shell) {
  28458. this._shell = shell;
  28459. if (shell !== null) { shell.addHole(this); }
  28460. };
  28461. EdgeRing$1.prototype.toPolygon = function toPolygon (geometryFactory) {
  28462. var this$1 = this;
  28463. var holeLR = new Array(this._holes.size()).fill(null);
  28464. for (var i = 0; i < this._holes.size(); i++) {
  28465. holeLR[i] = this$1._holes.get(i).getLinearRing();
  28466. }
  28467. var poly = geometryFactory.createPolygon(this.getLinearRing(), holeLR);
  28468. return poly
  28469. };
  28470. EdgeRing$1.prototype.interfaces_ = function interfaces_ () {
  28471. return []
  28472. };
  28473. EdgeRing$1.prototype.getClass = function getClass () {
  28474. return EdgeRing$1
  28475. };
  28476. var MinimalEdgeRing = (function (EdgeRing$$1) {
  28477. function MinimalEdgeRing () {
  28478. var start = arguments[0];
  28479. var geometryFactory = arguments[1];
  28480. EdgeRing$$1.call(this, start, geometryFactory);
  28481. }
  28482. if ( EdgeRing$$1 ) MinimalEdgeRing.__proto__ = EdgeRing$$1;
  28483. MinimalEdgeRing.prototype = Object.create( EdgeRing$$1 && EdgeRing$$1.prototype );
  28484. MinimalEdgeRing.prototype.constructor = MinimalEdgeRing;
  28485. MinimalEdgeRing.prototype.setEdgeRing = function setEdgeRing (de, er) {
  28486. de.setMinEdgeRing(er);
  28487. };
  28488. MinimalEdgeRing.prototype.getNext = function getNext (de) {
  28489. return de.getNextMin()
  28490. };
  28491. MinimalEdgeRing.prototype.interfaces_ = function interfaces_ () {
  28492. return []
  28493. };
  28494. MinimalEdgeRing.prototype.getClass = function getClass () {
  28495. return MinimalEdgeRing
  28496. };
  28497. return MinimalEdgeRing;
  28498. }(EdgeRing$1));
  28499. var MaximalEdgeRing = (function (EdgeRing$$1) {
  28500. function MaximalEdgeRing () {
  28501. var start = arguments[0];
  28502. var geometryFactory = arguments[1];
  28503. EdgeRing$$1.call(this, start, geometryFactory);
  28504. }
  28505. if ( EdgeRing$$1 ) MaximalEdgeRing.__proto__ = EdgeRing$$1;
  28506. MaximalEdgeRing.prototype = Object.create( EdgeRing$$1 && EdgeRing$$1.prototype );
  28507. MaximalEdgeRing.prototype.constructor = MaximalEdgeRing;
  28508. MaximalEdgeRing.prototype.buildMinimalRings = function buildMinimalRings () {
  28509. var this$1 = this;
  28510. var minEdgeRings = new ArrayList();
  28511. var de = this._startDe;
  28512. do {
  28513. if (de.getMinEdgeRing() === null) {
  28514. var minEr = new MinimalEdgeRing(de, this$1._geometryFactory);
  28515. minEdgeRings.add(minEr);
  28516. }
  28517. de = de.getNext();
  28518. } while (de !== this._startDe)
  28519. return minEdgeRings
  28520. };
  28521. MaximalEdgeRing.prototype.setEdgeRing = function setEdgeRing (de, er) {
  28522. de.setEdgeRing(er);
  28523. };
  28524. MaximalEdgeRing.prototype.linkDirectedEdgesForMinimalEdgeRings = function linkDirectedEdgesForMinimalEdgeRings () {
  28525. var this$1 = this;
  28526. var de = this._startDe;
  28527. do {
  28528. var node = de.getNode();
  28529. node.getEdges().linkMinimalDirectedEdges(this$1);
  28530. de = de.getNext();
  28531. } while (de !== this._startDe)
  28532. };
  28533. MaximalEdgeRing.prototype.getNext = function getNext (de) {
  28534. return de.getNext()
  28535. };
  28536. MaximalEdgeRing.prototype.interfaces_ = function interfaces_ () {
  28537. return []
  28538. };
  28539. MaximalEdgeRing.prototype.getClass = function getClass () {
  28540. return MaximalEdgeRing
  28541. };
  28542. return MaximalEdgeRing;
  28543. }(EdgeRing$1));
  28544. var GraphComponent = function GraphComponent () {
  28545. this._label = null;
  28546. this._isInResult = false;
  28547. this._isCovered = false;
  28548. this._isCoveredSet = false;
  28549. this._isVisited = false;
  28550. if (arguments.length === 0) {} else if (arguments.length === 1) {
  28551. var label = arguments[0];
  28552. this._label = label;
  28553. }
  28554. };
  28555. GraphComponent.prototype.setVisited = function setVisited (isVisited) {
  28556. this._isVisited = isVisited;
  28557. };
  28558. GraphComponent.prototype.setInResult = function setInResult (isInResult) {
  28559. this._isInResult = isInResult;
  28560. };
  28561. GraphComponent.prototype.isCovered = function isCovered () {
  28562. return this._isCovered
  28563. };
  28564. GraphComponent.prototype.isCoveredSet = function isCoveredSet () {
  28565. return this._isCoveredSet
  28566. };
  28567. GraphComponent.prototype.setLabel = function setLabel (label) {
  28568. this._label = label;
  28569. };
  28570. GraphComponent.prototype.getLabel = function getLabel () {
  28571. return this._label
  28572. };
  28573. GraphComponent.prototype.setCovered = function setCovered (isCovered) {
  28574. this._isCovered = isCovered;
  28575. this._isCoveredSet = true;
  28576. };
  28577. GraphComponent.prototype.updateIM = function updateIM (im) {
  28578. Assert.isTrue(this._label.getGeometryCount() >= 2, 'found partial label');
  28579. this.computeIM(im);
  28580. };
  28581. GraphComponent.prototype.isInResult = function isInResult () {
  28582. return this._isInResult
  28583. };
  28584. GraphComponent.prototype.isVisited = function isVisited () {
  28585. return this._isVisited
  28586. };
  28587. GraphComponent.prototype.interfaces_ = function interfaces_ () {
  28588. return []
  28589. };
  28590. GraphComponent.prototype.getClass = function getClass () {
  28591. return GraphComponent
  28592. };
  28593. var Node$2 = (function (GraphComponent$$1) {
  28594. function Node () {
  28595. GraphComponent$$1.call(this);
  28596. this._coord = null;
  28597. this._edges = null;
  28598. var coord = arguments[0];
  28599. var edges = arguments[1];
  28600. this._coord = coord;
  28601. this._edges = edges;
  28602. this._label = new Label(0, Location.NONE);
  28603. }
  28604. if ( GraphComponent$$1 ) Node.__proto__ = GraphComponent$$1;
  28605. Node.prototype = Object.create( GraphComponent$$1 && GraphComponent$$1.prototype );
  28606. Node.prototype.constructor = Node;
  28607. Node.prototype.isIncidentEdgeInResult = function isIncidentEdgeInResult () {
  28608. for (var it = this.getEdges().getEdges().iterator(); it.hasNext();) {
  28609. var de = it.next();
  28610. if (de.getEdge().isInResult()) { return true }
  28611. }
  28612. return false
  28613. };
  28614. Node.prototype.isIsolated = function isIsolated () {
  28615. return this._label.getGeometryCount() === 1
  28616. };
  28617. Node.prototype.getCoordinate = function getCoordinate () {
  28618. return this._coord
  28619. };
  28620. Node.prototype.print = function print (out) {
  28621. out.println('node ' + this._coord + ' lbl: ' + this._label);
  28622. };
  28623. Node.prototype.computeIM = function computeIM (im) {};
  28624. Node.prototype.computeMergedLocation = function computeMergedLocation (label2, eltIndex) {
  28625. var loc = Location.NONE;
  28626. loc = this._label.getLocation(eltIndex);
  28627. if (!label2.isNull(eltIndex)) {
  28628. var nLoc = label2.getLocation(eltIndex);
  28629. if (loc !== Location.BOUNDARY) { loc = nLoc; }
  28630. }
  28631. return loc
  28632. };
  28633. Node.prototype.setLabel = function setLabel () {
  28634. if (arguments.length === 2) {
  28635. var argIndex = arguments[0];
  28636. var onLocation = arguments[1];
  28637. if (this._label === null) {
  28638. this._label = new Label(argIndex, onLocation);
  28639. } else { this._label.setLocation(argIndex, onLocation); }
  28640. } else { return GraphComponent$$1.prototype.setLabel.apply(this, arguments) }
  28641. };
  28642. Node.prototype.getEdges = function getEdges () {
  28643. return this._edges
  28644. };
  28645. Node.prototype.mergeLabel = function mergeLabel () {
  28646. var this$1 = this;
  28647. if (arguments[0] instanceof Node) {
  28648. var n = arguments[0];
  28649. this.mergeLabel(n._label);
  28650. } else if (arguments[0] instanceof Label) {
  28651. var label2 = arguments[0];
  28652. for (var i = 0; i < 2; i++) {
  28653. var loc = this$1.computeMergedLocation(label2, i);
  28654. var thisLoc = this$1._label.getLocation(i);
  28655. if (thisLoc === Location.NONE) { this$1._label.setLocation(i, loc); }
  28656. }
  28657. }
  28658. };
  28659. Node.prototype.add = function add (e) {
  28660. this._edges.insert(e);
  28661. e.setNode(this);
  28662. };
  28663. Node.prototype.setLabelBoundary = function setLabelBoundary (argIndex) {
  28664. if (this._label === null) { return null }
  28665. var loc = Location.NONE;
  28666. if (this._label !== null) { loc = this._label.getLocation(argIndex); }
  28667. var newLoc = null;
  28668. switch (loc) {
  28669. case Location.BOUNDARY:
  28670. newLoc = Location.INTERIOR;
  28671. break
  28672. case Location.INTERIOR:
  28673. newLoc = Location.BOUNDARY;
  28674. break
  28675. default:
  28676. newLoc = Location.BOUNDARY;
  28677. break
  28678. }
  28679. this._label.setLocation(argIndex, newLoc);
  28680. };
  28681. Node.prototype.interfaces_ = function interfaces_ () {
  28682. return []
  28683. };
  28684. Node.prototype.getClass = function getClass () {
  28685. return Node
  28686. };
  28687. return Node;
  28688. }(GraphComponent));
  28689. var NodeMap = function NodeMap () {
  28690. this.nodeMap = new TreeMap();
  28691. this.nodeFact = null;
  28692. var nodeFact = arguments[0];
  28693. this.nodeFact = nodeFact;
  28694. };
  28695. NodeMap.prototype.find = function find (coord) {
  28696. return this.nodeMap.get(coord)
  28697. };
  28698. NodeMap.prototype.addNode = function addNode () {
  28699. if (arguments[0] instanceof Coordinate) {
  28700. var coord = arguments[0];
  28701. var node = this.nodeMap.get(coord);
  28702. if (node === null) {
  28703. node = this.nodeFact.createNode(coord);
  28704. this.nodeMap.put(coord, node);
  28705. }
  28706. return node
  28707. } else if (arguments[0] instanceof Node$2) {
  28708. var n = arguments[0];
  28709. var node$1 = this.nodeMap.get(n.getCoordinate());
  28710. if (node$1 === null) {
  28711. this.nodeMap.put(n.getCoordinate(), n);
  28712. return n
  28713. }
  28714. node$1.mergeLabel(n);
  28715. return node$1
  28716. }
  28717. };
  28718. NodeMap.prototype.print = function print (out) {
  28719. for (var it = this.iterator(); it.hasNext();) {
  28720. var n = it.next();
  28721. n.print(out);
  28722. }
  28723. };
  28724. NodeMap.prototype.iterator = function iterator () {
  28725. return this.nodeMap.values().iterator()
  28726. };
  28727. NodeMap.prototype.values = function values () {
  28728. return this.nodeMap.values()
  28729. };
  28730. NodeMap.prototype.getBoundaryNodes = function getBoundaryNodes (geomIndex) {
  28731. var bdyNodes = new ArrayList();
  28732. for (var i = this.iterator(); i.hasNext();) {
  28733. var node = i.next();
  28734. if (node.getLabel().getLocation(geomIndex) === Location.BOUNDARY) { bdyNodes.add(node); }
  28735. }
  28736. return bdyNodes
  28737. };
  28738. NodeMap.prototype.add = function add (e) {
  28739. var p = e.getCoordinate();
  28740. var n = this.addNode(p);
  28741. n.add(e);
  28742. };
  28743. NodeMap.prototype.interfaces_ = function interfaces_ () {
  28744. return []
  28745. };
  28746. NodeMap.prototype.getClass = function getClass () {
  28747. return NodeMap
  28748. };
  28749. var Quadrant = function Quadrant () {};
  28750. var staticAccessors$21 = { NE: { configurable: true },NW: { configurable: true },SW: { configurable: true },SE: { configurable: true } };
  28751. Quadrant.prototype.interfaces_ = function interfaces_ () {
  28752. return []
  28753. };
  28754. Quadrant.prototype.getClass = function getClass () {
  28755. return Quadrant
  28756. };
  28757. Quadrant.isNorthern = function isNorthern (quad) {
  28758. return quad === Quadrant.NE || quad === Quadrant.NW
  28759. };
  28760. Quadrant.isOpposite = function isOpposite (quad1, quad2) {
  28761. if (quad1 === quad2) { return false }
  28762. var diff = (quad1 - quad2 + 4) % 4;
  28763. if (diff === 2) { return true }
  28764. return false
  28765. };
  28766. Quadrant.commonHalfPlane = function commonHalfPlane (quad1, quad2) {
  28767. if (quad1 === quad2) { return quad1 }
  28768. var diff = (quad1 - quad2 + 4) % 4;
  28769. if (diff === 2) { return -1 }
  28770. var min = quad1 < quad2 ? quad1 : quad2;
  28771. var max = quad1 > quad2 ? quad1 : quad2;
  28772. if (min === 0 && max === 3) { return 3 }
  28773. return min
  28774. };
  28775. Quadrant.isInHalfPlane = function isInHalfPlane (quad, halfPlane) {
  28776. if (halfPlane === Quadrant.SE) {
  28777. return quad === Quadrant.SE || quad === Quadrant.SW
  28778. }
  28779. return quad === halfPlane || quad === halfPlane + 1
  28780. };
  28781. Quadrant.quadrant = function quadrant () {
  28782. if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') {
  28783. var dx = arguments[0];
  28784. var dy = arguments[1];
  28785. if (dx === 0.0 && dy === 0.0) { throw new IllegalArgumentException('Cannot compute the quadrant for point ( ' + dx + ', ' + dy + ' )') }
  28786. if (dx >= 0.0) {
  28787. if (dy >= 0.0) { return Quadrant.NE; } else { return Quadrant.SE }
  28788. } else {
  28789. if (dy >= 0.0) { return Quadrant.NW; } else { return Quadrant.SW }
  28790. }
  28791. } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Coordinate) {
  28792. var p0 = arguments[0];
  28793. var p1 = arguments[1];
  28794. if (p1.x === p0.x && p1.y === p0.y) { throw new IllegalArgumentException('Cannot compute the quadrant for two identical points ' + p0) }
  28795. if (p1.x >= p0.x) {
  28796. if (p1.y >= p0.y) { return Quadrant.NE; } else { return Quadrant.SE }
  28797. } else {
  28798. if (p1.y >= p0.y) { return Quadrant.NW; } else { return Quadrant.SW }
  28799. }
  28800. }
  28801. };
  28802. staticAccessors$21.NE.get = function () { return 0 };
  28803. staticAccessors$21.NW.get = function () { return 1 };
  28804. staticAccessors$21.SW.get = function () { return 2 };
  28805. staticAccessors$21.SE.get = function () { return 3 };
  28806. Object.defineProperties( Quadrant, staticAccessors$21 );
  28807. var EdgeEnd = function EdgeEnd () {
  28808. this._edge = null;
  28809. this._label = null;
  28810. this._node = null;
  28811. this._p0 = null;
  28812. this._p1 = null;
  28813. this._dx = null;
  28814. this._dy = null;
  28815. this._quadrant = null;
  28816. if (arguments.length === 1) {
  28817. var edge = arguments[0];
  28818. this._edge = edge;
  28819. } else if (arguments.length === 3) {
  28820. var edge$1 = arguments[0];
  28821. var p0 = arguments[1];
  28822. var p1 = arguments[2];
  28823. var label = null;
  28824. this._edge = edge$1;
  28825. this.init(p0, p1);
  28826. this._label = label;
  28827. } else if (arguments.length === 4) {
  28828. var edge$2 = arguments[0];
  28829. var p0$1 = arguments[1];
  28830. var p1$1 = arguments[2];
  28831. var label$1 = arguments[3];
  28832. this._edge = edge$2;
  28833. this.init(p0$1, p1$1);
  28834. this._label = label$1;
  28835. }
  28836. };
  28837. EdgeEnd.prototype.compareDirection = function compareDirection (e) {
  28838. if (this._dx === e._dx && this._dy === e._dy) { return 0 }
  28839. if (this._quadrant > e._quadrant) { return 1 }
  28840. if (this._quadrant < e._quadrant) { return -1 }
  28841. return CGAlgorithms.computeOrientation(e._p0, e._p1, this._p1)
  28842. };
  28843. EdgeEnd.prototype.getDy = function getDy () {
  28844. return this._dy
  28845. };
  28846. EdgeEnd.prototype.getCoordinate = function getCoordinate () {
  28847. return this._p0
  28848. };
  28849. EdgeEnd.prototype.setNode = function setNode (node) {
  28850. this._node = node;
  28851. };
  28852. EdgeEnd.prototype.print = function print (out) {
  28853. var angle = Math.atan2(this._dy, this._dx);
  28854. var className = this.getClass().getName();
  28855. var lastDotPos = className.lastIndexOf('.');
  28856. var name = className.substring(lastDotPos + 1);
  28857. out.print(' ' + name + ': ' + this._p0 + ' - ' + this._p1 + ' ' + this._quadrant + ':' + angle + ' ' + this._label);
  28858. };
  28859. EdgeEnd.prototype.compareTo = function compareTo (obj) {
  28860. var e = obj;
  28861. return this.compareDirection(e)
  28862. };
  28863. EdgeEnd.prototype.getDirectedCoordinate = function getDirectedCoordinate () {
  28864. return this._p1
  28865. };
  28866. EdgeEnd.prototype.getDx = function getDx () {
  28867. return this._dx
  28868. };
  28869. EdgeEnd.prototype.getLabel = function getLabel () {
  28870. return this._label
  28871. };
  28872. EdgeEnd.prototype.getEdge = function getEdge () {
  28873. return this._edge
  28874. };
  28875. EdgeEnd.prototype.getQuadrant = function getQuadrant () {
  28876. return this._quadrant
  28877. };
  28878. EdgeEnd.prototype.getNode = function getNode () {
  28879. return this._node
  28880. };
  28881. EdgeEnd.prototype.toString = function toString () {
  28882. var angle = Math.atan2(this._dy, this._dx);
  28883. var className = this.getClass().getName();
  28884. var lastDotPos = className.lastIndexOf('.');
  28885. var name = className.substring(lastDotPos + 1);
  28886. return ' ' + name + ': ' + this._p0 + ' - ' + this._p1 + ' ' + this._quadrant + ':' + angle + ' ' + this._label
  28887. };
  28888. EdgeEnd.prototype.computeLabel = function computeLabel (boundaryNodeRule) {};
  28889. EdgeEnd.prototype.init = function init (p0, p1) {
  28890. this._p0 = p0;
  28891. this._p1 = p1;
  28892. this._dx = p1.x - p0.x;
  28893. this._dy = p1.y - p0.y;
  28894. this._quadrant = Quadrant.quadrant(this._dx, this._dy);
  28895. Assert.isTrue(!(this._dx === 0 && this._dy === 0), 'EdgeEnd with identical endpoints found');
  28896. };
  28897. EdgeEnd.prototype.interfaces_ = function interfaces_ () {
  28898. return [Comparable]
  28899. };
  28900. EdgeEnd.prototype.getClass = function getClass () {
  28901. return EdgeEnd
  28902. };
  28903. var DirectedEdge = (function (EdgeEnd$$1) {
  28904. function DirectedEdge () {
  28905. var edge = arguments[0];
  28906. var isForward = arguments[1];
  28907. EdgeEnd$$1.call(this, edge);
  28908. this._isForward = null;
  28909. this._isInResult = false;
  28910. this._isVisited = false;
  28911. this._sym = null;
  28912. this._next = null;
  28913. this._nextMin = null;
  28914. this._edgeRing = null;
  28915. this._minEdgeRing = null;
  28916. this._depth = [0, -999, -999];
  28917. this._isForward = isForward;
  28918. if (isForward) {
  28919. this.init(edge.getCoordinate(0), edge.getCoordinate(1));
  28920. } else {
  28921. var n = edge.getNumPoints() - 1;
  28922. this.init(edge.getCoordinate(n), edge.getCoordinate(n - 1));
  28923. }
  28924. this.computeDirectedLabel();
  28925. }
  28926. if ( EdgeEnd$$1 ) DirectedEdge.__proto__ = EdgeEnd$$1;
  28927. DirectedEdge.prototype = Object.create( EdgeEnd$$1 && EdgeEnd$$1.prototype );
  28928. DirectedEdge.prototype.constructor = DirectedEdge;
  28929. DirectedEdge.prototype.getNextMin = function getNextMin () {
  28930. return this._nextMin
  28931. };
  28932. DirectedEdge.prototype.getDepth = function getDepth (position) {
  28933. return this._depth[position]
  28934. };
  28935. DirectedEdge.prototype.setVisited = function setVisited (isVisited) {
  28936. this._isVisited = isVisited;
  28937. };
  28938. DirectedEdge.prototype.computeDirectedLabel = function computeDirectedLabel () {
  28939. this._label = new Label(this._edge.getLabel());
  28940. if (!this._isForward) { this._label.flip(); }
  28941. };
  28942. DirectedEdge.prototype.getNext = function getNext () {
  28943. return this._next
  28944. };
  28945. DirectedEdge.prototype.setDepth = function setDepth (position, depthVal) {
  28946. if (this._depth[position] !== -999) {
  28947. if (this._depth[position] !== depthVal) { throw new TopologyException('assigned depths do not match', this.getCoordinate()) }
  28948. }
  28949. this._depth[position] = depthVal;
  28950. };
  28951. DirectedEdge.prototype.isInteriorAreaEdge = function isInteriorAreaEdge () {
  28952. var this$1 = this;
  28953. var isInteriorAreaEdge = true;
  28954. for (var i = 0; i < 2; i++) {
  28955. if (!(this$1._label.isArea(i) && this$1._label.getLocation(i, Position.LEFT) === Location.INTERIOR && this$1._label.getLocation(i, Position.RIGHT) === Location.INTERIOR)) {
  28956. isInteriorAreaEdge = false;
  28957. }
  28958. }
  28959. return isInteriorAreaEdge
  28960. };
  28961. DirectedEdge.prototype.setNextMin = function setNextMin (nextMin) {
  28962. this._nextMin = nextMin;
  28963. };
  28964. DirectedEdge.prototype.print = function print (out) {
  28965. EdgeEnd$$1.prototype.print.call(this, out);
  28966. out.print(' ' + this._depth[Position.LEFT] + '/' + this._depth[Position.RIGHT]);
  28967. out.print(' (' + this.getDepthDelta() + ')');
  28968. if (this._isInResult) { out.print(' inResult'); }
  28969. };
  28970. DirectedEdge.prototype.setMinEdgeRing = function setMinEdgeRing (minEdgeRing) {
  28971. this._minEdgeRing = minEdgeRing;
  28972. };
  28973. DirectedEdge.prototype.isLineEdge = function isLineEdge () {
  28974. var isLine = this._label.isLine(0) || this._label.isLine(1);
  28975. var isExteriorIfArea0 = !this._label.isArea(0) || this._label.allPositionsEqual(0, Location.EXTERIOR);
  28976. var isExteriorIfArea1 = !this._label.isArea(1) || this._label.allPositionsEqual(1, Location.EXTERIOR);
  28977. return isLine && isExteriorIfArea0 && isExteriorIfArea1
  28978. };
  28979. DirectedEdge.prototype.setEdgeRing = function setEdgeRing (edgeRing) {
  28980. this._edgeRing = edgeRing;
  28981. };
  28982. DirectedEdge.prototype.getMinEdgeRing = function getMinEdgeRing () {
  28983. return this._minEdgeRing
  28984. };
  28985. DirectedEdge.prototype.getDepthDelta = function getDepthDelta () {
  28986. var depthDelta = this._edge.getDepthDelta();
  28987. if (!this._isForward) { depthDelta = -depthDelta; }
  28988. return depthDelta
  28989. };
  28990. DirectedEdge.prototype.setInResult = function setInResult (isInResult) {
  28991. this._isInResult = isInResult;
  28992. };
  28993. DirectedEdge.prototype.getSym = function getSym () {
  28994. return this._sym
  28995. };
  28996. DirectedEdge.prototype.isForward = function isForward () {
  28997. return this._isForward
  28998. };
  28999. DirectedEdge.prototype.getEdge = function getEdge () {
  29000. return this._edge
  29001. };
  29002. DirectedEdge.prototype.printEdge = function printEdge (out) {
  29003. this.print(out);
  29004. out.print(' ');
  29005. if (this._isForward) { this._edge.print(out); } else { this._edge.printReverse(out); }
  29006. };
  29007. DirectedEdge.prototype.setSym = function setSym (de) {
  29008. this._sym = de;
  29009. };
  29010. DirectedEdge.prototype.setVisitedEdge = function setVisitedEdge (isVisited) {
  29011. this.setVisited(isVisited);
  29012. this._sym.setVisited(isVisited);
  29013. };
  29014. DirectedEdge.prototype.setEdgeDepths = function setEdgeDepths (position, depth) {
  29015. var depthDelta = this.getEdge().getDepthDelta();
  29016. if (!this._isForward) { depthDelta = -depthDelta; }
  29017. var directionFactor = 1;
  29018. if (position === Position.LEFT) { directionFactor = -1; }
  29019. var oppositePos = Position.opposite(position);
  29020. var delta = depthDelta * directionFactor;
  29021. var oppositeDepth = depth + delta;
  29022. this.setDepth(position, depth);
  29023. this.setDepth(oppositePos, oppositeDepth);
  29024. };
  29025. DirectedEdge.prototype.getEdgeRing = function getEdgeRing () {
  29026. return this._edgeRing
  29027. };
  29028. DirectedEdge.prototype.isInResult = function isInResult () {
  29029. return this._isInResult
  29030. };
  29031. DirectedEdge.prototype.setNext = function setNext (next) {
  29032. this._next = next;
  29033. };
  29034. DirectedEdge.prototype.isVisited = function isVisited () {
  29035. return this._isVisited
  29036. };
  29037. DirectedEdge.prototype.interfaces_ = function interfaces_ () {
  29038. return []
  29039. };
  29040. DirectedEdge.prototype.getClass = function getClass () {
  29041. return DirectedEdge
  29042. };
  29043. DirectedEdge.depthFactor = function depthFactor (currLocation, nextLocation) {
  29044. if (currLocation === Location.EXTERIOR && nextLocation === Location.INTERIOR) { return 1; } else if (currLocation === Location.INTERIOR && nextLocation === Location.EXTERIOR) { return -1 }
  29045. return 0
  29046. };
  29047. return DirectedEdge;
  29048. }(EdgeEnd));
  29049. var NodeFactory = function NodeFactory () {};
  29050. NodeFactory.prototype.createNode = function createNode (coord) {
  29051. return new Node$2(coord, null)
  29052. };
  29053. NodeFactory.prototype.interfaces_ = function interfaces_ () {
  29054. return []
  29055. };
  29056. NodeFactory.prototype.getClass = function getClass () {
  29057. return NodeFactory
  29058. };
  29059. var PlanarGraph = function PlanarGraph () {
  29060. this._edges = new ArrayList();
  29061. this._nodes = null;
  29062. this._edgeEndList = new ArrayList();
  29063. if (arguments.length === 0) {
  29064. this._nodes = new NodeMap(new NodeFactory());
  29065. } else if (arguments.length === 1) {
  29066. var nodeFact = arguments[0];
  29067. this._nodes = new NodeMap(nodeFact);
  29068. }
  29069. };
  29070. PlanarGraph.prototype.printEdges = function printEdges (out) {
  29071. var this$1 = this;
  29072. out.println('Edges:');
  29073. for (var i = 0; i < this._edges.size(); i++) {
  29074. out.println('edge ' + i + ':');
  29075. var e = this$1._edges.get(i);
  29076. e.print(out);
  29077. e.eiList.print(out);
  29078. }
  29079. };
  29080. PlanarGraph.prototype.find = function find (coord) {
  29081. return this._nodes.find(coord)
  29082. };
  29083. PlanarGraph.prototype.addNode = function addNode () {
  29084. if (arguments[0] instanceof Node$2) {
  29085. var node = arguments[0];
  29086. return this._nodes.addNode(node)
  29087. } else if (arguments[0] instanceof Coordinate) {
  29088. var coord = arguments[0];
  29089. return this._nodes.addNode(coord)
  29090. }
  29091. };
  29092. PlanarGraph.prototype.getNodeIterator = function getNodeIterator () {
  29093. return this._nodes.iterator()
  29094. };
  29095. PlanarGraph.prototype.linkResultDirectedEdges = function linkResultDirectedEdges () {
  29096. for (var nodeit = this._nodes.iterator(); nodeit.hasNext();) {
  29097. var node = nodeit.next();
  29098. node.getEdges().linkResultDirectedEdges();
  29099. }
  29100. };
  29101. PlanarGraph.prototype.debugPrintln = function debugPrintln (o) {
  29102. System.out.println(o);
  29103. };
  29104. PlanarGraph.prototype.isBoundaryNode = function isBoundaryNode (geomIndex, coord) {
  29105. var node = this._nodes.find(coord);
  29106. if (node === null) { return false }
  29107. var label = node.getLabel();
  29108. if (label !== null && label.getLocation(geomIndex) === Location.BOUNDARY) { return true }
  29109. return false
  29110. };
  29111. PlanarGraph.prototype.linkAllDirectedEdges = function linkAllDirectedEdges () {
  29112. for (var nodeit = this._nodes.iterator(); nodeit.hasNext();) {
  29113. var node = nodeit.next();
  29114. node.getEdges().linkAllDirectedEdges();
  29115. }
  29116. };
  29117. PlanarGraph.prototype.matchInSameDirection = function matchInSameDirection (p0, p1, ep0, ep1) {
  29118. if (!p0.equals(ep0)) { return false }
  29119. if (CGAlgorithms.computeOrientation(p0, p1, ep1) === CGAlgorithms.COLLINEAR && Quadrant.quadrant(p0, p1) === Quadrant.quadrant(ep0, ep1)) { return true }
  29120. return false
  29121. };
  29122. PlanarGraph.prototype.getEdgeEnds = function getEdgeEnds () {
  29123. return this._edgeEndList
  29124. };
  29125. PlanarGraph.prototype.debugPrint = function debugPrint (o) {
  29126. System.out.print(o);
  29127. };
  29128. PlanarGraph.prototype.getEdgeIterator = function getEdgeIterator () {
  29129. return this._edges.iterator()
  29130. };
  29131. PlanarGraph.prototype.findEdgeInSameDirection = function findEdgeInSameDirection (p0, p1) {
  29132. var this$1 = this;
  29133. for (var i = 0; i < this._edges.size(); i++) {
  29134. var e = this$1._edges.get(i);
  29135. var eCoord = e.getCoordinates();
  29136. if (this$1.matchInSameDirection(p0, p1, eCoord[0], eCoord[1])) { return e }
  29137. if (this$1.matchInSameDirection(p0, p1, eCoord[eCoord.length - 1], eCoord[eCoord.length - 2])) { return e }
  29138. }
  29139. return null
  29140. };
  29141. PlanarGraph.prototype.insertEdge = function insertEdge (e) {
  29142. this._edges.add(e);
  29143. };
  29144. PlanarGraph.prototype.findEdgeEnd = function findEdgeEnd (e) {
  29145. for (var i = this.getEdgeEnds().iterator(); i.hasNext();) {
  29146. var ee = i.next();
  29147. if (ee.getEdge() === e) { return ee }
  29148. }
  29149. return null
  29150. };
  29151. PlanarGraph.prototype.addEdges = function addEdges (edgesToAdd) {
  29152. var this$1 = this;
  29153. for (var it = edgesToAdd.iterator(); it.hasNext();) {
  29154. var e = it.next();
  29155. this$1._edges.add(e);
  29156. var de1 = new DirectedEdge(e, true);
  29157. var de2 = new DirectedEdge(e, false);
  29158. de1.setSym(de2);
  29159. de2.setSym(de1);
  29160. this$1.add(de1);
  29161. this$1.add(de2);
  29162. }
  29163. };
  29164. PlanarGraph.prototype.add = function add (e) {
  29165. this._nodes.add(e);
  29166. this._edgeEndList.add(e);
  29167. };
  29168. PlanarGraph.prototype.getNodes = function getNodes () {
  29169. return this._nodes.values()
  29170. };
  29171. PlanarGraph.prototype.findEdge = function findEdge (p0, p1) {
  29172. var this$1 = this;
  29173. for (var i = 0; i < this._edges.size(); i++) {
  29174. var e = this$1._edges.get(i);
  29175. var eCoord = e.getCoordinates();
  29176. if (p0.equals(eCoord[0]) && p1.equals(eCoord[1])) { return e }
  29177. }
  29178. return null
  29179. };
  29180. PlanarGraph.prototype.interfaces_ = function interfaces_ () {
  29181. return []
  29182. };
  29183. PlanarGraph.prototype.getClass = function getClass () {
  29184. return PlanarGraph
  29185. };
  29186. PlanarGraph.linkResultDirectedEdges = function linkResultDirectedEdges (nodes) {
  29187. for (var nodeit = nodes.iterator(); nodeit.hasNext();) {
  29188. var node = nodeit.next();
  29189. node.getEdges().linkResultDirectedEdges();
  29190. }
  29191. };
  29192. var PolygonBuilder = function PolygonBuilder () {
  29193. this._geometryFactory = null;
  29194. this._shellList = new ArrayList();
  29195. var geometryFactory = arguments[0];
  29196. this._geometryFactory = geometryFactory;
  29197. };
  29198. PolygonBuilder.prototype.sortShellsAndHoles = function sortShellsAndHoles (edgeRings, shellList, freeHoleList) {
  29199. for (var it = edgeRings.iterator(); it.hasNext();) {
  29200. var er = it.next();
  29201. if (er.isHole()) {
  29202. freeHoleList.add(er);
  29203. } else {
  29204. shellList.add(er);
  29205. }
  29206. }
  29207. };
  29208. PolygonBuilder.prototype.computePolygons = function computePolygons (shellList) {
  29209. var this$1 = this;
  29210. var resultPolyList = new ArrayList();
  29211. for (var it = shellList.iterator(); it.hasNext();) {
  29212. var er = it.next();
  29213. var poly = er.toPolygon(this$1._geometryFactory);
  29214. resultPolyList.add(poly);
  29215. }
  29216. return resultPolyList
  29217. };
  29218. PolygonBuilder.prototype.placeFreeHoles = function placeFreeHoles (shellList, freeHoleList) {
  29219. var this$1 = this;
  29220. for (var it = freeHoleList.iterator(); it.hasNext();) {
  29221. var hole = it.next();
  29222. if (hole.getShell() === null) {
  29223. var shell = this$1.findEdgeRingContaining(hole, shellList);
  29224. if (shell === null) { throw new TopologyException('unable to assign hole to a shell', hole.getCoordinate(0)) }
  29225. hole.setShell(shell);
  29226. }
  29227. }
  29228. };
  29229. PolygonBuilder.prototype.buildMinimalEdgeRings = function buildMinimalEdgeRings (maxEdgeRings, shellList, freeHoleList) {
  29230. var this$1 = this;
  29231. var edgeRings = new ArrayList();
  29232. for (var it = maxEdgeRings.iterator(); it.hasNext();) {
  29233. var er = it.next();
  29234. if (er.getMaxNodeDegree() > 2) {
  29235. er.linkDirectedEdgesForMinimalEdgeRings();
  29236. var minEdgeRings = er.buildMinimalRings();
  29237. var shell = this$1.findShell(minEdgeRings);
  29238. if (shell !== null) {
  29239. this$1.placePolygonHoles(shell, minEdgeRings);
  29240. shellList.add(shell);
  29241. } else {
  29242. freeHoleList.addAll(minEdgeRings);
  29243. }
  29244. } else {
  29245. edgeRings.add(er);
  29246. }
  29247. }
  29248. return edgeRings
  29249. };
  29250. PolygonBuilder.prototype.containsPoint = function containsPoint (p) {
  29251. for (var it = this._shellList.iterator(); it.hasNext();) {
  29252. var er = it.next();
  29253. if (er.containsPoint(p)) { return true }
  29254. }
  29255. return false
  29256. };
  29257. PolygonBuilder.prototype.buildMaximalEdgeRings = function buildMaximalEdgeRings (dirEdges) {
  29258. var this$1 = this;
  29259. var maxEdgeRings = new ArrayList();
  29260. for (var it = dirEdges.iterator(); it.hasNext();) {
  29261. var de = it.next();
  29262. if (de.isInResult() && de.getLabel().isArea()) {
  29263. if (de.getEdgeRing() === null) {
  29264. var er = new MaximalEdgeRing(de, this$1._geometryFactory);
  29265. maxEdgeRings.add(er);
  29266. er.setInResult();
  29267. }
  29268. }
  29269. }
  29270. return maxEdgeRings
  29271. };
  29272. PolygonBuilder.prototype.placePolygonHoles = function placePolygonHoles (shell, minEdgeRings) {
  29273. for (var it = minEdgeRings.iterator(); it.hasNext();) {
  29274. var er = it.next();
  29275. if (er.isHole()) {
  29276. er.setShell(shell);
  29277. }
  29278. }
  29279. };
  29280. PolygonBuilder.prototype.getPolygons = function getPolygons () {
  29281. var resultPolyList = this.computePolygons(this._shellList);
  29282. return resultPolyList
  29283. };
  29284. PolygonBuilder.prototype.findEdgeRingContaining = function findEdgeRingContaining (testEr, shellList) {
  29285. var testRing = testEr.getLinearRing();
  29286. var testEnv = testRing.getEnvelopeInternal();
  29287. var testPt = testRing.getCoordinateN(0);
  29288. var minShell = null;
  29289. var minEnv = null;
  29290. for (var it = shellList.iterator(); it.hasNext();) {
  29291. var tryShell = it.next();
  29292. var tryRing = tryShell.getLinearRing();
  29293. var tryEnv = tryRing.getEnvelopeInternal();
  29294. if (minShell !== null) { minEnv = minShell.getLinearRing().getEnvelopeInternal(); }
  29295. var isContained = false;
  29296. if (tryEnv.contains(testEnv) && CGAlgorithms.isPointInRing(testPt, tryRing.getCoordinates())) { isContained = true; }
  29297. if (isContained) {
  29298. if (minShell === null || minEnv.contains(tryEnv)) {
  29299. minShell = tryShell;
  29300. }
  29301. }
  29302. }
  29303. return minShell
  29304. };
  29305. PolygonBuilder.prototype.findShell = function findShell (minEdgeRings) {
  29306. var shellCount = 0;
  29307. var shell = null;
  29308. for (var it = minEdgeRings.iterator(); it.hasNext();) {
  29309. var er = it.next();
  29310. if (!er.isHole()) {
  29311. shell = er;
  29312. shellCount++;
  29313. }
  29314. }
  29315. Assert.isTrue(shellCount <= 1, 'found two shells in MinimalEdgeRing list');
  29316. return shell
  29317. };
  29318. PolygonBuilder.prototype.add = function add () {
  29319. if (arguments.length === 1) {
  29320. var graph = arguments[0];
  29321. this.add(graph.getEdgeEnds(), graph.getNodes());
  29322. } else if (arguments.length === 2) {
  29323. var dirEdges = arguments[0];
  29324. var nodes = arguments[1];
  29325. PlanarGraph.linkResultDirectedEdges(nodes);
  29326. var maxEdgeRings = this.buildMaximalEdgeRings(dirEdges);
  29327. var freeHoleList = new ArrayList();
  29328. var edgeRings = this.buildMinimalEdgeRings(maxEdgeRings, this._shellList, freeHoleList);
  29329. this.sortShellsAndHoles(edgeRings, this._shellList, freeHoleList);
  29330. this.placeFreeHoles(this._shellList, freeHoleList);
  29331. }
  29332. };
  29333. PolygonBuilder.prototype.interfaces_ = function interfaces_ () {
  29334. return []
  29335. };
  29336. PolygonBuilder.prototype.getClass = function getClass () {
  29337. return PolygonBuilder
  29338. };
  29339. var Boundable = function Boundable () {};
  29340. Boundable.prototype.getBounds = function getBounds () {};
  29341. Boundable.prototype.interfaces_ = function interfaces_ () {
  29342. return []
  29343. };
  29344. Boundable.prototype.getClass = function getClass () {
  29345. return Boundable
  29346. };
  29347. var ItemBoundable = function ItemBoundable () {
  29348. this._bounds = null;
  29349. this._item = null;
  29350. var bounds = arguments[0];
  29351. var item = arguments[1];
  29352. this._bounds = bounds;
  29353. this._item = item;
  29354. };
  29355. ItemBoundable.prototype.getItem = function getItem () {
  29356. return this._item
  29357. };
  29358. ItemBoundable.prototype.getBounds = function getBounds () {
  29359. return this._bounds
  29360. };
  29361. ItemBoundable.prototype.interfaces_ = function interfaces_ () {
  29362. return [Boundable, Serializable]
  29363. };
  29364. ItemBoundable.prototype.getClass = function getClass () {
  29365. return ItemBoundable
  29366. };
  29367. var PriorityQueue = function PriorityQueue () {
  29368. this._size = null;
  29369. this._items = null;
  29370. this._size = 0;
  29371. this._items = new ArrayList();
  29372. this._items.add(null);
  29373. };
  29374. PriorityQueue.prototype.poll = function poll () {
  29375. if (this.isEmpty()) { return null }
  29376. var minItem = this._items.get(1);
  29377. this._items.set(1, this._items.get(this._size));
  29378. this._size -= 1;
  29379. this.reorder(1);
  29380. return minItem
  29381. };
  29382. PriorityQueue.prototype.size = function size () {
  29383. return this._size
  29384. };
  29385. PriorityQueue.prototype.reorder = function reorder (hole) {
  29386. var this$1 = this;
  29387. var child = null;
  29388. var tmp = this._items.get(hole);
  29389. for (; hole * 2 <= this._size; hole = child) {
  29390. child = hole * 2;
  29391. if (child !== this$1._size && this$1._items.get(child + 1).compareTo(this$1._items.get(child)) < 0) { child++; }
  29392. if (this$1._items.get(child).compareTo(tmp) < 0) { this$1._items.set(hole, this$1._items.get(child)); } else { break }
  29393. }
  29394. this._items.set(hole, tmp);
  29395. };
  29396. PriorityQueue.prototype.clear = function clear () {
  29397. this._size = 0;
  29398. this._items.clear();
  29399. };
  29400. PriorityQueue.prototype.isEmpty = function isEmpty () {
  29401. return this._size === 0
  29402. };
  29403. PriorityQueue.prototype.add = function add (x) {
  29404. var this$1 = this;
  29405. this._items.add(null);
  29406. this._size += 1;
  29407. var hole = this._size;
  29408. this._items.set(0, x);
  29409. for (; x.compareTo(this._items.get(Math.trunc(hole / 2))) < 0; hole /= 2) {
  29410. this$1._items.set(hole, this$1._items.get(Math.trunc(hole / 2)));
  29411. }
  29412. this._items.set(hole, x);
  29413. };
  29414. PriorityQueue.prototype.interfaces_ = function interfaces_ () {
  29415. return []
  29416. };
  29417. PriorityQueue.prototype.getClass = function getClass () {
  29418. return PriorityQueue
  29419. };
  29420. var ItemVisitor = function ItemVisitor () {};
  29421. ItemVisitor.prototype.visitItem = function visitItem (item) {};
  29422. ItemVisitor.prototype.interfaces_ = function interfaces_ () {
  29423. return []
  29424. };
  29425. ItemVisitor.prototype.getClass = function getClass () {
  29426. return ItemVisitor
  29427. };
  29428. var SpatialIndex = function SpatialIndex () {};
  29429. SpatialIndex.prototype.insert = function insert (itemEnv, item) {};
  29430. SpatialIndex.prototype.remove = function remove (itemEnv, item) {};
  29431. SpatialIndex.prototype.query = function query () {
  29432. // if (arguments.length === 1) {
  29433. // const searchEnv = arguments[0]
  29434. // } else if (arguments.length === 2) {
  29435. // const searchEnv = arguments[0]
  29436. // const visitor = arguments[1]
  29437. // }
  29438. };
  29439. SpatialIndex.prototype.interfaces_ = function interfaces_ () {
  29440. return []
  29441. };
  29442. SpatialIndex.prototype.getClass = function getClass () {
  29443. return SpatialIndex
  29444. };
  29445. var AbstractNode = function AbstractNode () {
  29446. this._childBoundables = new ArrayList();
  29447. this._bounds = null;
  29448. this._level = null;
  29449. if (arguments.length === 0) {} else if (arguments.length === 1) {
  29450. var level = arguments[0];
  29451. this._level = level;
  29452. }
  29453. };
  29454. var staticAccessors$22 = { serialVersionUID: { configurable: true } };
  29455. AbstractNode.prototype.getLevel = function getLevel () {
  29456. return this._level
  29457. };
  29458. AbstractNode.prototype.size = function size () {
  29459. return this._childBoundables.size()
  29460. };
  29461. AbstractNode.prototype.getChildBoundables = function getChildBoundables () {
  29462. return this._childBoundables
  29463. };
  29464. AbstractNode.prototype.addChildBoundable = function addChildBoundable (childBoundable) {
  29465. Assert.isTrue(this._bounds === null);
  29466. this._childBoundables.add(childBoundable);
  29467. };
  29468. AbstractNode.prototype.isEmpty = function isEmpty () {
  29469. return this._childBoundables.isEmpty()
  29470. };
  29471. AbstractNode.prototype.getBounds = function getBounds () {
  29472. if (this._bounds === null) {
  29473. this._bounds = this.computeBounds();
  29474. }
  29475. return this._bounds
  29476. };
  29477. AbstractNode.prototype.interfaces_ = function interfaces_ () {
  29478. return [Boundable, Serializable]
  29479. };
  29480. AbstractNode.prototype.getClass = function getClass () {
  29481. return AbstractNode
  29482. };
  29483. staticAccessors$22.serialVersionUID.get = function () { return 6493722185909573708 };
  29484. Object.defineProperties( AbstractNode, staticAccessors$22 );
  29485. var Collections = function Collections () {};
  29486. Collections.reverseOrder = function reverseOrder () {
  29487. return {
  29488. compare: function compare (a, b) {
  29489. return b.compareTo(a)
  29490. }
  29491. }
  29492. };
  29493. Collections.min = function min (l) {
  29494. Collections.sort(l);
  29495. return l.get(0)
  29496. };
  29497. Collections.sort = function sort (l, c) {
  29498. var a = l.toArray();
  29499. if (c) {
  29500. Arrays.sort(a, c);
  29501. } else {
  29502. Arrays.sort(a);
  29503. }
  29504. var i = l.iterator();
  29505. for (var pos = 0, alen = a.length; pos < alen; pos++) {
  29506. i.next();
  29507. i.set(a[pos]);
  29508. }
  29509. };
  29510. Collections.singletonList = function singletonList (o) {
  29511. var arrayList = new ArrayList();
  29512. arrayList.add(o);
  29513. return arrayList
  29514. };
  29515. var BoundablePair = function BoundablePair () {
  29516. this._boundable1 = null;
  29517. this._boundable2 = null;
  29518. this._distance = null;
  29519. this._itemDistance = null;
  29520. var boundable1 = arguments[0];
  29521. var boundable2 = arguments[1];
  29522. var itemDistance = arguments[2];
  29523. this._boundable1 = boundable1;
  29524. this._boundable2 = boundable2;
  29525. this._itemDistance = itemDistance;
  29526. this._distance = this.distance();
  29527. };
  29528. BoundablePair.prototype.expandToQueue = function expandToQueue (priQ, minDistance) {
  29529. var isComp1 = BoundablePair.isComposite(this._boundable1);
  29530. var isComp2 = BoundablePair.isComposite(this._boundable2);
  29531. if (isComp1 && isComp2) {
  29532. if (BoundablePair.area(this._boundable1) > BoundablePair.area(this._boundable2)) {
  29533. this.expand(this._boundable1, this._boundable2, priQ, minDistance);
  29534. return null
  29535. } else {
  29536. this.expand(this._boundable2, this._boundable1, priQ, minDistance);
  29537. return null
  29538. }
  29539. } else if (isComp1) {
  29540. this.expand(this._boundable1, this._boundable2, priQ, minDistance);
  29541. return null
  29542. } else if (isComp2) {
  29543. this.expand(this._boundable2, this._boundable1, priQ, minDistance);
  29544. return null
  29545. }
  29546. throw new IllegalArgumentException('neither boundable is composite')
  29547. };
  29548. BoundablePair.prototype.isLeaves = function isLeaves () {
  29549. return !(BoundablePair.isComposite(this._boundable1) || BoundablePair.isComposite(this._boundable2))
  29550. };
  29551. BoundablePair.prototype.compareTo = function compareTo (o) {
  29552. var nd = o;
  29553. if (this._distance < nd._distance) { return -1 }
  29554. if (this._distance > nd._distance) { return 1 }
  29555. return 0
  29556. };
  29557. BoundablePair.prototype.expand = function expand (bndComposite, bndOther, priQ, minDistance) {
  29558. var this$1 = this;
  29559. var children = bndComposite.getChildBoundables();
  29560. for (var i = children.iterator(); i.hasNext();) {
  29561. var child = i.next();
  29562. var bp = new BoundablePair(child, bndOther, this$1._itemDistance);
  29563. if (bp.getDistance() < minDistance) {
  29564. priQ.add(bp);
  29565. }
  29566. }
  29567. };
  29568. BoundablePair.prototype.getBoundable = function getBoundable (i) {
  29569. if (i === 0) { return this._boundable1 }
  29570. return this._boundable2
  29571. };
  29572. BoundablePair.prototype.getDistance = function getDistance () {
  29573. return this._distance
  29574. };
  29575. BoundablePair.prototype.distance = function distance () {
  29576. if (this.isLeaves()) {
  29577. return this._itemDistance.distance(this._boundable1, this._boundable2)
  29578. }
  29579. return this._boundable1.getBounds().distance(this._boundable2.getBounds())
  29580. };
  29581. BoundablePair.prototype.interfaces_ = function interfaces_ () {
  29582. return [Comparable]
  29583. };
  29584. BoundablePair.prototype.getClass = function getClass () {
  29585. return BoundablePair
  29586. };
  29587. BoundablePair.area = function area (b) {
  29588. return b.getBounds().getArea()
  29589. };
  29590. BoundablePair.isComposite = function isComposite (item) {
  29591. return item instanceof AbstractNode
  29592. };
  29593. var AbstractSTRtree = function AbstractSTRtree () {
  29594. this._root = null;
  29595. this._built = false;
  29596. this._itemBoundables = new ArrayList();
  29597. this._nodeCapacity = null;
  29598. if (arguments.length === 0) {
  29599. var nodeCapacity = AbstractSTRtree.DEFAULT_NODE_CAPACITY;
  29600. this._nodeCapacity = nodeCapacity;
  29601. } else if (arguments.length === 1) {
  29602. var nodeCapacity$1 = arguments[0];
  29603. Assert.isTrue(nodeCapacity$1 > 1, 'Node capacity must be greater than 1');
  29604. this._nodeCapacity = nodeCapacity$1;
  29605. }
  29606. };
  29607. var staticAccessors$23 = { IntersectsOp: { configurable: true },serialVersionUID: { configurable: true },DEFAULT_NODE_CAPACITY: { configurable: true } };
  29608. AbstractSTRtree.prototype.getNodeCapacity = function getNodeCapacity () {
  29609. return this._nodeCapacity
  29610. };
  29611. AbstractSTRtree.prototype.lastNode = function lastNode (nodes) {
  29612. return nodes.get(nodes.size() - 1)
  29613. };
  29614. AbstractSTRtree.prototype.size = function size () {
  29615. var this$1 = this;
  29616. if (arguments.length === 0) {
  29617. if (this.isEmpty()) {
  29618. return 0
  29619. }
  29620. this.build();
  29621. return this.size(this._root)
  29622. } else if (arguments.length === 1) {
  29623. var node = arguments[0];
  29624. var size = 0;
  29625. for (var i = node.getChildBoundables().iterator(); i.hasNext();) {
  29626. var childBoundable = i.next();
  29627. if (childBoundable instanceof AbstractNode) {
  29628. size += this$1.size(childBoundable);
  29629. } else if (childBoundable instanceof ItemBoundable) {
  29630. size += 1;
  29631. }
  29632. }
  29633. return size
  29634. }
  29635. };
  29636. AbstractSTRtree.prototype.removeItem = function removeItem (node, item) {
  29637. var childToRemove = null;
  29638. for (var i = node.getChildBoundables().iterator(); i.hasNext();) {
  29639. var childBoundable = i.next();
  29640. if (childBoundable instanceof ItemBoundable) {
  29641. if (childBoundable.getItem() === item) { childToRemove = childBoundable; }
  29642. }
  29643. }
  29644. if (childToRemove !== null) {
  29645. node.getChildBoundables().remove(childToRemove);
  29646. return true
  29647. }
  29648. return false
  29649. };
  29650. AbstractSTRtree.prototype.itemsTree = function itemsTree () {
  29651. var this$1 = this;
  29652. if (arguments.length === 0) {
  29653. this.build();
  29654. var valuesTree = this.itemsTree(this._root);
  29655. if (valuesTree === null) { return new ArrayList() }
  29656. return valuesTree
  29657. } else if (arguments.length === 1) {
  29658. var node = arguments[0];
  29659. var valuesTreeForNode = new ArrayList();
  29660. for (var i = node.getChildBoundables().iterator(); i.hasNext();) {
  29661. var childBoundable = i.next();
  29662. if (childBoundable instanceof AbstractNode) {
  29663. var valuesTreeForChild = this$1.itemsTree(childBoundable);
  29664. if (valuesTreeForChild !== null) { valuesTreeForNode.add(valuesTreeForChild); }
  29665. } else if (childBoundable instanceof ItemBoundable) {
  29666. valuesTreeForNode.add(childBoundable.getItem());
  29667. } else {
  29668. Assert.shouldNeverReachHere();
  29669. }
  29670. }
  29671. if (valuesTreeForNode.size() <= 0) { return null }
  29672. return valuesTreeForNode
  29673. }
  29674. };
  29675. AbstractSTRtree.prototype.insert = function insert (bounds, item) {
  29676. Assert.isTrue(!this._built, 'Cannot insert items into an STR packed R-tree after it has been built.');
  29677. this._itemBoundables.add(new ItemBoundable(bounds, item));
  29678. };
  29679. AbstractSTRtree.prototype.boundablesAtLevel = function boundablesAtLevel () {
  29680. var this$1 = this;
  29681. if (arguments.length === 1) {
  29682. var level = arguments[0];
  29683. var boundables = new ArrayList();
  29684. this.boundablesAtLevel(level, this._root, boundables);
  29685. return boundables
  29686. } else if (arguments.length === 3) {
  29687. var level$1 = arguments[0];
  29688. var top = arguments[1];
  29689. var boundables$1 = arguments[2];
  29690. Assert.isTrue(level$1 > -2);
  29691. if (top.getLevel() === level$1) {
  29692. boundables$1.add(top);
  29693. return null
  29694. }
  29695. for (var i = top.getChildBoundables().iterator(); i.hasNext();) {
  29696. var boundable = i.next();
  29697. if (boundable instanceof AbstractNode) {
  29698. this$1.boundablesAtLevel(level$1, boundable, boundables$1);
  29699. } else {
  29700. Assert.isTrue(boundable instanceof ItemBoundable);
  29701. if (level$1 === -1) {
  29702. boundables$1.add(boundable);
  29703. }
  29704. }
  29705. }
  29706. return null
  29707. }
  29708. };
  29709. AbstractSTRtree.prototype.query = function query () {
  29710. var this$1 = this;
  29711. if (arguments.length === 1) {
  29712. var searchBounds = arguments[0];
  29713. this.build();
  29714. var matches = new ArrayList();
  29715. if (this.isEmpty()) {
  29716. return matches
  29717. }
  29718. if (this.getIntersectsOp().intersects(this._root.getBounds(), searchBounds)) {
  29719. this.query(searchBounds, this._root, matches);
  29720. }
  29721. return matches
  29722. } else if (arguments.length === 2) {
  29723. var searchBounds$1 = arguments[0];
  29724. var visitor = arguments[1];
  29725. this.build();
  29726. if (this.isEmpty()) {
  29727. return null
  29728. }
  29729. if (this.getIntersectsOp().intersects(this._root.getBounds(), searchBounds$1)) {
  29730. this.query(searchBounds$1, this._root, visitor);
  29731. }
  29732. } else if (arguments.length === 3) {
  29733. if (hasInterface(arguments[2], ItemVisitor) && (arguments[0] instanceof Object && arguments[1] instanceof AbstractNode)) {
  29734. var searchBounds$2 = arguments[0];
  29735. var node = arguments[1];
  29736. var visitor$1 = arguments[2];
  29737. var childBoundables = node.getChildBoundables();
  29738. for (var i = 0; i < childBoundables.size(); i++) {
  29739. var childBoundable = childBoundables.get(i);
  29740. if (!this$1.getIntersectsOp().intersects(childBoundable.getBounds(), searchBounds$2)) {
  29741. continue
  29742. }
  29743. if (childBoundable instanceof AbstractNode) {
  29744. this$1.query(searchBounds$2, childBoundable, visitor$1);
  29745. } else if (childBoundable instanceof ItemBoundable) {
  29746. visitor$1.visitItem(childBoundable.getItem());
  29747. } else {
  29748. Assert.shouldNeverReachHere();
  29749. }
  29750. }
  29751. } else if (hasInterface(arguments[2], List) && (arguments[0] instanceof Object && arguments[1] instanceof AbstractNode)) {
  29752. var searchBounds$3 = arguments[0];
  29753. var node$1 = arguments[1];
  29754. var matches$1 = arguments[2];
  29755. var childBoundables$1 = node$1.getChildBoundables();
  29756. for (var i$1 = 0; i$1 < childBoundables$1.size(); i$1++) {
  29757. var childBoundable$1 = childBoundables$1.get(i$1);
  29758. if (!this$1.getIntersectsOp().intersects(childBoundable$1.getBounds(), searchBounds$3)) {
  29759. continue
  29760. }
  29761. if (childBoundable$1 instanceof AbstractNode) {
  29762. this$1.query(searchBounds$3, childBoundable$1, matches$1);
  29763. } else if (childBoundable$1 instanceof ItemBoundable) {
  29764. matches$1.add(childBoundable$1.getItem());
  29765. } else {
  29766. Assert.shouldNeverReachHere();
  29767. }
  29768. }
  29769. }
  29770. }
  29771. };
  29772. AbstractSTRtree.prototype.build = function build () {
  29773. if (this._built) { return null }
  29774. this._root = this._itemBoundables.isEmpty() ? this.createNode(0) : this.createHigherLevels(this._itemBoundables, -1);
  29775. this._itemBoundables = null;
  29776. this._built = true;
  29777. };
  29778. AbstractSTRtree.prototype.getRoot = function getRoot () {
  29779. this.build();
  29780. return this._root
  29781. };
  29782. AbstractSTRtree.prototype.remove = function remove () {
  29783. var this$1 = this;
  29784. if (arguments.length === 2) {
  29785. var searchBounds = arguments[0];
  29786. var item = arguments[1];
  29787. this.build();
  29788. if (this.getIntersectsOp().intersects(this._root.getBounds(), searchBounds)) {
  29789. return this.remove(searchBounds, this._root, item)
  29790. }
  29791. return false
  29792. } else if (arguments.length === 3) {
  29793. var searchBounds$1 = arguments[0];
  29794. var node = arguments[1];
  29795. var item$1 = arguments[2];
  29796. var found = this.removeItem(node, item$1);
  29797. if (found) { return true }
  29798. var childToPrune = null;
  29799. for (var i = node.getChildBoundables().iterator(); i.hasNext();) {
  29800. var childBoundable = i.next();
  29801. if (!this$1.getIntersectsOp().intersects(childBoundable.getBounds(), searchBounds$1)) {
  29802. continue
  29803. }
  29804. if (childBoundable instanceof AbstractNode) {
  29805. found = this$1.remove(searchBounds$1, childBoundable, item$1);
  29806. if (found) {
  29807. childToPrune = childBoundable;
  29808. break
  29809. }
  29810. }
  29811. }
  29812. if (childToPrune !== null) {
  29813. if (childToPrune.getChildBoundables().isEmpty()) {
  29814. node.getChildBoundables().remove(childToPrune);
  29815. }
  29816. }
  29817. return found
  29818. }
  29819. };
  29820. AbstractSTRtree.prototype.createHigherLevels = function createHigherLevels (boundablesOfALevel, level) {
  29821. Assert.isTrue(!boundablesOfALevel.isEmpty());
  29822. var parentBoundables = this.createParentBoundables(boundablesOfALevel, level + 1);
  29823. if (parentBoundables.size() === 1) {
  29824. return parentBoundables.get(0)
  29825. }
  29826. return this.createHigherLevels(parentBoundables, level + 1)
  29827. };
  29828. AbstractSTRtree.prototype.depth = function depth () {
  29829. var this$1 = this;
  29830. if (arguments.length === 0) {
  29831. if (this.isEmpty()) {
  29832. return 0
  29833. }
  29834. this.build();
  29835. return this.depth(this._root)
  29836. } else if (arguments.length === 1) {
  29837. var node = arguments[0];
  29838. var maxChildDepth = 0;
  29839. for (var i = node.getChildBoundables().iterator(); i.hasNext();) {
  29840. var childBoundable = i.next();
  29841. if (childBoundable instanceof AbstractNode) {
  29842. var childDepth = this$1.depth(childBoundable);
  29843. if (childDepth > maxChildDepth) { maxChildDepth = childDepth; }
  29844. }
  29845. }
  29846. return maxChildDepth + 1
  29847. }
  29848. };
  29849. AbstractSTRtree.prototype.createParentBoundables = function createParentBoundables (childBoundables, newLevel) {
  29850. var this$1 = this;
  29851. Assert.isTrue(!childBoundables.isEmpty());
  29852. var parentBoundables = new ArrayList();
  29853. parentBoundables.add(this.createNode(newLevel));
  29854. var sortedChildBoundables = new ArrayList(childBoundables);
  29855. Collections.sort(sortedChildBoundables, this.getComparator());
  29856. for (var i = sortedChildBoundables.iterator(); i.hasNext();) {
  29857. var childBoundable = i.next();
  29858. if (this$1.lastNode(parentBoundables).getChildBoundables().size() === this$1.getNodeCapacity()) {
  29859. parentBoundables.add(this$1.createNode(newLevel));
  29860. }
  29861. this$1.lastNode(parentBoundables).addChildBoundable(childBoundable);
  29862. }
  29863. return parentBoundables
  29864. };
  29865. AbstractSTRtree.prototype.isEmpty = function isEmpty () {
  29866. if (!this._built) { return this._itemBoundables.isEmpty() }
  29867. return this._root.isEmpty()
  29868. };
  29869. AbstractSTRtree.prototype.interfaces_ = function interfaces_ () {
  29870. return [Serializable]
  29871. };
  29872. AbstractSTRtree.prototype.getClass = function getClass () {
  29873. return AbstractSTRtree
  29874. };
  29875. AbstractSTRtree.compareDoubles = function compareDoubles (a, b) {
  29876. return a > b ? 1 : a < b ? -1 : 0
  29877. };
  29878. staticAccessors$23.IntersectsOp.get = function () { return IntersectsOp };
  29879. staticAccessors$23.serialVersionUID.get = function () { return -3886435814360241337 };
  29880. staticAccessors$23.DEFAULT_NODE_CAPACITY.get = function () { return 10 };
  29881. Object.defineProperties( AbstractSTRtree, staticAccessors$23 );
  29882. var IntersectsOp = function IntersectsOp () {};
  29883. var ItemDistance = function ItemDistance () {};
  29884. ItemDistance.prototype.distance = function distance (item1, item2) {};
  29885. ItemDistance.prototype.interfaces_ = function interfaces_ () {
  29886. return []
  29887. };
  29888. ItemDistance.prototype.getClass = function getClass () {
  29889. return ItemDistance
  29890. };
  29891. var STRtree = (function (AbstractSTRtree$$1) {
  29892. function STRtree (nodeCapacity) {
  29893. nodeCapacity = nodeCapacity || STRtree.DEFAULT_NODE_CAPACITY;
  29894. AbstractSTRtree$$1.call(this, nodeCapacity);
  29895. }
  29896. if ( AbstractSTRtree$$1 ) STRtree.__proto__ = AbstractSTRtree$$1;
  29897. STRtree.prototype = Object.create( AbstractSTRtree$$1 && AbstractSTRtree$$1.prototype );
  29898. STRtree.prototype.constructor = STRtree;
  29899. var staticAccessors = { STRtreeNode: { configurable: true },serialVersionUID: { configurable: true },xComparator: { configurable: true },yComparator: { configurable: true },intersectsOp: { configurable: true },DEFAULT_NODE_CAPACITY: { configurable: true } };
  29900. STRtree.prototype.createParentBoundablesFromVerticalSlices = function createParentBoundablesFromVerticalSlices (verticalSlices, newLevel) {
  29901. var this$1 = this;
  29902. Assert.isTrue(verticalSlices.length > 0);
  29903. var parentBoundables = new ArrayList();
  29904. for (var i = 0; i < verticalSlices.length; i++) {
  29905. parentBoundables.addAll(this$1.createParentBoundablesFromVerticalSlice(verticalSlices[i], newLevel));
  29906. }
  29907. return parentBoundables
  29908. };
  29909. STRtree.prototype.createNode = function createNode (level) {
  29910. return new STRtreeNode(level)
  29911. };
  29912. STRtree.prototype.size = function size () {
  29913. if (arguments.length === 0) {
  29914. return AbstractSTRtree$$1.prototype.size.call(this)
  29915. } else { return AbstractSTRtree$$1.prototype.size.apply(this, arguments) }
  29916. };
  29917. STRtree.prototype.insert = function insert () {
  29918. if (arguments.length === 2) {
  29919. var itemEnv = arguments[0];
  29920. var item = arguments[1];
  29921. if (itemEnv.isNull()) {
  29922. return null
  29923. }
  29924. AbstractSTRtree$$1.prototype.insert.call(this, itemEnv, item);
  29925. } else { return AbstractSTRtree$$1.prototype.insert.apply(this, arguments) }
  29926. };
  29927. STRtree.prototype.getIntersectsOp = function getIntersectsOp () {
  29928. return STRtree.intersectsOp
  29929. };
  29930. STRtree.prototype.verticalSlices = function verticalSlices (childBoundables, sliceCount) {
  29931. var sliceCapacity = Math.trunc(Math.ceil(childBoundables.size() / sliceCount));
  29932. var slices = new Array(sliceCount).fill(null);
  29933. var i = childBoundables.iterator();
  29934. for (var j = 0; j < sliceCount; j++) {
  29935. slices[j] = new ArrayList();
  29936. var boundablesAddedToSlice = 0;
  29937. while (i.hasNext() && boundablesAddedToSlice < sliceCapacity) {
  29938. var childBoundable = i.next();
  29939. slices[j].add(childBoundable);
  29940. boundablesAddedToSlice++;
  29941. }
  29942. }
  29943. return slices
  29944. };
  29945. STRtree.prototype.query = function query () {
  29946. if (arguments.length === 1) {
  29947. var searchEnv = arguments[0];
  29948. return AbstractSTRtree$$1.prototype.query.call(this, searchEnv)
  29949. } else if (arguments.length === 2) {
  29950. var searchEnv$1 = arguments[0];
  29951. var visitor = arguments[1];
  29952. AbstractSTRtree$$1.prototype.query.call(this, searchEnv$1, visitor);
  29953. } else if (arguments.length === 3) {
  29954. if (hasInterface(arguments[2], ItemVisitor) && (arguments[0] instanceof Object && arguments[1] instanceof AbstractNode)) {
  29955. var searchBounds = arguments[0];
  29956. var node = arguments[1];
  29957. var visitor$1 = arguments[2];
  29958. AbstractSTRtree$$1.prototype.query.call(this, searchBounds, node, visitor$1);
  29959. } else if (hasInterface(arguments[2], List) && (arguments[0] instanceof Object && arguments[1] instanceof AbstractNode)) {
  29960. var searchBounds$1 = arguments[0];
  29961. var node$1 = arguments[1];
  29962. var matches = arguments[2];
  29963. AbstractSTRtree$$1.prototype.query.call(this, searchBounds$1, node$1, matches);
  29964. }
  29965. }
  29966. };
  29967. STRtree.prototype.getComparator = function getComparator () {
  29968. return STRtree.yComparator
  29969. };
  29970. STRtree.prototype.createParentBoundablesFromVerticalSlice = function createParentBoundablesFromVerticalSlice (childBoundables, newLevel) {
  29971. return AbstractSTRtree$$1.prototype.createParentBoundables.call(this, childBoundables, newLevel)
  29972. };
  29973. STRtree.prototype.remove = function remove () {
  29974. if (arguments.length === 2) {
  29975. var itemEnv = arguments[0];
  29976. var item = arguments[1];
  29977. return AbstractSTRtree$$1.prototype.remove.call(this, itemEnv, item)
  29978. } else { return AbstractSTRtree$$1.prototype.remove.apply(this, arguments) }
  29979. };
  29980. STRtree.prototype.depth = function depth () {
  29981. if (arguments.length === 0) {
  29982. return AbstractSTRtree$$1.prototype.depth.call(this)
  29983. } else { return AbstractSTRtree$$1.prototype.depth.apply(this, arguments) }
  29984. };
  29985. STRtree.prototype.createParentBoundables = function createParentBoundables (childBoundables, newLevel) {
  29986. Assert.isTrue(!childBoundables.isEmpty());
  29987. var minLeafCount = Math.trunc(Math.ceil(childBoundables.size() / this.getNodeCapacity()));
  29988. var sortedChildBoundables = new ArrayList(childBoundables);
  29989. Collections.sort(sortedChildBoundables, STRtree.xComparator);
  29990. var verticalSlices = this.verticalSlices(sortedChildBoundables, Math.trunc(Math.ceil(Math.sqrt(minLeafCount))));
  29991. return this.createParentBoundablesFromVerticalSlices(verticalSlices, newLevel)
  29992. };
  29993. STRtree.prototype.nearestNeighbour = function nearestNeighbour () {
  29994. if (arguments.length === 1) {
  29995. if (hasInterface(arguments[0], ItemDistance)) {
  29996. var itemDist = arguments[0];
  29997. var bp = new BoundablePair(this.getRoot(), this.getRoot(), itemDist);
  29998. return this.nearestNeighbour(bp)
  29999. } else if (arguments[0] instanceof BoundablePair) {
  30000. var initBndPair = arguments[0];
  30001. return this.nearestNeighbour(initBndPair, Double.POSITIVE_INFINITY)
  30002. }
  30003. } else if (arguments.length === 2) {
  30004. if (arguments[0] instanceof STRtree && hasInterface(arguments[1], ItemDistance)) {
  30005. var tree = arguments[0];
  30006. var itemDist$1 = arguments[1];
  30007. var bp$1 = new BoundablePair(this.getRoot(), tree.getRoot(), itemDist$1);
  30008. return this.nearestNeighbour(bp$1)
  30009. } else if (arguments[0] instanceof BoundablePair && typeof arguments[1] === 'number') {
  30010. var initBndPair$1 = arguments[0];
  30011. var maxDistance = arguments[1];
  30012. var distanceLowerBound = maxDistance;
  30013. var minPair = null;
  30014. var priQ = new PriorityQueue();
  30015. priQ.add(initBndPair$1);
  30016. while (!priQ.isEmpty() && distanceLowerBound > 0.0) {
  30017. var bndPair = priQ.poll();
  30018. var currentDistance = bndPair.getDistance();
  30019. if (currentDistance >= distanceLowerBound) { break }
  30020. if (bndPair.isLeaves()) {
  30021. distanceLowerBound = currentDistance;
  30022. minPair = bndPair;
  30023. } else {
  30024. bndPair.expandToQueue(priQ, distanceLowerBound);
  30025. }
  30026. }
  30027. return [minPair.getBoundable(0).getItem(), minPair.getBoundable(1).getItem()]
  30028. }
  30029. } else if (arguments.length === 3) {
  30030. var env = arguments[0];
  30031. var item = arguments[1];
  30032. var itemDist$2 = arguments[2];
  30033. var bnd = new ItemBoundable(env, item);
  30034. var bp$2 = new BoundablePair(this.getRoot(), bnd, itemDist$2);
  30035. return this.nearestNeighbour(bp$2)[0]
  30036. }
  30037. };
  30038. STRtree.prototype.interfaces_ = function interfaces_ () {
  30039. return [SpatialIndex, Serializable]
  30040. };
  30041. STRtree.prototype.getClass = function getClass () {
  30042. return STRtree
  30043. };
  30044. STRtree.centreX = function centreX (e) {
  30045. return STRtree.avg(e.getMinX(), e.getMaxX())
  30046. };
  30047. STRtree.avg = function avg (a, b) {
  30048. return (a + b) / 2
  30049. };
  30050. STRtree.centreY = function centreY (e) {
  30051. return STRtree.avg(e.getMinY(), e.getMaxY())
  30052. };
  30053. staticAccessors.STRtreeNode.get = function () { return STRtreeNode };
  30054. staticAccessors.serialVersionUID.get = function () { return 259274702368956900 };
  30055. staticAccessors.xComparator.get = function () {
  30056. return {
  30057. interfaces_: function () {
  30058. return [Comparator]
  30059. },
  30060. compare: function (o1, o2) {
  30061. return AbstractSTRtree$$1.compareDoubles(STRtree.centreX(o1.getBounds()), STRtree.centreX(o2.getBounds()))
  30062. }
  30063. }
  30064. };
  30065. staticAccessors.yComparator.get = function () {
  30066. return {
  30067. interfaces_: function () {
  30068. return [Comparator]
  30069. },
  30070. compare: function (o1, o2) {
  30071. return AbstractSTRtree$$1.compareDoubles(STRtree.centreY(o1.getBounds()), STRtree.centreY(o2.getBounds()))
  30072. }
  30073. }
  30074. };
  30075. staticAccessors.intersectsOp.get = function () {
  30076. return {
  30077. interfaces_: function () {
  30078. return [AbstractSTRtree$$1.IntersectsOp]
  30079. },
  30080. intersects: function (aBounds, bBounds) {
  30081. return aBounds.intersects(bBounds)
  30082. }
  30083. }
  30084. };
  30085. staticAccessors.DEFAULT_NODE_CAPACITY.get = function () { return 10 };
  30086. Object.defineProperties( STRtree, staticAccessors );
  30087. return STRtree;
  30088. }(AbstractSTRtree));
  30089. var STRtreeNode = (function (AbstractNode$$1) {
  30090. function STRtreeNode () {
  30091. var level = arguments[0];
  30092. AbstractNode$$1.call(this, level);
  30093. }
  30094. if ( AbstractNode$$1 ) STRtreeNode.__proto__ = AbstractNode$$1;
  30095. STRtreeNode.prototype = Object.create( AbstractNode$$1 && AbstractNode$$1.prototype );
  30096. STRtreeNode.prototype.constructor = STRtreeNode;
  30097. STRtreeNode.prototype.computeBounds = function computeBounds () {
  30098. var bounds = null;
  30099. for (var i = this.getChildBoundables().iterator(); i.hasNext();) {
  30100. var childBoundable = i.next();
  30101. if (bounds === null) {
  30102. bounds = new Envelope(childBoundable.getBounds());
  30103. } else {
  30104. bounds.expandToInclude(childBoundable.getBounds());
  30105. }
  30106. }
  30107. return bounds
  30108. };
  30109. STRtreeNode.prototype.interfaces_ = function interfaces_ () {
  30110. return []
  30111. };
  30112. STRtreeNode.prototype.getClass = function getClass () {
  30113. return STRtreeNode
  30114. };
  30115. return STRtreeNode;
  30116. }(AbstractNode));
  30117. var SegmentPointComparator = function SegmentPointComparator () {};
  30118. SegmentPointComparator.prototype.interfaces_ = function interfaces_ () {
  30119. return []
  30120. };
  30121. SegmentPointComparator.prototype.getClass = function getClass () {
  30122. return SegmentPointComparator
  30123. };
  30124. SegmentPointComparator.relativeSign = function relativeSign (x0, x1) {
  30125. if (x0 < x1) { return -1 }
  30126. if (x0 > x1) { return 1 }
  30127. return 0
  30128. };
  30129. SegmentPointComparator.compare = function compare (octant, p0, p1) {
  30130. if (p0.equals2D(p1)) { return 0 }
  30131. var xSign = SegmentPointComparator.relativeSign(p0.x, p1.x);
  30132. var ySign = SegmentPointComparator.relativeSign(p0.y, p1.y);
  30133. switch (octant) {
  30134. case 0:
  30135. return SegmentPointComparator.compareValue(xSign, ySign)
  30136. case 1:
  30137. return SegmentPointComparator.compareValue(ySign, xSign)
  30138. case 2:
  30139. return SegmentPointComparator.compareValue(ySign, -xSign)
  30140. case 3:
  30141. return SegmentPointComparator.compareValue(-xSign, ySign)
  30142. case 4:
  30143. return SegmentPointComparator.compareValue(-xSign, -ySign)
  30144. case 5:
  30145. return SegmentPointComparator.compareValue(-ySign, -xSign)
  30146. case 6:
  30147. return SegmentPointComparator.compareValue(-ySign, xSign)
  30148. case 7:
  30149. return SegmentPointComparator.compareValue(xSign, -ySign)
  30150. default:
  30151. }
  30152. Assert.shouldNeverReachHere('invalid octant value');
  30153. return 0
  30154. };
  30155. SegmentPointComparator.compareValue = function compareValue (compareSign0, compareSign1) {
  30156. if (compareSign0 < 0) { return -1 }
  30157. if (compareSign0 > 0) { return 1 }
  30158. if (compareSign1 < 0) { return -1 }
  30159. if (compareSign1 > 0) { return 1 }
  30160. return 0
  30161. };
  30162. var SegmentNode = function SegmentNode () {
  30163. this._segString = null;
  30164. this.coord = null;
  30165. this.segmentIndex = null;
  30166. this._segmentOctant = null;
  30167. this._isInterior = null;
  30168. var segString = arguments[0];
  30169. var coord = arguments[1];
  30170. var segmentIndex = arguments[2];
  30171. var segmentOctant = arguments[3];
  30172. this._segString = segString;
  30173. this.coord = new Coordinate(coord);
  30174. this.segmentIndex = segmentIndex;
  30175. this._segmentOctant = segmentOctant;
  30176. this._isInterior = !coord.equals2D(segString.getCoordinate(segmentIndex));
  30177. };
  30178. SegmentNode.prototype.getCoordinate = function getCoordinate () {
  30179. return this.coord
  30180. };
  30181. SegmentNode.prototype.print = function print (out) {
  30182. out.print(this.coord);
  30183. out.print(' seg # = ' + this.segmentIndex);
  30184. };
  30185. SegmentNode.prototype.compareTo = function compareTo (obj) {
  30186. var other = obj;
  30187. if (this.segmentIndex < other.segmentIndex) { return -1 }
  30188. if (this.segmentIndex > other.segmentIndex) { return 1 }
  30189. if (this.coord.equals2D(other.coord)) { return 0 }
  30190. return SegmentPointComparator.compare(this._segmentOctant, this.coord, other.coord)
  30191. };
  30192. SegmentNode.prototype.isEndPoint = function isEndPoint (maxSegmentIndex) {
  30193. if (this.segmentIndex === 0 && !this._isInterior) { return true }
  30194. if (this.segmentIndex === maxSegmentIndex) { return true }
  30195. return false
  30196. };
  30197. SegmentNode.prototype.isInterior = function isInterior () {
  30198. return this._isInterior
  30199. };
  30200. SegmentNode.prototype.interfaces_ = function interfaces_ () {
  30201. return [Comparable]
  30202. };
  30203. SegmentNode.prototype.getClass = function getClass () {
  30204. return SegmentNode
  30205. };
  30206. // import Iterator from '../../../../java/util/Iterator'
  30207. var SegmentNodeList = function SegmentNodeList () {
  30208. this._nodeMap = new TreeMap();
  30209. this._edge = null;
  30210. var edge = arguments[0];
  30211. this._edge = edge;
  30212. };
  30213. SegmentNodeList.prototype.getSplitCoordinates = function getSplitCoordinates () {
  30214. var this$1 = this;
  30215. var coordList = new CoordinateList();
  30216. this.addEndpoints();
  30217. var it = this.iterator();
  30218. var eiPrev = it.next();
  30219. while (it.hasNext()) {
  30220. var ei = it.next();
  30221. this$1.addEdgeCoordinates(eiPrev, ei, coordList);
  30222. eiPrev = ei;
  30223. }
  30224. return coordList.toCoordinateArray()
  30225. };
  30226. SegmentNodeList.prototype.addCollapsedNodes = function addCollapsedNodes () {
  30227. var this$1 = this;
  30228. var collapsedVertexIndexes = new ArrayList();
  30229. this.findCollapsesFromInsertedNodes(collapsedVertexIndexes);
  30230. this.findCollapsesFromExistingVertices(collapsedVertexIndexes);
  30231. for (var it = collapsedVertexIndexes.iterator(); it.hasNext();) {
  30232. var vertexIndex = it.next().intValue();
  30233. this$1.add(this$1._edge.getCoordinate(vertexIndex), vertexIndex);
  30234. }
  30235. };
  30236. SegmentNodeList.prototype.print = function print (out) {
  30237. out.println('Intersections:');
  30238. for (var it = this.iterator(); it.hasNext();) {
  30239. var ei = it.next();
  30240. ei.print(out);
  30241. }
  30242. };
  30243. SegmentNodeList.prototype.findCollapsesFromExistingVertices = function findCollapsesFromExistingVertices (collapsedVertexIndexes) {
  30244. var this$1 = this;
  30245. for (var i = 0; i < this._edge.size() - 2; i++) {
  30246. var p0 = this$1._edge.getCoordinate(i);
  30247. // const p1 = this._edge.getCoordinate(i + 1)
  30248. var p2 = this$1._edge.getCoordinate(i + 2);
  30249. if (p0.equals2D(p2)) {
  30250. collapsedVertexIndexes.add(new Integer(i + 1));
  30251. }
  30252. }
  30253. };
  30254. SegmentNodeList.prototype.addEdgeCoordinates = function addEdgeCoordinates (ei0, ei1, coordList) {
  30255. var this$1 = this;
  30256. // let npts = ei1.segmentIndex - ei0.segmentIndex + 2
  30257. var lastSegStartPt = this._edge.getCoordinate(ei1.segmentIndex);
  30258. var useIntPt1 = ei1.isInterior() || !ei1.coord.equals2D(lastSegStartPt);
  30259. // if (!useIntPt1) {
  30260. // npts--
  30261. // }
  30262. // const ipt = 0
  30263. coordList.add(new Coordinate(ei0.coord), false);
  30264. for (var i = ei0.segmentIndex + 1; i <= ei1.segmentIndex; i++) {
  30265. coordList.add(this$1._edge.getCoordinate(i));
  30266. }
  30267. if (useIntPt1) {
  30268. coordList.add(new Coordinate(ei1.coord));
  30269. }
  30270. };
  30271. SegmentNodeList.prototype.iterator = function iterator () {
  30272. return this._nodeMap.values().iterator()
  30273. };
  30274. SegmentNodeList.prototype.addSplitEdges = function addSplitEdges (edgeList) {
  30275. var this$1 = this;
  30276. this.addEndpoints();
  30277. this.addCollapsedNodes();
  30278. var it = this.iterator();
  30279. var eiPrev = it.next();
  30280. while (it.hasNext()) {
  30281. var ei = it.next();
  30282. var newEdge = this$1.createSplitEdge(eiPrev, ei);
  30283. edgeList.add(newEdge);
  30284. eiPrev = ei;
  30285. }
  30286. };
  30287. SegmentNodeList.prototype.findCollapseIndex = function findCollapseIndex (ei0, ei1, collapsedVertexIndex) {
  30288. if (!ei0.coord.equals2D(ei1.coord)) { return false }
  30289. var numVerticesBetween = ei1.segmentIndex - ei0.segmentIndex;
  30290. if (!ei1.isInterior()) {
  30291. numVerticesBetween--;
  30292. }
  30293. if (numVerticesBetween === 1) {
  30294. collapsedVertexIndex[0] = ei0.segmentIndex + 1;
  30295. return true
  30296. }
  30297. return false
  30298. };
  30299. SegmentNodeList.prototype.findCollapsesFromInsertedNodes = function findCollapsesFromInsertedNodes (collapsedVertexIndexes) {
  30300. var this$1 = this;
  30301. var collapsedVertexIndex = new Array(1).fill(null);
  30302. var it = this.iterator();
  30303. var eiPrev = it.next();
  30304. while (it.hasNext()) {
  30305. var ei = it.next();
  30306. var isCollapsed = this$1.findCollapseIndex(eiPrev, ei, collapsedVertexIndex);
  30307. if (isCollapsed) { collapsedVertexIndexes.add(new Integer(collapsedVertexIndex[0])); }
  30308. eiPrev = ei;
  30309. }
  30310. };
  30311. SegmentNodeList.prototype.getEdge = function getEdge () {
  30312. return this._edge
  30313. };
  30314. SegmentNodeList.prototype.addEndpoints = function addEndpoints () {
  30315. var maxSegIndex = this._edge.size() - 1;
  30316. this.add(this._edge.getCoordinate(0), 0);
  30317. this.add(this._edge.getCoordinate(maxSegIndex), maxSegIndex);
  30318. };
  30319. SegmentNodeList.prototype.createSplitEdge = function createSplitEdge (ei0, ei1) {
  30320. var this$1 = this;
  30321. var npts = ei1.segmentIndex - ei0.segmentIndex + 2;
  30322. var lastSegStartPt = this._edge.getCoordinate(ei1.segmentIndex);
  30323. var useIntPt1 = ei1.isInterior() || !ei1.coord.equals2D(lastSegStartPt);
  30324. if (!useIntPt1) {
  30325. npts--;
  30326. }
  30327. var pts = new Array(npts).fill(null);
  30328. var ipt = 0;
  30329. pts[ipt++] = new Coordinate(ei0.coord);
  30330. for (var i = ei0.segmentIndex + 1; i <= ei1.segmentIndex; i++) {
  30331. pts[ipt++] = this$1._edge.getCoordinate(i);
  30332. }
  30333. if (useIntPt1) { pts[ipt] = new Coordinate(ei1.coord); }
  30334. return new NodedSegmentString(pts, this._edge.getData())
  30335. };
  30336. SegmentNodeList.prototype.add = function add (intPt, segmentIndex) {
  30337. var eiNew = new SegmentNode(this._edge, intPt, segmentIndex, this._edge.getSegmentOctant(segmentIndex));
  30338. var ei = this._nodeMap.get(eiNew);
  30339. if (ei !== null) {
  30340. Assert.isTrue(ei.coord.equals2D(intPt), 'Found equal nodes with different coordinates');
  30341. return ei
  30342. }
  30343. this._nodeMap.put(eiNew, eiNew);
  30344. return eiNew
  30345. };
  30346. SegmentNodeList.prototype.checkSplitEdgesCorrectness = function checkSplitEdgesCorrectness (splitEdges) {
  30347. var edgePts = this._edge.getCoordinates();
  30348. var split0 = splitEdges.get(0);
  30349. var pt0 = split0.getCoordinate(0);
  30350. if (!pt0.equals2D(edgePts[0])) { throw new RuntimeException('bad split edge start point at ' + pt0) }
  30351. var splitn = splitEdges.get(splitEdges.size() - 1);
  30352. var splitnPts = splitn.getCoordinates();
  30353. var ptn = splitnPts[splitnPts.length - 1];
  30354. if (!ptn.equals2D(edgePts[edgePts.length - 1])) { throw new RuntimeException('bad split edge end point at ' + ptn) }
  30355. };
  30356. SegmentNodeList.prototype.interfaces_ = function interfaces_ () {
  30357. return []
  30358. };
  30359. SegmentNodeList.prototype.getClass = function getClass () {
  30360. return SegmentNodeList
  30361. };
  30362. // class NodeVertexIterator {
  30363. // constructor () {
  30364. // this._nodeList = null
  30365. // this._edge = null
  30366. // this._nodeIt = null
  30367. // this._currNode = null
  30368. // this._nextNode = null
  30369. // this._currSegIndex = 0
  30370. // let nodeList = arguments[0]
  30371. // this._nodeList = nodeList
  30372. // this._edge = nodeList.getEdge()
  30373. // this._nodeIt = nodeList.iterator()
  30374. // this.readNextNode()
  30375. // }
  30376. // next () {
  30377. // if (this._currNode === null) {
  30378. // this._currNode = this._nextNode
  30379. // this._currSegIndex = this._currNode.segmentIndex
  30380. // this.readNextNode()
  30381. // return this._currNode
  30382. // }
  30383. // if (this._nextNode === null) return null
  30384. // if (this._nextNode.segmentIndex === this._currNode.segmentIndex) {
  30385. // this._currNode = this._nextNode
  30386. // this._currSegIndex = this._currNode.segmentIndex
  30387. // this.readNextNode()
  30388. // return this._currNode
  30389. // }
  30390. // if (this._nextNode.segmentIndex > this._currNode.segmentIndex) {}
  30391. // return null
  30392. // }
  30393. // remove () {
  30394. // // throw new UnsupportedOperationException(this.getClass().getName())
  30395. // }
  30396. // hasNext () {
  30397. // if (this._nextNode === null) return false
  30398. // return true
  30399. // }
  30400. // readNextNode () {
  30401. // if (this._nodeIt.hasNext()) this._nextNode = this._nodeIt.next(); else this._nextNode = null
  30402. // }
  30403. // interfaces_ () {
  30404. // return [Iterator]
  30405. // }
  30406. // getClass () {
  30407. // return NodeVertexIterator
  30408. // }
  30409. // }
  30410. var Octant = function Octant () {};
  30411. Octant.prototype.interfaces_ = function interfaces_ () {
  30412. return []
  30413. };
  30414. Octant.prototype.getClass = function getClass () {
  30415. return Octant
  30416. };
  30417. Octant.octant = function octant () {
  30418. if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') {
  30419. var dx = arguments[0];
  30420. var dy = arguments[1];
  30421. if (dx === 0.0 && dy === 0.0) { throw new IllegalArgumentException('Cannot compute the octant for point ( ' + dx + ', ' + dy + ' )') }
  30422. var adx = Math.abs(dx);
  30423. var ady = Math.abs(dy);
  30424. if (dx >= 0) {
  30425. if (dy >= 0) {
  30426. if (adx >= ady) { return 0; } else { return 1 }
  30427. } else {
  30428. if (adx >= ady) { return 7; } else { return 6 }
  30429. }
  30430. } else {
  30431. if (dy >= 0) {
  30432. if (adx >= ady) { return 3; } else { return 2 }
  30433. } else {
  30434. if (adx >= ady) { return 4; } else { return 5 }
  30435. }
  30436. }
  30437. } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Coordinate) {
  30438. var p0 = arguments[0];
  30439. var p1 = arguments[1];
  30440. var dx$1 = p1.x - p0.x;
  30441. var dy$1 = p1.y - p0.y;
  30442. if (dx$1 === 0.0 && dy$1 === 0.0) { throw new IllegalArgumentException('Cannot compute the octant for two identical points ' + p0) }
  30443. return Octant.octant(dx$1, dy$1)
  30444. }
  30445. };
  30446. var SegmentString = function SegmentString () {};
  30447. SegmentString.prototype.getCoordinates = function getCoordinates () {};
  30448. SegmentString.prototype.size = function size () {};
  30449. SegmentString.prototype.getCoordinate = function getCoordinate (i) {};
  30450. SegmentString.prototype.isClosed = function isClosed () {};
  30451. SegmentString.prototype.setData = function setData (data) {};
  30452. SegmentString.prototype.getData = function getData () {};
  30453. SegmentString.prototype.interfaces_ = function interfaces_ () {
  30454. return []
  30455. };
  30456. SegmentString.prototype.getClass = function getClass () {
  30457. return SegmentString
  30458. };
  30459. var NodableSegmentString = function NodableSegmentString () {};
  30460. NodableSegmentString.prototype.addIntersection = function addIntersection (intPt, segmentIndex) {};
  30461. NodableSegmentString.prototype.interfaces_ = function interfaces_ () {
  30462. return [SegmentString]
  30463. };
  30464. NodableSegmentString.prototype.getClass = function getClass () {
  30465. return NodableSegmentString
  30466. };
  30467. var NodedSegmentString = function NodedSegmentString () {
  30468. this._nodeList = new SegmentNodeList(this);
  30469. this._pts = null;
  30470. this._data = null;
  30471. var pts = arguments[0];
  30472. var data = arguments[1];
  30473. this._pts = pts;
  30474. this._data = data;
  30475. };
  30476. NodedSegmentString.prototype.getCoordinates = function getCoordinates () {
  30477. return this._pts
  30478. };
  30479. NodedSegmentString.prototype.size = function size () {
  30480. return this._pts.length
  30481. };
  30482. NodedSegmentString.prototype.getCoordinate = function getCoordinate (i) {
  30483. return this._pts[i]
  30484. };
  30485. NodedSegmentString.prototype.isClosed = function isClosed () {
  30486. return this._pts[0].equals(this._pts[this._pts.length - 1])
  30487. };
  30488. NodedSegmentString.prototype.getSegmentOctant = function getSegmentOctant (index) {
  30489. if (index === this._pts.length - 1) { return -1 }
  30490. return this.safeOctant(this.getCoordinate(index), this.getCoordinate(index + 1))
  30491. };
  30492. NodedSegmentString.prototype.setData = function setData (data) {
  30493. this._data = data;
  30494. };
  30495. NodedSegmentString.prototype.safeOctant = function safeOctant (p0, p1) {
  30496. if (p0.equals2D(p1)) { return 0 }
  30497. return Octant.octant(p0, p1)
  30498. };
  30499. NodedSegmentString.prototype.getData = function getData () {
  30500. return this._data
  30501. };
  30502. NodedSegmentString.prototype.addIntersection = function addIntersection () {
  30503. if (arguments.length === 2) {
  30504. var intPt$1 = arguments[0];
  30505. var segmentIndex = arguments[1];
  30506. this.addIntersectionNode(intPt$1, segmentIndex);
  30507. } else if (arguments.length === 4) {
  30508. var li = arguments[0];
  30509. var segmentIndex$1 = arguments[1];
  30510. // const geomIndex = arguments[2]
  30511. var intIndex = arguments[3];
  30512. var intPt = new Coordinate(li.getIntersection(intIndex));
  30513. this.addIntersection(intPt, segmentIndex$1);
  30514. }
  30515. };
  30516. NodedSegmentString.prototype.toString = function toString () {
  30517. return WKTWriter.toLineString(new CoordinateArraySequence(this._pts))
  30518. };
  30519. NodedSegmentString.prototype.getNodeList = function getNodeList () {
  30520. return this._nodeList
  30521. };
  30522. NodedSegmentString.prototype.addIntersectionNode = function addIntersectionNode (intPt, segmentIndex) {
  30523. var normalizedSegmentIndex = segmentIndex;
  30524. var nextSegIndex = normalizedSegmentIndex + 1;
  30525. if (nextSegIndex < this._pts.length) {
  30526. var nextPt = this._pts[nextSegIndex];
  30527. if (intPt.equals2D(nextPt)) {
  30528. normalizedSegmentIndex = nextSegIndex;
  30529. }
  30530. }
  30531. var ei = this._nodeList.add(intPt, normalizedSegmentIndex);
  30532. return ei
  30533. };
  30534. NodedSegmentString.prototype.addIntersections = function addIntersections (li, segmentIndex, geomIndex) {
  30535. var this$1 = this;
  30536. for (var i = 0; i < li.getIntersectionNum(); i++) {
  30537. this$1.addIntersection(li, segmentIndex, geomIndex, i);
  30538. }
  30539. };
  30540. NodedSegmentString.prototype.interfaces_ = function interfaces_ () {
  30541. return [NodableSegmentString]
  30542. };
  30543. NodedSegmentString.prototype.getClass = function getClass () {
  30544. return NodedSegmentString
  30545. };
  30546. NodedSegmentString.getNodedSubstrings = function getNodedSubstrings () {
  30547. if (arguments.length === 1) {
  30548. var segStrings = arguments[0];
  30549. var resultEdgelist = new ArrayList();
  30550. NodedSegmentString.getNodedSubstrings(segStrings, resultEdgelist);
  30551. return resultEdgelist
  30552. } else if (arguments.length === 2) {
  30553. var segStrings$1 = arguments[0];
  30554. var resultEdgelist$1 = arguments[1];
  30555. for (var i = segStrings$1.iterator(); i.hasNext();) {
  30556. var ss = i.next();
  30557. ss.getNodeList().addSplitEdges(resultEdgelist$1);
  30558. }
  30559. }
  30560. };
  30561. var LineSegment = function LineSegment () {
  30562. this.p0 = null;
  30563. this.p1 = null;
  30564. if (arguments.length === 0) {
  30565. this.p0 = new Coordinate();
  30566. this.p1 = new Coordinate();
  30567. } else if (arguments.length === 1) {
  30568. var ls = arguments[0];
  30569. this.p0 = new Coordinate(ls.p0);
  30570. this.p1 = new Coordinate(ls.p1);
  30571. } else if (arguments.length === 2) {
  30572. this.p0 = arguments[0];
  30573. this.p1 = arguments[1];
  30574. } else if (arguments.length === 4) {
  30575. var x0 = arguments[0];
  30576. var y0 = arguments[1];
  30577. var x1 = arguments[2];
  30578. var y1 = arguments[3];
  30579. this.p0 = new Coordinate(x0, y0);
  30580. this.p1 = new Coordinate(x1, y1);
  30581. }
  30582. };
  30583. var staticAccessors$24 = { serialVersionUID: { configurable: true } };
  30584. LineSegment.prototype.minX = function minX () {
  30585. return Math.min(this.p0.x, this.p1.x)
  30586. };
  30587. LineSegment.prototype.orientationIndex = function orientationIndex () {
  30588. if (arguments[0] instanceof LineSegment) {
  30589. var seg = arguments[0];
  30590. var orient0 = CGAlgorithms.orientationIndex(this.p0, this.p1, seg.p0);
  30591. var orient1 = CGAlgorithms.orientationIndex(this.p0, this.p1, seg.p1);
  30592. if (orient0 >= 0 && orient1 >= 0) { return Math.max(orient0, orient1) }
  30593. if (orient0 <= 0 && orient1 <= 0) { return Math.max(orient0, orient1) }
  30594. return 0
  30595. } else if (arguments[0] instanceof Coordinate) {
  30596. var p = arguments[0];
  30597. return CGAlgorithms.orientationIndex(this.p0, this.p1, p)
  30598. }
  30599. };
  30600. LineSegment.prototype.toGeometry = function toGeometry (geomFactory) {
  30601. return geomFactory.createLineString([this.p0, this.p1])
  30602. };
  30603. LineSegment.prototype.isVertical = function isVertical () {
  30604. return this.p0.x === this.p1.x
  30605. };
  30606. LineSegment.prototype.equals = function equals (o) {
  30607. if (!(o instanceof LineSegment)) {
  30608. return false
  30609. }
  30610. var other = o;
  30611. return this.p0.equals(other.p0) && this.p1.equals(other.p1)
  30612. };
  30613. LineSegment.prototype.intersection = function intersection (line) {
  30614. var li = new RobustLineIntersector();
  30615. li.computeIntersection(this.p0, this.p1, line.p0, line.p1);
  30616. if (li.hasIntersection()) { return li.getIntersection(0) }
  30617. return null
  30618. };
  30619. LineSegment.prototype.project = function project () {
  30620. if (arguments[0] instanceof Coordinate) {
  30621. var p = arguments[0];
  30622. if (p.equals(this.p0) || p.equals(this.p1)) { return new Coordinate(p) }
  30623. var r = this.projectionFactor(p);
  30624. var coord = new Coordinate();
  30625. coord.x = this.p0.x + r * (this.p1.x - this.p0.x);
  30626. coord.y = this.p0.y + r * (this.p1.y - this.p0.y);
  30627. return coord
  30628. } else if (arguments[0] instanceof LineSegment) {
  30629. var seg = arguments[0];
  30630. var pf0 = this.projectionFactor(seg.p0);
  30631. var pf1 = this.projectionFactor(seg.p1);
  30632. if (pf0 >= 1.0 && pf1 >= 1.0) { return null }
  30633. if (pf0 <= 0.0 && pf1 <= 0.0) { return null }
  30634. var newp0 = this.project(seg.p0);
  30635. if (pf0 < 0.0) { newp0 = this.p0; }
  30636. if (pf0 > 1.0) { newp0 = this.p1; }
  30637. var newp1 = this.project(seg.p1);
  30638. if (pf1 < 0.0) { newp1 = this.p0; }
  30639. if (pf1 > 1.0) { newp1 = this.p1; }
  30640. return new LineSegment(newp0, newp1)
  30641. }
  30642. };
  30643. LineSegment.prototype.normalize = function normalize () {
  30644. if (this.p1.compareTo(this.p0) < 0) { this.reverse(); }
  30645. };
  30646. LineSegment.prototype.angle = function angle () {
  30647. return Math.atan2(this.p1.y - this.p0.y, this.p1.x - this.p0.x)
  30648. };
  30649. LineSegment.prototype.getCoordinate = function getCoordinate (i) {
  30650. if (i === 0) { return this.p0 }
  30651. return this.p1
  30652. };
  30653. LineSegment.prototype.distancePerpendicular = function distancePerpendicular (p) {
  30654. return CGAlgorithms.distancePointLinePerpendicular(p, this.p0, this.p1)
  30655. };
  30656. LineSegment.prototype.minY = function minY () {
  30657. return Math.min(this.p0.y, this.p1.y)
  30658. };
  30659. LineSegment.prototype.midPoint = function midPoint () {
  30660. return LineSegment.midPoint(this.p0, this.p1)
  30661. };
  30662. LineSegment.prototype.projectionFactor = function projectionFactor (p) {
  30663. if (p.equals(this.p0)) { return 0.0 }
  30664. if (p.equals(this.p1)) { return 1.0 }
  30665. var dx = this.p1.x - this.p0.x;
  30666. var dy = this.p1.y - this.p0.y;
  30667. var len = dx * dx + dy * dy;
  30668. if (len <= 0.0) { return Double.NaN }
  30669. var r = ((p.x - this.p0.x) * dx + (p.y - this.p0.y) * dy) / len;
  30670. return r
  30671. };
  30672. LineSegment.prototype.closestPoints = function closestPoints (line) {
  30673. var intPt = this.intersection(line);
  30674. if (intPt !== null) {
  30675. return [intPt, intPt]
  30676. }
  30677. var closestPt = new Array(2).fill(null);
  30678. var minDistance = Double.MAX_VALUE;
  30679. var dist = null;
  30680. var close00 = this.closestPoint(line.p0);
  30681. minDistance = close00.distance(line.p0);
  30682. closestPt[0] = close00;
  30683. closestPt[1] = line.p0;
  30684. var close01 = this.closestPoint(line.p1);
  30685. dist = close01.distance(line.p1);
  30686. if (dist < minDistance) {
  30687. minDistance = dist;
  30688. closestPt[0] = close01;
  30689. closestPt[1] = line.p1;
  30690. }
  30691. var close10 = line.closestPoint(this.p0);
  30692. dist = close10.distance(this.p0);
  30693. if (dist < minDistance) {
  30694. minDistance = dist;
  30695. closestPt[0] = this.p0;
  30696. closestPt[1] = close10;
  30697. }
  30698. var close11 = line.closestPoint(this.p1);
  30699. dist = close11.distance(this.p1);
  30700. if (dist < minDistance) {
  30701. minDistance = dist;
  30702. closestPt[0] = this.p1;
  30703. closestPt[1] = close11;
  30704. }
  30705. return closestPt
  30706. };
  30707. LineSegment.prototype.closestPoint = function closestPoint (p) {
  30708. var factor = this.projectionFactor(p);
  30709. if (factor > 0 && factor < 1) {
  30710. return this.project(p)
  30711. }
  30712. var dist0 = this.p0.distance(p);
  30713. var dist1 = this.p1.distance(p);
  30714. if (dist0 < dist1) { return this.p0 }
  30715. return this.p1
  30716. };
  30717. LineSegment.prototype.maxX = function maxX () {
  30718. return Math.max(this.p0.x, this.p1.x)
  30719. };
  30720. LineSegment.prototype.getLength = function getLength () {
  30721. return this.p0.distance(this.p1)
  30722. };
  30723. LineSegment.prototype.compareTo = function compareTo (o) {
  30724. var other = o;
  30725. var comp0 = this.p0.compareTo(other.p0);
  30726. if (comp0 !== 0) { return comp0 }
  30727. return this.p1.compareTo(other.p1)
  30728. };
  30729. LineSegment.prototype.reverse = function reverse () {
  30730. var temp = this.p0;
  30731. this.p0 = this.p1;
  30732. this.p1 = temp;
  30733. };
  30734. LineSegment.prototype.equalsTopo = function equalsTopo (other) {
  30735. return this.p0.equals(other.p0) &&
  30736. (this.p1.equals(other.p1) || this.p0.equals(other.p1)) &&
  30737. this.p1.equals(other.p0)
  30738. };
  30739. LineSegment.prototype.lineIntersection = function lineIntersection (line) {
  30740. try {
  30741. var intPt = HCoordinate.intersection(this.p0, this.p1, line.p0, line.p1);
  30742. return intPt
  30743. } catch (ex) {
  30744. if (ex instanceof NotRepresentableException) {} else { throw ex }
  30745. } finally {}
  30746. return null
  30747. };
  30748. LineSegment.prototype.maxY = function maxY () {
  30749. return Math.max(this.p0.y, this.p1.y)
  30750. };
  30751. LineSegment.prototype.pointAlongOffset = function pointAlongOffset (segmentLengthFraction, offsetDistance) {
  30752. var segx = this.p0.x + segmentLengthFraction * (this.p1.x - this.p0.x);
  30753. var segy = this.p0.y + segmentLengthFraction * (this.p1.y - this.p0.y);
  30754. var dx = this.p1.x - this.p0.x;
  30755. var dy = this.p1.y - this.p0.y;
  30756. var len = Math.sqrt(dx * dx + dy * dy);
  30757. var ux = 0.0;
  30758. var uy = 0.0;
  30759. if (offsetDistance !== 0.0) {
  30760. if (len <= 0.0) { throw new Error('Cannot compute offset from zero-length line segment') }
  30761. ux = offsetDistance * dx / len;
  30762. uy = offsetDistance * dy / len;
  30763. }
  30764. var offsetx = segx - uy;
  30765. var offsety = segy + ux;
  30766. var coord = new Coordinate(offsetx, offsety);
  30767. return coord
  30768. };
  30769. LineSegment.prototype.setCoordinates = function setCoordinates () {
  30770. if (arguments.length === 1) {
  30771. var ls = arguments[0];
  30772. this.setCoordinates(ls.p0, ls.p1);
  30773. } else if (arguments.length === 2) {
  30774. var p0 = arguments[0];
  30775. var p1 = arguments[1];
  30776. this.p0.x = p0.x;
  30777. this.p0.y = p0.y;
  30778. this.p1.x = p1.x;
  30779. this.p1.y = p1.y;
  30780. }
  30781. };
  30782. LineSegment.prototype.segmentFraction = function segmentFraction (inputPt) {
  30783. var segFrac = this.projectionFactor(inputPt);
  30784. if (segFrac < 0.0) { segFrac = 0.0; } else if (segFrac > 1.0 || Double.isNaN(segFrac)) { segFrac = 1.0; }
  30785. return segFrac
  30786. };
  30787. LineSegment.prototype.toString = function toString () {
  30788. return 'LINESTRING( ' + this.p0.x + ' ' + this.p0.y + ', ' + this.p1.x + ' ' + this.p1.y + ')'
  30789. };
  30790. LineSegment.prototype.isHorizontal = function isHorizontal () {
  30791. return this.p0.y === this.p1.y
  30792. };
  30793. LineSegment.prototype.distance = function distance () {
  30794. if (arguments[0] instanceof LineSegment) {
  30795. var ls = arguments[0];
  30796. return CGAlgorithms.distanceLineLine(this.p0, this.p1, ls.p0, ls.p1)
  30797. } else if (arguments[0] instanceof Coordinate) {
  30798. var p = arguments[0];
  30799. return CGAlgorithms.distancePointLine(p, this.p0, this.p1)
  30800. }
  30801. };
  30802. LineSegment.prototype.pointAlong = function pointAlong (segmentLengthFraction) {
  30803. var coord = new Coordinate();
  30804. coord.x = this.p0.x + segmentLengthFraction * (this.p1.x - this.p0.x);
  30805. coord.y = this.p0.y + segmentLengthFraction * (this.p1.y - this.p0.y);
  30806. return coord
  30807. };
  30808. LineSegment.prototype.hashCode = function hashCode () {
  30809. var bits0 = Double.doubleToLongBits(this.p0.x);
  30810. bits0 ^= Double.doubleToLongBits(this.p0.y) * 31;
  30811. var hash0 = Math.trunc(bits0) ^ Math.trunc(bits0 >> 32);
  30812. var bits1 = Double.doubleToLongBits(this.p1.x);
  30813. bits1 ^= Double.doubleToLongBits(this.p1.y) * 31;
  30814. var hash1 = Math.trunc(bits1) ^ Math.trunc(bits1 >> 32);
  30815. return hash0 ^ hash1
  30816. };
  30817. LineSegment.prototype.interfaces_ = function interfaces_ () {
  30818. return [Comparable, Serializable]
  30819. };
  30820. LineSegment.prototype.getClass = function getClass () {
  30821. return LineSegment
  30822. };
  30823. LineSegment.midPoint = function midPoint (p0, p1) {
  30824. return new Coordinate((p0.x + p1.x) / 2, (p0.y + p1.y) / 2)
  30825. };
  30826. staticAccessors$24.serialVersionUID.get = function () { return 3252005833466256227 };
  30827. Object.defineProperties( LineSegment, staticAccessors$24 );
  30828. var MonotoneChainOverlapAction = function MonotoneChainOverlapAction () {
  30829. this.tempEnv1 = new Envelope();
  30830. this.tempEnv2 = new Envelope();
  30831. this._overlapSeg1 = new LineSegment();
  30832. this._overlapSeg2 = new LineSegment();
  30833. };
  30834. MonotoneChainOverlapAction.prototype.overlap = function overlap () {
  30835. if (arguments.length === 2) {
  30836. // const seg1 = arguments[0]
  30837. // const seg2 = arguments[1]
  30838. } else if (arguments.length === 4) {
  30839. var mc1 = arguments[0];
  30840. var start1 = arguments[1];
  30841. var mc2 = arguments[2];
  30842. var start2 = arguments[3];
  30843. mc1.getLineSegment(start1, this._overlapSeg1);
  30844. mc2.getLineSegment(start2, this._overlapSeg2);
  30845. this.overlap(this._overlapSeg1, this._overlapSeg2);
  30846. }
  30847. };
  30848. MonotoneChainOverlapAction.prototype.interfaces_ = function interfaces_ () {
  30849. return []
  30850. };
  30851. MonotoneChainOverlapAction.prototype.getClass = function getClass () {
  30852. return MonotoneChainOverlapAction
  30853. };
  30854. var MonotoneChain = function MonotoneChain () {
  30855. this._pts = null;
  30856. this._start = null;
  30857. this._end = null;
  30858. this._env = null;
  30859. this._context = null;
  30860. this._id = null;
  30861. var pts = arguments[0];
  30862. var start = arguments[1];
  30863. var end = arguments[2];
  30864. var context = arguments[3];
  30865. this._pts = pts;
  30866. this._start = start;
  30867. this._end = end;
  30868. this._context = context;
  30869. };
  30870. MonotoneChain.prototype.getLineSegment = function getLineSegment (index, ls) {
  30871. ls.p0 = this._pts[index];
  30872. ls.p1 = this._pts[index + 1];
  30873. };
  30874. MonotoneChain.prototype.computeSelect = function computeSelect (searchEnv, start0, end0, mcs) {
  30875. var p0 = this._pts[start0];
  30876. var p1 = this._pts[end0];
  30877. mcs.tempEnv1.init(p0, p1);
  30878. if (end0 - start0 === 1) {
  30879. mcs.select(this, start0);
  30880. return null
  30881. }
  30882. if (!searchEnv.intersects(mcs.tempEnv1)) { return null }
  30883. var mid = Math.trunc((start0 + end0) / 2);
  30884. if (start0 < mid) {
  30885. this.computeSelect(searchEnv, start0, mid, mcs);
  30886. }
  30887. if (mid < end0) {
  30888. this.computeSelect(searchEnv, mid, end0, mcs);
  30889. }
  30890. };
  30891. MonotoneChain.prototype.getCoordinates = function getCoordinates () {
  30892. var this$1 = this;
  30893. var coord = new Array(this._end - this._start + 1).fill(null);
  30894. var index = 0;
  30895. for (var i = this._start; i <= this._end; i++) {
  30896. coord[index++] = this$1._pts[i];
  30897. }
  30898. return coord
  30899. };
  30900. MonotoneChain.prototype.computeOverlaps = function computeOverlaps (mc, mco) {
  30901. this.computeOverlapsInternal(this._start, this._end, mc, mc._start, mc._end, mco);
  30902. };
  30903. MonotoneChain.prototype.setId = function setId (id) {
  30904. this._id = id;
  30905. };
  30906. MonotoneChain.prototype.select = function select (searchEnv, mcs) {
  30907. this.computeSelect(searchEnv, this._start, this._end, mcs);
  30908. };
  30909. MonotoneChain.prototype.getEnvelope = function getEnvelope () {
  30910. if (this._env === null) {
  30911. var p0 = this._pts[this._start];
  30912. var p1 = this._pts[this._end];
  30913. this._env = new Envelope(p0, p1);
  30914. }
  30915. return this._env
  30916. };
  30917. MonotoneChain.prototype.getEndIndex = function getEndIndex () {
  30918. return this._end
  30919. };
  30920. MonotoneChain.prototype.getStartIndex = function getStartIndex () {
  30921. return this._start
  30922. };
  30923. MonotoneChain.prototype.getContext = function getContext () {
  30924. return this._context
  30925. };
  30926. MonotoneChain.prototype.getId = function getId () {
  30927. return this._id
  30928. };
  30929. MonotoneChain.prototype.computeOverlapsInternal = function computeOverlapsInternal (start0, end0, mc, start1, end1, mco) {
  30930. var p00 = this._pts[start0];
  30931. var p01 = this._pts[end0];
  30932. var p10 = mc._pts[start1];
  30933. var p11 = mc._pts[end1];
  30934. if (end0 - start0 === 1 && end1 - start1 === 1) {
  30935. mco.overlap(this, start0, mc, start1);
  30936. return null
  30937. }
  30938. mco.tempEnv1.init(p00, p01);
  30939. mco.tempEnv2.init(p10, p11);
  30940. if (!mco.tempEnv1.intersects(mco.tempEnv2)) { return null }
  30941. var mid0 = Math.trunc((start0 + end0) / 2);
  30942. var mid1 = Math.trunc((start1 + end1) / 2);
  30943. if (start0 < mid0) {
  30944. if (start1 < mid1) { this.computeOverlapsInternal(start0, mid0, mc, start1, mid1, mco); }
  30945. if (mid1 < end1) { this.computeOverlapsInternal(start0, mid0, mc, mid1, end1, mco); }
  30946. }
  30947. if (mid0 < end0) {
  30948. if (start1 < mid1) { this.computeOverlapsInternal(mid0, end0, mc, start1, mid1, mco); }
  30949. if (mid1 < end1) { this.computeOverlapsInternal(mid0, end0, mc, mid1, end1, mco); }
  30950. }
  30951. };
  30952. MonotoneChain.prototype.interfaces_ = function interfaces_ () {
  30953. return []
  30954. };
  30955. MonotoneChain.prototype.getClass = function getClass () {
  30956. return MonotoneChain
  30957. };
  30958. var MonotoneChainBuilder = function MonotoneChainBuilder () {};
  30959. MonotoneChainBuilder.prototype.interfaces_ = function interfaces_ () {
  30960. return []
  30961. };
  30962. MonotoneChainBuilder.prototype.getClass = function getClass () {
  30963. return MonotoneChainBuilder
  30964. };
  30965. MonotoneChainBuilder.getChainStartIndices = function getChainStartIndices (pts) {
  30966. var start = 0;
  30967. var startIndexList = new ArrayList();
  30968. startIndexList.add(new Integer(start));
  30969. do {
  30970. var last = MonotoneChainBuilder.findChainEnd(pts, start);
  30971. startIndexList.add(new Integer(last));
  30972. start = last;
  30973. } while (start < pts.length - 1)
  30974. var startIndex = MonotoneChainBuilder.toIntArray(startIndexList);
  30975. return startIndex
  30976. };
  30977. MonotoneChainBuilder.findChainEnd = function findChainEnd (pts, start) {
  30978. var safeStart = start;
  30979. while (safeStart < pts.length - 1 && pts[safeStart].equals2D(pts[safeStart + 1])) {
  30980. safeStart++;
  30981. }
  30982. if (safeStart >= pts.length - 1) {
  30983. return pts.length - 1
  30984. }
  30985. var chainQuad = Quadrant.quadrant(pts[safeStart], pts[safeStart + 1]);
  30986. var last = start + 1;
  30987. while (last < pts.length) {
  30988. if (!pts[last - 1].equals2D(pts[last])) {
  30989. var quad = Quadrant.quadrant(pts[last - 1], pts[last]);
  30990. if (quad !== chainQuad) { break }
  30991. }
  30992. last++;
  30993. }
  30994. return last - 1
  30995. };
  30996. MonotoneChainBuilder.getChains = function getChains () {
  30997. if (arguments.length === 1) {
  30998. var pts = arguments[0];
  30999. return MonotoneChainBuilder.getChains(pts, null)
  31000. } else if (arguments.length === 2) {
  31001. var pts$1 = arguments[0];
  31002. var context = arguments[1];
  31003. var mcList = new ArrayList();
  31004. var startIndex = MonotoneChainBuilder.getChainStartIndices(pts$1);
  31005. for (var i = 0; i < startIndex.length - 1; i++) {
  31006. var mc = new MonotoneChain(pts$1, startIndex[i], startIndex[i + 1], context);
  31007. mcList.add(mc);
  31008. }
  31009. return mcList
  31010. }
  31011. };
  31012. MonotoneChainBuilder.toIntArray = function toIntArray (list) {
  31013. var array = new Array(list.size()).fill(null);
  31014. for (var i = 0; i < array.length; i++) {
  31015. array[i] = list.get(i).intValue();
  31016. }
  31017. return array
  31018. };
  31019. var Noder = function Noder () {};
  31020. Noder.prototype.computeNodes = function computeNodes (segStrings) {};
  31021. Noder.prototype.getNodedSubstrings = function getNodedSubstrings () {};
  31022. Noder.prototype.interfaces_ = function interfaces_ () {
  31023. return []
  31024. };
  31025. Noder.prototype.getClass = function getClass () {
  31026. return Noder
  31027. };
  31028. var SinglePassNoder = function SinglePassNoder () {
  31029. this._segInt = null;
  31030. if (arguments.length === 0) {} else if (arguments.length === 1) {
  31031. var segInt = arguments[0];
  31032. this.setSegmentIntersector(segInt);
  31033. }
  31034. };
  31035. SinglePassNoder.prototype.setSegmentIntersector = function setSegmentIntersector (segInt) {
  31036. this._segInt = segInt;
  31037. };
  31038. SinglePassNoder.prototype.interfaces_ = function interfaces_ () {
  31039. return [Noder]
  31040. };
  31041. SinglePassNoder.prototype.getClass = function getClass () {
  31042. return SinglePassNoder
  31043. };
  31044. var MCIndexNoder = (function (SinglePassNoder$$1) {
  31045. function MCIndexNoder (si) {
  31046. if (si) { SinglePassNoder$$1.call(this, si); }
  31047. else { SinglePassNoder$$1.call(this); }
  31048. this._monoChains = new ArrayList();
  31049. this._index = new STRtree();
  31050. this._idCounter = 0;
  31051. this._nodedSegStrings = null;
  31052. this._nOverlaps = 0;
  31053. }
  31054. if ( SinglePassNoder$$1 ) MCIndexNoder.__proto__ = SinglePassNoder$$1;
  31055. MCIndexNoder.prototype = Object.create( SinglePassNoder$$1 && SinglePassNoder$$1.prototype );
  31056. MCIndexNoder.prototype.constructor = MCIndexNoder;
  31057. var staticAccessors = { SegmentOverlapAction: { configurable: true } };
  31058. MCIndexNoder.prototype.getMonotoneChains = function getMonotoneChains () {
  31059. return this._monoChains
  31060. };
  31061. MCIndexNoder.prototype.getNodedSubstrings = function getNodedSubstrings () {
  31062. return NodedSegmentString.getNodedSubstrings(this._nodedSegStrings)
  31063. };
  31064. MCIndexNoder.prototype.getIndex = function getIndex () {
  31065. return this._index
  31066. };
  31067. MCIndexNoder.prototype.add = function add (segStr) {
  31068. var this$1 = this;
  31069. var segChains = MonotoneChainBuilder.getChains(segStr.getCoordinates(), segStr);
  31070. for (var i = segChains.iterator(); i.hasNext();) {
  31071. var mc = i.next();
  31072. mc.setId(this$1._idCounter++);
  31073. this$1._index.insert(mc.getEnvelope(), mc);
  31074. this$1._monoChains.add(mc);
  31075. }
  31076. };
  31077. MCIndexNoder.prototype.computeNodes = function computeNodes (inputSegStrings) {
  31078. var this$1 = this;
  31079. this._nodedSegStrings = inputSegStrings;
  31080. for (var i = inputSegStrings.iterator(); i.hasNext();) {
  31081. this$1.add(i.next());
  31082. }
  31083. this.intersectChains();
  31084. };
  31085. MCIndexNoder.prototype.intersectChains = function intersectChains () {
  31086. var this$1 = this;
  31087. var overlapAction = new SegmentOverlapAction(this._segInt);
  31088. for (var i = this._monoChains.iterator(); i.hasNext();) {
  31089. var queryChain = i.next();
  31090. var overlapChains = this$1._index.query(queryChain.getEnvelope());
  31091. for (var j = overlapChains.iterator(); j.hasNext();) {
  31092. var testChain = j.next();
  31093. if (testChain.getId() > queryChain.getId()) {
  31094. queryChain.computeOverlaps(testChain, overlapAction);
  31095. this$1._nOverlaps++;
  31096. }
  31097. if (this$1._segInt.isDone()) { return null }
  31098. }
  31099. }
  31100. };
  31101. MCIndexNoder.prototype.interfaces_ = function interfaces_ () {
  31102. return []
  31103. };
  31104. MCIndexNoder.prototype.getClass = function getClass () {
  31105. return MCIndexNoder
  31106. };
  31107. staticAccessors.SegmentOverlapAction.get = function () { return SegmentOverlapAction };
  31108. Object.defineProperties( MCIndexNoder, staticAccessors );
  31109. return MCIndexNoder;
  31110. }(SinglePassNoder));
  31111. var SegmentOverlapAction = (function (MonotoneChainOverlapAction$$1) {
  31112. function SegmentOverlapAction () {
  31113. MonotoneChainOverlapAction$$1.call(this);
  31114. this._si = null;
  31115. var si = arguments[0];
  31116. this._si = si;
  31117. }
  31118. if ( MonotoneChainOverlapAction$$1 ) SegmentOverlapAction.__proto__ = MonotoneChainOverlapAction$$1;
  31119. SegmentOverlapAction.prototype = Object.create( MonotoneChainOverlapAction$$1 && MonotoneChainOverlapAction$$1.prototype );
  31120. SegmentOverlapAction.prototype.constructor = SegmentOverlapAction;
  31121. SegmentOverlapAction.prototype.overlap = function overlap () {
  31122. if (arguments.length === 4) {
  31123. var mc1 = arguments[0];
  31124. var start1 = arguments[1];
  31125. var mc2 = arguments[2];
  31126. var start2 = arguments[3];
  31127. var ss1 = mc1.getContext();
  31128. var ss2 = mc2.getContext();
  31129. this._si.processIntersections(ss1, start1, ss2, start2);
  31130. } else { return MonotoneChainOverlapAction$$1.prototype.overlap.apply(this, arguments) }
  31131. };
  31132. SegmentOverlapAction.prototype.interfaces_ = function interfaces_ () {
  31133. return []
  31134. };
  31135. SegmentOverlapAction.prototype.getClass = function getClass () {
  31136. return SegmentOverlapAction
  31137. };
  31138. return SegmentOverlapAction;
  31139. }(MonotoneChainOverlapAction));
  31140. var BufferParameters = function BufferParameters () {
  31141. this._quadrantSegments = BufferParameters.DEFAULT_QUADRANT_SEGMENTS;
  31142. this._endCapStyle = BufferParameters.CAP_ROUND;
  31143. this._joinStyle = BufferParameters.JOIN_ROUND;
  31144. this._mitreLimit = BufferParameters.DEFAULT_MITRE_LIMIT;
  31145. this._isSingleSided = false;
  31146. this._simplifyFactor = BufferParameters.DEFAULT_SIMPLIFY_FACTOR;
  31147. if (arguments.length === 0) {} else if (arguments.length === 1) {
  31148. var quadrantSegments = arguments[0];
  31149. this.setQuadrantSegments(quadrantSegments);
  31150. } else if (arguments.length === 2) {
  31151. var quadrantSegments$1 = arguments[0];
  31152. var endCapStyle = arguments[1];
  31153. this.setQuadrantSegments(quadrantSegments$1);
  31154. this.setEndCapStyle(endCapStyle);
  31155. } else if (arguments.length === 4) {
  31156. var quadrantSegments$2 = arguments[0];
  31157. var endCapStyle$1 = arguments[1];
  31158. var joinStyle = arguments[2];
  31159. var mitreLimit = arguments[3];
  31160. this.setQuadrantSegments(quadrantSegments$2);
  31161. this.setEndCapStyle(endCapStyle$1);
  31162. this.setJoinStyle(joinStyle);
  31163. this.setMitreLimit(mitreLimit);
  31164. }
  31165. };
  31166. var staticAccessors$25 = { CAP_ROUND: { configurable: true },CAP_FLAT: { configurable: true },CAP_SQUARE: { configurable: true },JOIN_ROUND: { configurable: true },JOIN_MITRE: { configurable: true },JOIN_BEVEL: { configurable: true },DEFAULT_QUADRANT_SEGMENTS: { configurable: true },DEFAULT_MITRE_LIMIT: { configurable: true },DEFAULT_SIMPLIFY_FACTOR: { configurable: true } };
  31167. BufferParameters.prototype.getEndCapStyle = function getEndCapStyle () {
  31168. return this._endCapStyle
  31169. };
  31170. BufferParameters.prototype.isSingleSided = function isSingleSided () {
  31171. return this._isSingleSided
  31172. };
  31173. BufferParameters.prototype.setQuadrantSegments = function setQuadrantSegments (quadSegs) {
  31174. this._quadrantSegments = quadSegs;
  31175. if (this._quadrantSegments === 0) { this._joinStyle = BufferParameters.JOIN_BEVEL; }
  31176. if (this._quadrantSegments < 0) {
  31177. this._joinStyle = BufferParameters.JOIN_MITRE;
  31178. this._mitreLimit = Math.abs(this._quadrantSegments);
  31179. }
  31180. if (quadSegs <= 0) {
  31181. this._quadrantSegments = 1;
  31182. }
  31183. if (this._joinStyle !== BufferParameters.JOIN_ROUND) {
  31184. this._quadrantSegments = BufferParameters.DEFAULT_QUADRANT_SEGMENTS;
  31185. }
  31186. };
  31187. BufferParameters.prototype.getJoinStyle = function getJoinStyle () {
  31188. return this._joinStyle
  31189. };
  31190. BufferParameters.prototype.setJoinStyle = function setJoinStyle (joinStyle) {
  31191. this._joinStyle = joinStyle;
  31192. };
  31193. BufferParameters.prototype.setSimplifyFactor = function setSimplifyFactor (simplifyFactor) {
  31194. this._simplifyFactor = simplifyFactor < 0 ? 0 : simplifyFactor;
  31195. };
  31196. BufferParameters.prototype.getSimplifyFactor = function getSimplifyFactor () {
  31197. return this._simplifyFactor
  31198. };
  31199. BufferParameters.prototype.getQuadrantSegments = function getQuadrantSegments () {
  31200. return this._quadrantSegments
  31201. };
  31202. BufferParameters.prototype.setEndCapStyle = function setEndCapStyle (endCapStyle) {
  31203. this._endCapStyle = endCapStyle;
  31204. };
  31205. BufferParameters.prototype.getMitreLimit = function getMitreLimit () {
  31206. return this._mitreLimit
  31207. };
  31208. BufferParameters.prototype.setMitreLimit = function setMitreLimit (mitreLimit) {
  31209. this._mitreLimit = mitreLimit;
  31210. };
  31211. BufferParameters.prototype.setSingleSided = function setSingleSided (isSingleSided) {
  31212. this._isSingleSided = isSingleSided;
  31213. };
  31214. BufferParameters.prototype.interfaces_ = function interfaces_ () {
  31215. return []
  31216. };
  31217. BufferParameters.prototype.getClass = function getClass () {
  31218. return BufferParameters
  31219. };
  31220. BufferParameters.bufferDistanceError = function bufferDistanceError (quadSegs) {
  31221. var alpha = Math.PI / 2.0 / quadSegs;
  31222. return 1 - Math.cos(alpha / 2.0)
  31223. };
  31224. staticAccessors$25.CAP_ROUND.get = function () { return 1 };
  31225. staticAccessors$25.CAP_FLAT.get = function () { return 2 };
  31226. staticAccessors$25.CAP_SQUARE.get = function () { return 3 };
  31227. staticAccessors$25.JOIN_ROUND.get = function () { return 1 };
  31228. staticAccessors$25.JOIN_MITRE.get = function () { return 2 };
  31229. staticAccessors$25.JOIN_BEVEL.get = function () { return 3 };
  31230. staticAccessors$25.DEFAULT_QUADRANT_SEGMENTS.get = function () { return 8 };
  31231. staticAccessors$25.DEFAULT_MITRE_LIMIT.get = function () { return 5.0 };
  31232. staticAccessors$25.DEFAULT_SIMPLIFY_FACTOR.get = function () { return 0.01 };
  31233. Object.defineProperties( BufferParameters, staticAccessors$25 );
  31234. var BufferInputLineSimplifier = function BufferInputLineSimplifier (inputLine) {
  31235. this._distanceTol = null;
  31236. this._isDeleted = null;
  31237. this._angleOrientation = CGAlgorithms.COUNTERCLOCKWISE;
  31238. this._inputLine = inputLine || null;
  31239. };
  31240. var staticAccessors$26 = { INIT: { configurable: true },DELETE: { configurable: true },KEEP: { configurable: true },NUM_PTS_TO_CHECK: { configurable: true } };
  31241. BufferInputLineSimplifier.prototype.isDeletable = function isDeletable (i0, i1, i2, distanceTol) {
  31242. var p0 = this._inputLine[i0];
  31243. var p1 = this._inputLine[i1];
  31244. var p2 = this._inputLine[i2];
  31245. if (!this.isConcave(p0, p1, p2)) { return false }
  31246. if (!this.isShallow(p0, p1, p2, distanceTol)) { return false }
  31247. return this.isShallowSampled(p0, p1, i0, i2, distanceTol)
  31248. };
  31249. BufferInputLineSimplifier.prototype.deleteShallowConcavities = function deleteShallowConcavities () {
  31250. var this$1 = this;
  31251. var index = 1;
  31252. // const maxIndex = this._inputLine.length - 1
  31253. var midIndex = this.findNextNonDeletedIndex(index);
  31254. var lastIndex = this.findNextNonDeletedIndex(midIndex);
  31255. var isChanged = false;
  31256. while (lastIndex < this._inputLine.length) {
  31257. var isMiddleVertexDeleted = false;
  31258. if (this$1.isDeletable(index, midIndex, lastIndex, this$1._distanceTol)) {
  31259. this$1._isDeleted[midIndex] = BufferInputLineSimplifier.DELETE;
  31260. isMiddleVertexDeleted = true;
  31261. isChanged = true;
  31262. }
  31263. if (isMiddleVertexDeleted) { index = lastIndex; } else { index = midIndex; }
  31264. midIndex = this$1.findNextNonDeletedIndex(index);
  31265. lastIndex = this$1.findNextNonDeletedIndex(midIndex);
  31266. }
  31267. return isChanged
  31268. };
  31269. BufferInputLineSimplifier.prototype.isShallowConcavity = function isShallowConcavity (p0, p1, p2, distanceTol) {
  31270. var orientation = CGAlgorithms.computeOrientation(p0, p1, p2);
  31271. var isAngleToSimplify = orientation === this._angleOrientation;
  31272. if (!isAngleToSimplify) { return false }
  31273. var dist = CGAlgorithms.distancePointLine(p1, p0, p2);
  31274. return dist < distanceTol
  31275. };
  31276. BufferInputLineSimplifier.prototype.isShallowSampled = function isShallowSampled (p0, p2, i0, i2, distanceTol) {
  31277. var this$1 = this;
  31278. var inc = Math.trunc((i2 - i0) / BufferInputLineSimplifier.NUM_PTS_TO_CHECK);
  31279. if (inc <= 0) { inc = 1; }
  31280. for (var i = i0; i < i2; i += inc) {
  31281. if (!this$1.isShallow(p0, p2, this$1._inputLine[i], distanceTol)) { return false }
  31282. }
  31283. return true
  31284. };
  31285. BufferInputLineSimplifier.prototype.isConcave = function isConcave (p0, p1, p2) {
  31286. var orientation = CGAlgorithms.computeOrientation(p0, p1, p2);
  31287. var isConcave = orientation === this._angleOrientation;
  31288. return isConcave
  31289. };
  31290. BufferInputLineSimplifier.prototype.simplify = function simplify (distanceTol) {
  31291. var this$1 = this;
  31292. this._distanceTol = Math.abs(distanceTol);
  31293. if (distanceTol < 0) { this._angleOrientation = CGAlgorithms.CLOCKWISE; }
  31294. this._isDeleted = new Array(this._inputLine.length).fill(null);
  31295. var isChanged = false;
  31296. do {
  31297. isChanged = this$1.deleteShallowConcavities();
  31298. } while (isChanged)
  31299. return this.collapseLine()
  31300. };
  31301. BufferInputLineSimplifier.prototype.findNextNonDeletedIndex = function findNextNonDeletedIndex (index) {
  31302. var next = index + 1;
  31303. while (next < this._inputLine.length && this._isDeleted[next] === BufferInputLineSimplifier.DELETE) { next++; }
  31304. return next
  31305. };
  31306. BufferInputLineSimplifier.prototype.isShallow = function isShallow (p0, p1, p2, distanceTol) {
  31307. var dist = CGAlgorithms.distancePointLine(p1, p0, p2);
  31308. return dist < distanceTol
  31309. };
  31310. BufferInputLineSimplifier.prototype.collapseLine = function collapseLine () {
  31311. var this$1 = this;
  31312. var coordList = new CoordinateList();
  31313. for (var i = 0; i < this._inputLine.length; i++) {
  31314. if (this$1._isDeleted[i] !== BufferInputLineSimplifier.DELETE) { coordList.add(this$1._inputLine[i]); }
  31315. }
  31316. return coordList.toCoordinateArray()
  31317. };
  31318. BufferInputLineSimplifier.prototype.interfaces_ = function interfaces_ () {
  31319. return []
  31320. };
  31321. BufferInputLineSimplifier.prototype.getClass = function getClass () {
  31322. return BufferInputLineSimplifier
  31323. };
  31324. BufferInputLineSimplifier.simplify = function simplify (inputLine, distanceTol) {
  31325. var simp = new BufferInputLineSimplifier(inputLine);
  31326. return simp.simplify(distanceTol)
  31327. };
  31328. staticAccessors$26.INIT.get = function () { return 0 };
  31329. staticAccessors$26.DELETE.get = function () { return 1 };
  31330. staticAccessors$26.KEEP.get = function () { return 1 };
  31331. staticAccessors$26.NUM_PTS_TO_CHECK.get = function () { return 10 };
  31332. Object.defineProperties( BufferInputLineSimplifier, staticAccessors$26 );
  31333. var OffsetSegmentString = function OffsetSegmentString () {
  31334. this._ptList = null;
  31335. this._precisionModel = null;
  31336. this._minimimVertexDistance = 0.0;
  31337. this._ptList = new ArrayList();
  31338. };
  31339. var staticAccessors$28 = { COORDINATE_ARRAY_TYPE: { configurable: true } };
  31340. OffsetSegmentString.prototype.getCoordinates = function getCoordinates () {
  31341. var coord = this._ptList.toArray(OffsetSegmentString.COORDINATE_ARRAY_TYPE);
  31342. return coord
  31343. };
  31344. OffsetSegmentString.prototype.setPrecisionModel = function setPrecisionModel (precisionModel) {
  31345. this._precisionModel = precisionModel;
  31346. };
  31347. OffsetSegmentString.prototype.addPt = function addPt (pt) {
  31348. var bufPt = new Coordinate(pt);
  31349. this._precisionModel.makePrecise(bufPt);
  31350. if (this.isRedundant(bufPt)) { return null }
  31351. this._ptList.add(bufPt);
  31352. };
  31353. OffsetSegmentString.prototype.revere = function revere () {};
  31354. OffsetSegmentString.prototype.addPts = function addPts (pt, isForward) {
  31355. var this$1 = this;
  31356. if (isForward) {
  31357. for (var i = 0; i < pt.length; i++) {
  31358. this$1.addPt(pt[i]);
  31359. }
  31360. } else {
  31361. for (var i$1 = pt.length - 1; i$1 >= 0; i$1--) {
  31362. this$1.addPt(pt[i$1]);
  31363. }
  31364. }
  31365. };
  31366. OffsetSegmentString.prototype.isRedundant = function isRedundant (pt) {
  31367. if (this._ptList.size() < 1) { return false }
  31368. var lastPt = this._ptList.get(this._ptList.size() - 1);
  31369. var ptDist = pt.distance(lastPt);
  31370. if (ptDist < this._minimimVertexDistance) { return true }
  31371. return false
  31372. };
  31373. OffsetSegmentString.prototype.toString = function toString () {
  31374. var fact = new GeometryFactory();
  31375. var line = fact.createLineString(this.getCoordinates());
  31376. return line.toString()
  31377. };
  31378. OffsetSegmentString.prototype.closeRing = function closeRing () {
  31379. if (this._ptList.size() < 1) { return null }
  31380. var startPt = new Coordinate(this._ptList.get(0));
  31381. var lastPt = this._ptList.get(this._ptList.size() - 1);
  31382. // const last2Pt = null
  31383. // if (this._ptList.size() >= 2) last2Pt = this._ptList.get(this._ptList.size() - 2)
  31384. if (startPt.equals(lastPt)) { return null }
  31385. this._ptList.add(startPt);
  31386. };
  31387. OffsetSegmentString.prototype.setMinimumVertexDistance = function setMinimumVertexDistance (minimimVertexDistance) {
  31388. this._minimimVertexDistance = minimimVertexDistance;
  31389. };
  31390. OffsetSegmentString.prototype.interfaces_ = function interfaces_ () {
  31391. return []
  31392. };
  31393. OffsetSegmentString.prototype.getClass = function getClass () {
  31394. return OffsetSegmentString
  31395. };
  31396. staticAccessors$28.COORDINATE_ARRAY_TYPE.get = function () { return new Array(0).fill(null) };
  31397. Object.defineProperties( OffsetSegmentString, staticAccessors$28 );
  31398. var Angle = function Angle () {};
  31399. var staticAccessors$29 = { PI_TIMES_2: { configurable: true },PI_OVER_2: { configurable: true },PI_OVER_4: { configurable: true },COUNTERCLOCKWISE: { configurable: true },CLOCKWISE: { configurable: true },NONE: { configurable: true } };
  31400. Angle.prototype.interfaces_ = function interfaces_ () {
  31401. return []
  31402. };
  31403. Angle.prototype.getClass = function getClass () {
  31404. return Angle
  31405. };
  31406. Angle.toDegrees = function toDegrees (radians) {
  31407. return radians * 180 / Math.PI
  31408. };
  31409. Angle.normalize = function normalize (angle) {
  31410. while (angle > Math.PI) { angle -= Angle.PI_TIMES_2; }
  31411. while (angle <= -Math.PI) { angle += Angle.PI_TIMES_2; }
  31412. return angle
  31413. };
  31414. Angle.angle = function angle () {
  31415. if (arguments.length === 1) {
  31416. var p = arguments[0];
  31417. return Math.atan2(p.y, p.x)
  31418. } else if (arguments.length === 2) {
  31419. var p0 = arguments[0];
  31420. var p1 = arguments[1];
  31421. var dx = p1.x - p0.x;
  31422. var dy = p1.y - p0.y;
  31423. return Math.atan2(dy, dx)
  31424. }
  31425. };
  31426. Angle.isAcute = function isAcute (p0, p1, p2) {
  31427. var dx0 = p0.x - p1.x;
  31428. var dy0 = p0.y - p1.y;
  31429. var dx1 = p2.x - p1.x;
  31430. var dy1 = p2.y - p1.y;
  31431. var dotprod = dx0 * dx1 + dy0 * dy1;
  31432. return dotprod > 0
  31433. };
  31434. Angle.isObtuse = function isObtuse (p0, p1, p2) {
  31435. var dx0 = p0.x - p1.x;
  31436. var dy0 = p0.y - p1.y;
  31437. var dx1 = p2.x - p1.x;
  31438. var dy1 = p2.y - p1.y;
  31439. var dotprod = dx0 * dx1 + dy0 * dy1;
  31440. return dotprod < 0
  31441. };
  31442. Angle.interiorAngle = function interiorAngle (p0, p1, p2) {
  31443. var anglePrev = Angle.angle(p1, p0);
  31444. var angleNext = Angle.angle(p1, p2);
  31445. return Math.abs(angleNext - anglePrev)
  31446. };
  31447. Angle.normalizePositive = function normalizePositive (angle) {
  31448. if (angle < 0.0) {
  31449. while (angle < 0.0) { angle += Angle.PI_TIMES_2; }
  31450. if (angle >= Angle.PI_TIMES_2) { angle = 0.0; }
  31451. } else {
  31452. while (angle >= Angle.PI_TIMES_2) { angle -= Angle.PI_TIMES_2; }
  31453. if (angle < 0.0) { angle = 0.0; }
  31454. }
  31455. return angle
  31456. };
  31457. Angle.angleBetween = function angleBetween (tip1, tail, tip2) {
  31458. var a1 = Angle.angle(tail, tip1);
  31459. var a2 = Angle.angle(tail, tip2);
  31460. return Angle.diff(a1, a2)
  31461. };
  31462. Angle.diff = function diff (ang1, ang2) {
  31463. var delAngle = null;
  31464. if (ang1 < ang2) {
  31465. delAngle = ang2 - ang1;
  31466. } else {
  31467. delAngle = ang1 - ang2;
  31468. }
  31469. if (delAngle > Math.PI) {
  31470. delAngle = 2 * Math.PI - delAngle;
  31471. }
  31472. return delAngle
  31473. };
  31474. Angle.toRadians = function toRadians (angleDegrees) {
  31475. return angleDegrees * Math.PI / 180.0
  31476. };
  31477. Angle.getTurn = function getTurn (ang1, ang2) {
  31478. var crossproduct = Math.sin(ang2 - ang1);
  31479. if (crossproduct > 0) {
  31480. return Angle.COUNTERCLOCKWISE
  31481. }
  31482. if (crossproduct < 0) {
  31483. return Angle.CLOCKWISE
  31484. }
  31485. return Angle.NONE
  31486. };
  31487. Angle.angleBetweenOriented = function angleBetweenOriented (tip1, tail, tip2) {
  31488. var a1 = Angle.angle(tail, tip1);
  31489. var a2 = Angle.angle(tail, tip2);
  31490. var angDel = a2 - a1;
  31491. if (angDel <= -Math.PI) { return angDel + Angle.PI_TIMES_2 }
  31492. if (angDel > Math.PI) { return angDel - Angle.PI_TIMES_2 }
  31493. return angDel
  31494. };
  31495. staticAccessors$29.PI_TIMES_2.get = function () { return 2.0 * Math.PI };
  31496. staticAccessors$29.PI_OVER_2.get = function () { return Math.PI / 2.0 };
  31497. staticAccessors$29.PI_OVER_4.get = function () { return Math.PI / 4.0 };
  31498. staticAccessors$29.COUNTERCLOCKWISE.get = function () { return CGAlgorithms.COUNTERCLOCKWISE };
  31499. staticAccessors$29.CLOCKWISE.get = function () { return CGAlgorithms.CLOCKWISE };
  31500. staticAccessors$29.NONE.get = function () { return CGAlgorithms.COLLINEAR };
  31501. Object.defineProperties( Angle, staticAccessors$29 );
  31502. var OffsetSegmentGenerator = function OffsetSegmentGenerator () {
  31503. this._maxCurveSegmentError = 0.0;
  31504. this._filletAngleQuantum = null;
  31505. this._closingSegLengthFactor = 1;
  31506. this._segList = null;
  31507. this._distance = 0.0;
  31508. this._precisionModel = null;
  31509. this._bufParams = null;
  31510. this._li = null;
  31511. this._s0 = null;
  31512. this._s1 = null;
  31513. this._s2 = null;
  31514. this._seg0 = new LineSegment();
  31515. this._seg1 = new LineSegment();
  31516. this._offset0 = new LineSegment();
  31517. this._offset1 = new LineSegment();
  31518. this._side = 0;
  31519. this._hasNarrowConcaveAngle = false;
  31520. var precisionModel = arguments[0];
  31521. var bufParams = arguments[1];
  31522. var distance = arguments[2];
  31523. this._precisionModel = precisionModel;
  31524. this._bufParams = bufParams;
  31525. this._li = new RobustLineIntersector();
  31526. this._filletAngleQuantum = Math.PI / 2.0 / bufParams.getQuadrantSegments();
  31527. if (bufParams.getQuadrantSegments() >= 8 && bufParams.getJoinStyle() === BufferParameters.JOIN_ROUND) { this._closingSegLengthFactor = OffsetSegmentGenerator.MAX_CLOSING_SEG_LEN_FACTOR; }
  31528. this.init(distance);
  31529. };
  31530. var staticAccessors$27 = { OFFSET_SEGMENT_SEPARATION_FACTOR: { configurable: true },INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR: { configurable: true },CURVE_VERTEX_SNAP_DISTANCE_FACTOR: { configurable: true },MAX_CLOSING_SEG_LEN_FACTOR: { configurable: true } };
  31531. OffsetSegmentGenerator.prototype.addNextSegment = function addNextSegment (p, addStartPoint) {
  31532. this._s0 = this._s1;
  31533. this._s1 = this._s2;
  31534. this._s2 = p;
  31535. this._seg0.setCoordinates(this._s0, this._s1);
  31536. this.computeOffsetSegment(this._seg0, this._side, this._distance, this._offset0);
  31537. this._seg1.setCoordinates(this._s1, this._s2);
  31538. this.computeOffsetSegment(this._seg1, this._side, this._distance, this._offset1);
  31539. if (this._s1.equals(this._s2)) { return null }
  31540. var orientation = CGAlgorithms.computeOrientation(this._s0, this._s1, this._s2);
  31541. var outsideTurn = (orientation === CGAlgorithms.CLOCKWISE && this._side === Position.LEFT) || (orientation === CGAlgorithms.COUNTERCLOCKWISE && this._side === Position.RIGHT);
  31542. if (orientation === 0) {
  31543. this.addCollinear(addStartPoint);
  31544. } else if (outsideTurn) {
  31545. this.addOutsideTurn(orientation, addStartPoint);
  31546. } else {
  31547. this.addInsideTurn(orientation, addStartPoint);
  31548. }
  31549. };
  31550. OffsetSegmentGenerator.prototype.addLineEndCap = function addLineEndCap (p0, p1) {
  31551. var seg = new LineSegment(p0, p1);
  31552. var offsetL = new LineSegment();
  31553. this.computeOffsetSegment(seg, Position.LEFT, this._distance, offsetL);
  31554. var offsetR = new LineSegment();
  31555. this.computeOffsetSegment(seg, Position.RIGHT, this._distance, offsetR);
  31556. var dx = p1.x - p0.x;
  31557. var dy = p1.y - p0.y;
  31558. var angle = Math.atan2(dy, dx);
  31559. switch (this._bufParams.getEndCapStyle()) {
  31560. case BufferParameters.CAP_ROUND:
  31561. this._segList.addPt(offsetL.p1);
  31562. this.addFilletArc(p1, angle + Math.PI / 2, angle - Math.PI / 2, CGAlgorithms.CLOCKWISE, this._distance);
  31563. this._segList.addPt(offsetR.p1);
  31564. break
  31565. case BufferParameters.CAP_FLAT:
  31566. this._segList.addPt(offsetL.p1);
  31567. this._segList.addPt(offsetR.p1);
  31568. break
  31569. case BufferParameters.CAP_SQUARE:
  31570. var squareCapSideOffset = new Coordinate();
  31571. squareCapSideOffset.x = Math.abs(this._distance) * Math.cos(angle);
  31572. squareCapSideOffset.y = Math.abs(this._distance) * Math.sin(angle);
  31573. var squareCapLOffset = new Coordinate(offsetL.p1.x + squareCapSideOffset.x, offsetL.p1.y + squareCapSideOffset.y);
  31574. var squareCapROffset = new Coordinate(offsetR.p1.x + squareCapSideOffset.x, offsetR.p1.y + squareCapSideOffset.y);
  31575. this._segList.addPt(squareCapLOffset);
  31576. this._segList.addPt(squareCapROffset);
  31577. break
  31578. default:
  31579. }
  31580. };
  31581. OffsetSegmentGenerator.prototype.getCoordinates = function getCoordinates () {
  31582. var pts = this._segList.getCoordinates();
  31583. return pts
  31584. };
  31585. OffsetSegmentGenerator.prototype.addMitreJoin = function addMitreJoin (p, offset0, offset1, distance) {
  31586. var isMitreWithinLimit = true;
  31587. var intPt = null;
  31588. try {
  31589. intPt = HCoordinate.intersection(offset0.p0, offset0.p1, offset1.p0, offset1.p1);
  31590. var mitreRatio = distance <= 0.0 ? 1.0 : intPt.distance(p) / Math.abs(distance);
  31591. if (mitreRatio > this._bufParams.getMitreLimit()) { isMitreWithinLimit = false; }
  31592. } catch (ex) {
  31593. if (ex instanceof NotRepresentableException) {
  31594. intPt = new Coordinate(0, 0);
  31595. isMitreWithinLimit = false;
  31596. } else { throw ex }
  31597. } finally {}
  31598. if (isMitreWithinLimit) {
  31599. this._segList.addPt(intPt);
  31600. } else {
  31601. this.addLimitedMitreJoin(offset0, offset1, distance, this._bufParams.getMitreLimit());
  31602. }
  31603. };
  31604. OffsetSegmentGenerator.prototype.addFilletCorner = function addFilletCorner (p, p0, p1, direction, radius) {
  31605. var dx0 = p0.x - p.x;
  31606. var dy0 = p0.y - p.y;
  31607. var startAngle = Math.atan2(dy0, dx0);
  31608. var dx1 = p1.x - p.x;
  31609. var dy1 = p1.y - p.y;
  31610. var endAngle = Math.atan2(dy1, dx1);
  31611. if (direction === CGAlgorithms.CLOCKWISE) {
  31612. if (startAngle <= endAngle) { startAngle += 2.0 * Math.PI; }
  31613. } else {
  31614. if (startAngle >= endAngle) { startAngle -= 2.0 * Math.PI; }
  31615. }
  31616. this._segList.addPt(p0);
  31617. this.addFilletArc(p, startAngle, endAngle, direction, radius);
  31618. this._segList.addPt(p1);
  31619. };
  31620. OffsetSegmentGenerator.prototype.addOutsideTurn = function addOutsideTurn (orientation, addStartPoint) {
  31621. if (this._offset0.p1.distance(this._offset1.p0) < this._distance * OffsetSegmentGenerator.OFFSET_SEGMENT_SEPARATION_FACTOR) {
  31622. this._segList.addPt(this._offset0.p1);
  31623. return null
  31624. }
  31625. if (this._bufParams.getJoinStyle() === BufferParameters.JOIN_MITRE) {
  31626. this.addMitreJoin(this._s1, this._offset0, this._offset1, this._distance);
  31627. } else if (this._bufParams.getJoinStyle() === BufferParameters.JOIN_BEVEL) {
  31628. this.addBevelJoin(this._offset0, this._offset1);
  31629. } else {
  31630. if (addStartPoint) { this._segList.addPt(this._offset0.p1); }
  31631. this.addFilletCorner(this._s1, this._offset0.p1, this._offset1.p0, orientation, this._distance);
  31632. this._segList.addPt(this._offset1.p0);
  31633. }
  31634. };
  31635. OffsetSegmentGenerator.prototype.createSquare = function createSquare (p) {
  31636. this._segList.addPt(new Coordinate(p.x + this._distance, p.y + this._distance));
  31637. this._segList.addPt(new Coordinate(p.x + this._distance, p.y - this._distance));
  31638. this._segList.addPt(new Coordinate(p.x - this._distance, p.y - this._distance));
  31639. this._segList.addPt(new Coordinate(p.x - this._distance, p.y + this._distance));
  31640. this._segList.closeRing();
  31641. };
  31642. OffsetSegmentGenerator.prototype.addSegments = function addSegments (pt, isForward) {
  31643. this._segList.addPts(pt, isForward);
  31644. };
  31645. OffsetSegmentGenerator.prototype.addFirstSegment = function addFirstSegment () {
  31646. this._segList.addPt(this._offset1.p0);
  31647. };
  31648. OffsetSegmentGenerator.prototype.addLastSegment = function addLastSegment () {
  31649. this._segList.addPt(this._offset1.p1);
  31650. };
  31651. OffsetSegmentGenerator.prototype.initSideSegments = function initSideSegments (s1, s2, side) {
  31652. this._s1 = s1;
  31653. this._s2 = s2;
  31654. this._side = side;
  31655. this._seg1.setCoordinates(s1, s2);
  31656. this.computeOffsetSegment(this._seg1, side, this._distance, this._offset1);
  31657. };
  31658. OffsetSegmentGenerator.prototype.addLimitedMitreJoin = function addLimitedMitreJoin (offset0, offset1, distance, mitreLimit) {
  31659. var basePt = this._seg0.p1;
  31660. var ang0 = Angle.angle(basePt, this._seg0.p0);
  31661. // const ang1 = Angle.angle(basePt, this._seg1.p1)
  31662. var angDiff = Angle.angleBetweenOriented(this._seg0.p0, basePt, this._seg1.p1);
  31663. var angDiffHalf = angDiff / 2;
  31664. var midAng = Angle.normalize(ang0 + angDiffHalf);
  31665. var mitreMidAng = Angle.normalize(midAng + Math.PI);
  31666. var mitreDist = mitreLimit * distance;
  31667. var bevelDelta = mitreDist * Math.abs(Math.sin(angDiffHalf));
  31668. var bevelHalfLen = distance - bevelDelta;
  31669. var bevelMidX = basePt.x + mitreDist * Math.cos(mitreMidAng);
  31670. var bevelMidY = basePt.y + mitreDist * Math.sin(mitreMidAng);
  31671. var bevelMidPt = new Coordinate(bevelMidX, bevelMidY);
  31672. var mitreMidLine = new LineSegment(basePt, bevelMidPt);
  31673. var bevelEndLeft = mitreMidLine.pointAlongOffset(1.0, bevelHalfLen);
  31674. var bevelEndRight = mitreMidLine.pointAlongOffset(1.0, -bevelHalfLen);
  31675. if (this._side === Position.LEFT) {
  31676. this._segList.addPt(bevelEndLeft);
  31677. this._segList.addPt(bevelEndRight);
  31678. } else {
  31679. this._segList.addPt(bevelEndRight);
  31680. this._segList.addPt(bevelEndLeft);
  31681. }
  31682. };
  31683. OffsetSegmentGenerator.prototype.computeOffsetSegment = function computeOffsetSegment (seg, side, distance, offset) {
  31684. var sideSign = side === Position.LEFT ? 1 : -1;
  31685. var dx = seg.p1.x - seg.p0.x;
  31686. var dy = seg.p1.y - seg.p0.y;
  31687. var len = Math.sqrt(dx * dx + dy * dy);
  31688. var ux = sideSign * distance * dx / len;
  31689. var uy = sideSign * distance * dy / len;
  31690. offset.p0.x = seg.p0.x - uy;
  31691. offset.p0.y = seg.p0.y + ux;
  31692. offset.p1.x = seg.p1.x - uy;
  31693. offset.p1.y = seg.p1.y + ux;
  31694. };
  31695. OffsetSegmentGenerator.prototype.addFilletArc = function addFilletArc (p, startAngle, endAngle, direction, radius) {
  31696. var this$1 = this;
  31697. var directionFactor = direction === CGAlgorithms.CLOCKWISE ? -1 : 1;
  31698. var totalAngle = Math.abs(startAngle - endAngle);
  31699. var nSegs = Math.trunc(totalAngle / this._filletAngleQuantum + 0.5);
  31700. if (nSegs < 1) { return null }
  31701. var initAngle = 0.0;
  31702. var currAngleInc = totalAngle / nSegs;
  31703. var currAngle = initAngle;
  31704. var pt = new Coordinate();
  31705. while (currAngle < totalAngle) {
  31706. var angle = startAngle + directionFactor * currAngle;
  31707. pt.x = p.x + radius * Math.cos(angle);
  31708. pt.y = p.y + radius * Math.sin(angle);
  31709. this$1._segList.addPt(pt);
  31710. currAngle += currAngleInc;
  31711. }
  31712. };
  31713. OffsetSegmentGenerator.prototype.addInsideTurn = function addInsideTurn (orientation, addStartPoint) {
  31714. this._li.computeIntersection(this._offset0.p0, this._offset0.p1, this._offset1.p0, this._offset1.p1);
  31715. if (this._li.hasIntersection()) {
  31716. this._segList.addPt(this._li.getIntersection(0));
  31717. } else {
  31718. this._hasNarrowConcaveAngle = true;
  31719. if (this._offset0.p1.distance(this._offset1.p0) < this._distance * OffsetSegmentGenerator.INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR) {
  31720. this._segList.addPt(this._offset0.p1);
  31721. } else {
  31722. this._segList.addPt(this._offset0.p1);
  31723. if (this._closingSegLengthFactor > 0) {
  31724. var mid0 = new Coordinate((this._closingSegLengthFactor * this._offset0.p1.x + this._s1.x) / (this._closingSegLengthFactor + 1), (this._closingSegLengthFactor * this._offset0.p1.y + this._s1.y) / (this._closingSegLengthFactor + 1));
  31725. this._segList.addPt(mid0);
  31726. var mid1 = new Coordinate((this._closingSegLengthFactor * this._offset1.p0.x + this._s1.x) / (this._closingSegLengthFactor + 1), (this._closingSegLengthFactor * this._offset1.p0.y + this._s1.y) / (this._closingSegLengthFactor + 1));
  31727. this._segList.addPt(mid1);
  31728. } else {
  31729. this._segList.addPt(this._s1);
  31730. }
  31731. this._segList.addPt(this._offset1.p0);
  31732. }
  31733. }
  31734. };
  31735. OffsetSegmentGenerator.prototype.createCircle = function createCircle (p) {
  31736. var pt = new Coordinate(p.x + this._distance, p.y);
  31737. this._segList.addPt(pt);
  31738. this.addFilletArc(p, 0.0, 2.0 * Math.PI, -1, this._distance);
  31739. this._segList.closeRing();
  31740. };
  31741. OffsetSegmentGenerator.prototype.addBevelJoin = function addBevelJoin (offset0, offset1) {
  31742. this._segList.addPt(offset0.p1);
  31743. this._segList.addPt(offset1.p0);
  31744. };
  31745. OffsetSegmentGenerator.prototype.init = function init (distance) {
  31746. this._distance = distance;
  31747. this._maxCurveSegmentError = distance * (1 - Math.cos(this._filletAngleQuantum / 2.0));
  31748. this._segList = new OffsetSegmentString();
  31749. this._segList.setPrecisionModel(this._precisionModel);
  31750. this._segList.setMinimumVertexDistance(distance * OffsetSegmentGenerator.CURVE_VERTEX_SNAP_DISTANCE_FACTOR);
  31751. };
  31752. OffsetSegmentGenerator.prototype.addCollinear = function addCollinear (addStartPoint) {
  31753. this._li.computeIntersection(this._s0, this._s1, this._s1, this._s2);
  31754. var numInt = this._li.getIntersectionNum();
  31755. if (numInt >= 2) {
  31756. if (this._bufParams.getJoinStyle() === BufferParameters.JOIN_BEVEL || this._bufParams.getJoinStyle() === BufferParameters.JOIN_MITRE) {
  31757. if (addStartPoint) { this._segList.addPt(this._offset0.p1); }
  31758. this._segList.addPt(this._offset1.p0);
  31759. } else {
  31760. this.addFilletCorner(this._s1, this._offset0.p1, this._offset1.p0, CGAlgorithms.CLOCKWISE, this._distance);
  31761. }
  31762. }
  31763. };
  31764. OffsetSegmentGenerator.prototype.closeRing = function closeRing () {
  31765. this._segList.closeRing();
  31766. };
  31767. OffsetSegmentGenerator.prototype.hasNarrowConcaveAngle = function hasNarrowConcaveAngle () {
  31768. return this._hasNarrowConcaveAngle
  31769. };
  31770. OffsetSegmentGenerator.prototype.interfaces_ = function interfaces_ () {
  31771. return []
  31772. };
  31773. OffsetSegmentGenerator.prototype.getClass = function getClass () {
  31774. return OffsetSegmentGenerator
  31775. };
  31776. staticAccessors$27.OFFSET_SEGMENT_SEPARATION_FACTOR.get = function () { return 1.0E-3 };
  31777. staticAccessors$27.INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR.get = function () { return 1.0E-3 };
  31778. staticAccessors$27.CURVE_VERTEX_SNAP_DISTANCE_FACTOR.get = function () { return 1.0E-6 };
  31779. staticAccessors$27.MAX_CLOSING_SEG_LEN_FACTOR.get = function () { return 80 };
  31780. Object.defineProperties( OffsetSegmentGenerator, staticAccessors$27 );
  31781. var OffsetCurveBuilder = function OffsetCurveBuilder () {
  31782. this._distance = 0.0;
  31783. this._precisionModel = null;
  31784. this._bufParams = null;
  31785. var precisionModel = arguments[0];
  31786. var bufParams = arguments[1];
  31787. this._precisionModel = precisionModel;
  31788. this._bufParams = bufParams;
  31789. };
  31790. OffsetCurveBuilder.prototype.getOffsetCurve = function getOffsetCurve (inputPts, distance) {
  31791. this._distance = distance;
  31792. if (distance === 0.0) { return null }
  31793. var isRightSide = distance < 0.0;
  31794. var posDistance = Math.abs(distance);
  31795. var segGen = this.getSegGen(posDistance);
  31796. if (inputPts.length <= 1) {
  31797. this.computePointCurve(inputPts[0], segGen);
  31798. } else {
  31799. this.computeOffsetCurve(inputPts, isRightSide, segGen);
  31800. }
  31801. var curvePts = segGen.getCoordinates();
  31802. if (isRightSide) { CoordinateArrays.reverse(curvePts); }
  31803. return curvePts
  31804. };
  31805. OffsetCurveBuilder.prototype.computeSingleSidedBufferCurve = function computeSingleSidedBufferCurve (inputPts, isRightSide, segGen) {
  31806. var distTol = this.simplifyTolerance(this._distance);
  31807. if (isRightSide) {
  31808. segGen.addSegments(inputPts, true);
  31809. var simp2 = BufferInputLineSimplifier.simplify(inputPts, -distTol);
  31810. var n2 = simp2.length - 1;
  31811. segGen.initSideSegments(simp2[n2], simp2[n2 - 1], Position.LEFT);
  31812. segGen.addFirstSegment();
  31813. for (var i = n2 - 2; i >= 0; i--) {
  31814. segGen.addNextSegment(simp2[i], true);
  31815. }
  31816. } else {
  31817. segGen.addSegments(inputPts, false);
  31818. var simp1 = BufferInputLineSimplifier.simplify(inputPts, distTol);
  31819. var n1 = simp1.length - 1;
  31820. segGen.initSideSegments(simp1[0], simp1[1], Position.LEFT);
  31821. segGen.addFirstSegment();
  31822. for (var i$1 = 2; i$1 <= n1; i$1++) {
  31823. segGen.addNextSegment(simp1[i$1], true);
  31824. }
  31825. }
  31826. segGen.addLastSegment();
  31827. segGen.closeRing();
  31828. };
  31829. OffsetCurveBuilder.prototype.computeRingBufferCurve = function computeRingBufferCurve (inputPts, side, segGen) {
  31830. var distTol = this.simplifyTolerance(this._distance);
  31831. if (side === Position.RIGHT) { distTol = -distTol; }
  31832. var simp = BufferInputLineSimplifier.simplify(inputPts, distTol);
  31833. var n = simp.length - 1;
  31834. segGen.initSideSegments(simp[n - 1], simp[0], side);
  31835. for (var i = 1; i <= n; i++) {
  31836. var addStartPoint = i !== 1;
  31837. segGen.addNextSegment(simp[i], addStartPoint);
  31838. }
  31839. segGen.closeRing();
  31840. };
  31841. OffsetCurveBuilder.prototype.computeLineBufferCurve = function computeLineBufferCurve (inputPts, segGen) {
  31842. var distTol = this.simplifyTolerance(this._distance);
  31843. var simp1 = BufferInputLineSimplifier.simplify(inputPts, distTol);
  31844. var n1 = simp1.length - 1;
  31845. segGen.initSideSegments(simp1[0], simp1[1], Position.LEFT);
  31846. for (var i = 2; i <= n1; i++) {
  31847. segGen.addNextSegment(simp1[i], true);
  31848. }
  31849. segGen.addLastSegment();
  31850. segGen.addLineEndCap(simp1[n1 - 1], simp1[n1]);
  31851. var simp2 = BufferInputLineSimplifier.simplify(inputPts, -distTol);
  31852. var n2 = simp2.length - 1;
  31853. segGen.initSideSegments(simp2[n2], simp2[n2 - 1], Position.LEFT);
  31854. for (var i$1 = n2 - 2; i$1 >= 0; i$1--) {
  31855. segGen.addNextSegment(simp2[i$1], true);
  31856. }
  31857. segGen.addLastSegment();
  31858. segGen.addLineEndCap(simp2[1], simp2[0]);
  31859. segGen.closeRing();
  31860. };
  31861. OffsetCurveBuilder.prototype.computePointCurve = function computePointCurve (pt, segGen) {
  31862. switch (this._bufParams.getEndCapStyle()) {
  31863. case BufferParameters.CAP_ROUND:
  31864. segGen.createCircle(pt);
  31865. break
  31866. case BufferParameters.CAP_SQUARE:
  31867. segGen.createSquare(pt);
  31868. break
  31869. default:
  31870. }
  31871. };
  31872. OffsetCurveBuilder.prototype.getLineCurve = function getLineCurve (inputPts, distance) {
  31873. this._distance = distance;
  31874. if (distance < 0.0 && !this._bufParams.isSingleSided()) { return null }
  31875. if (distance === 0.0) { return null }
  31876. var posDistance = Math.abs(distance);
  31877. var segGen = this.getSegGen(posDistance);
  31878. if (inputPts.length <= 1) {
  31879. this.computePointCurve(inputPts[0], segGen);
  31880. } else {
  31881. if (this._bufParams.isSingleSided()) {
  31882. var isRightSide = distance < 0.0;
  31883. this.computeSingleSidedBufferCurve(inputPts, isRightSide, segGen);
  31884. } else { this.computeLineBufferCurve(inputPts, segGen); }
  31885. }
  31886. var lineCoord = segGen.getCoordinates();
  31887. return lineCoord
  31888. };
  31889. OffsetCurveBuilder.prototype.getBufferParameters = function getBufferParameters () {
  31890. return this._bufParams
  31891. };
  31892. OffsetCurveBuilder.prototype.simplifyTolerance = function simplifyTolerance (bufDistance) {
  31893. return bufDistance * this._bufParams.getSimplifyFactor()
  31894. };
  31895. OffsetCurveBuilder.prototype.getRingCurve = function getRingCurve (inputPts, side, distance) {
  31896. this._distance = distance;
  31897. if (inputPts.length <= 2) { return this.getLineCurve(inputPts, distance) }
  31898. if (distance === 0.0) {
  31899. return OffsetCurveBuilder.copyCoordinates(inputPts)
  31900. }
  31901. var segGen = this.getSegGen(distance);
  31902. this.computeRingBufferCurve(inputPts, side, segGen);
  31903. return segGen.getCoordinates()
  31904. };
  31905. OffsetCurveBuilder.prototype.computeOffsetCurve = function computeOffsetCurve (inputPts, isRightSide, segGen) {
  31906. var distTol = this.simplifyTolerance(this._distance);
  31907. if (isRightSide) {
  31908. var simp2 = BufferInputLineSimplifier.simplify(inputPts, -distTol);
  31909. var n2 = simp2.length - 1;
  31910. segGen.initSideSegments(simp2[n2], simp2[n2 - 1], Position.LEFT);
  31911. segGen.addFirstSegment();
  31912. for (var i = n2 - 2; i >= 0; i--) {
  31913. segGen.addNextSegment(simp2[i], true);
  31914. }
  31915. } else {
  31916. var simp1 = BufferInputLineSimplifier.simplify(inputPts, distTol);
  31917. var n1 = simp1.length - 1;
  31918. segGen.initSideSegments(simp1[0], simp1[1], Position.LEFT);
  31919. segGen.addFirstSegment();
  31920. for (var i$1 = 2; i$1 <= n1; i$1++) {
  31921. segGen.addNextSegment(simp1[i$1], true);
  31922. }
  31923. }
  31924. segGen.addLastSegment();
  31925. };
  31926. OffsetCurveBuilder.prototype.getSegGen = function getSegGen (distance) {
  31927. return new OffsetSegmentGenerator(this._precisionModel, this._bufParams, distance)
  31928. };
  31929. OffsetCurveBuilder.prototype.interfaces_ = function interfaces_ () {
  31930. return []
  31931. };
  31932. OffsetCurveBuilder.prototype.getClass = function getClass () {
  31933. return OffsetCurveBuilder
  31934. };
  31935. OffsetCurveBuilder.copyCoordinates = function copyCoordinates (pts) {
  31936. var copy = new Array(pts.length).fill(null);
  31937. for (var i = 0; i < copy.length; i++) {
  31938. copy[i] = new Coordinate(pts[i]);
  31939. }
  31940. return copy
  31941. };
  31942. var SubgraphDepthLocater = function SubgraphDepthLocater () {
  31943. this._subgraphs = null;
  31944. this._seg = new LineSegment();
  31945. this._cga = new CGAlgorithms();
  31946. var subgraphs = arguments[0];
  31947. this._subgraphs = subgraphs;
  31948. };
  31949. var staticAccessors$30 = { DepthSegment: { configurable: true } };
  31950. SubgraphDepthLocater.prototype.findStabbedSegments = function findStabbedSegments () {
  31951. var this$1 = this;
  31952. if (arguments.length === 1) {
  31953. var stabbingRayLeftPt = arguments[0];
  31954. var stabbedSegments = new ArrayList();
  31955. for (var i = this._subgraphs.iterator(); i.hasNext();) {
  31956. var bsg = i.next();
  31957. var env = bsg.getEnvelope();
  31958. if (stabbingRayLeftPt.y < env.getMinY() || stabbingRayLeftPt.y > env.getMaxY()) { continue }
  31959. this$1.findStabbedSegments(stabbingRayLeftPt, bsg.getDirectedEdges(), stabbedSegments);
  31960. }
  31961. return stabbedSegments
  31962. } else if (arguments.length === 3) {
  31963. if (hasInterface(arguments[2], List) && (arguments[0] instanceof Coordinate && arguments[1] instanceof DirectedEdge)) {
  31964. var stabbingRayLeftPt$1 = arguments[0];
  31965. var dirEdge = arguments[1];
  31966. var stabbedSegments$1 = arguments[2];
  31967. var pts = dirEdge.getEdge().getCoordinates();
  31968. for (var i$1 = 0; i$1 < pts.length - 1; i$1++) {
  31969. this$1._seg.p0 = pts[i$1];
  31970. this$1._seg.p1 = pts[i$1 + 1];
  31971. if (this$1._seg.p0.y > this$1._seg.p1.y) { this$1._seg.reverse(); }
  31972. var maxx = Math.max(this$1._seg.p0.x, this$1._seg.p1.x);
  31973. if (maxx < stabbingRayLeftPt$1.x) { continue }
  31974. if (this$1._seg.isHorizontal()) { continue }
  31975. if (stabbingRayLeftPt$1.y < this$1._seg.p0.y || stabbingRayLeftPt$1.y > this$1._seg.p1.y) { continue }
  31976. if (CGAlgorithms.computeOrientation(this$1._seg.p0, this$1._seg.p1, stabbingRayLeftPt$1) === CGAlgorithms.RIGHT) { continue }
  31977. var depth = dirEdge.getDepth(Position.LEFT);
  31978. if (!this$1._seg.p0.equals(pts[i$1])) { depth = dirEdge.getDepth(Position.RIGHT); }
  31979. var ds = new DepthSegment(this$1._seg, depth);
  31980. stabbedSegments$1.add(ds);
  31981. }
  31982. } else if (hasInterface(arguments[2], List) && (arguments[0] instanceof Coordinate && hasInterface(arguments[1], List))) {
  31983. var stabbingRayLeftPt$2 = arguments[0];
  31984. var dirEdges = arguments[1];
  31985. var stabbedSegments$2 = arguments[2];
  31986. for (var i$2 = dirEdges.iterator(); i$2.hasNext();) {
  31987. var de = i$2.next();
  31988. if (!de.isForward()) { continue }
  31989. this$1.findStabbedSegments(stabbingRayLeftPt$2, de, stabbedSegments$2);
  31990. }
  31991. }
  31992. }
  31993. };
  31994. SubgraphDepthLocater.prototype.getDepth = function getDepth (p) {
  31995. var stabbedSegments = this.findStabbedSegments(p);
  31996. if (stabbedSegments.size() === 0) { return 0 }
  31997. var ds = Collections.min(stabbedSegments);
  31998. return ds._leftDepth
  31999. };
  32000. SubgraphDepthLocater.prototype.interfaces_ = function interfaces_ () {
  32001. return []
  32002. };
  32003. SubgraphDepthLocater.prototype.getClass = function getClass () {
  32004. return SubgraphDepthLocater
  32005. };
  32006. staticAccessors$30.DepthSegment.get = function () { return DepthSegment };
  32007. Object.defineProperties( SubgraphDepthLocater, staticAccessors$30 );
  32008. var DepthSegment = function DepthSegment () {
  32009. this._upwardSeg = null;
  32010. this._leftDepth = null;
  32011. var seg = arguments[0];
  32012. var depth = arguments[1];
  32013. this._upwardSeg = new LineSegment(seg);
  32014. this._leftDepth = depth;
  32015. };
  32016. DepthSegment.prototype.compareTo = function compareTo (obj) {
  32017. var other = obj;
  32018. if (this._upwardSeg.minX() >= other._upwardSeg.maxX()) { return 1 }
  32019. if (this._upwardSeg.maxX() <= other._upwardSeg.minX()) { return -1 }
  32020. var orientIndex = this._upwardSeg.orientationIndex(other._upwardSeg);
  32021. if (orientIndex !== 0) { return orientIndex }
  32022. orientIndex = -1 * other._upwardSeg.orientationIndex(this._upwardSeg);
  32023. if (orientIndex !== 0) { return orientIndex }
  32024. return this._upwardSeg.compareTo(other._upwardSeg)
  32025. };
  32026. DepthSegment.prototype.compareX = function compareX (seg0, seg1) {
  32027. var compare0 = seg0.p0.compareTo(seg1.p0);
  32028. if (compare0 !== 0) { return compare0 }
  32029. return seg0.p1.compareTo(seg1.p1)
  32030. };
  32031. DepthSegment.prototype.toString = function toString () {
  32032. return this._upwardSeg.toString()
  32033. };
  32034. DepthSegment.prototype.interfaces_ = function interfaces_ () {
  32035. return [Comparable]
  32036. };
  32037. DepthSegment.prototype.getClass = function getClass () {
  32038. return DepthSegment
  32039. };
  32040. var Triangle$1 = function Triangle (p0, p1, p2) {
  32041. this.p0 = p0 || null;
  32042. this.p1 = p1 || null;
  32043. this.p2 = p2 || null;
  32044. };
  32045. Triangle$1.prototype.area = function area () {
  32046. return Triangle$1.area(this.p0, this.p1, this.p2)
  32047. };
  32048. Triangle$1.prototype.signedArea = function signedArea () {
  32049. return Triangle$1.signedArea(this.p0, this.p1, this.p2)
  32050. };
  32051. Triangle$1.prototype.interpolateZ = function interpolateZ (p) {
  32052. if (p === null) { throw new IllegalArgumentException('Supplied point is null.') }
  32053. return Triangle$1.interpolateZ(p, this.p0, this.p1, this.p2)
  32054. };
  32055. Triangle$1.prototype.longestSideLength = function longestSideLength () {
  32056. return Triangle$1.longestSideLength(this.p0, this.p1, this.p2)
  32057. };
  32058. Triangle$1.prototype.isAcute = function isAcute () {
  32059. return Triangle$1.isAcute(this.p0, this.p1, this.p2)
  32060. };
  32061. Triangle$1.prototype.circumcentre = function circumcentre () {
  32062. return Triangle$1.circumcentre(this.p0, this.p1, this.p2)
  32063. };
  32064. Triangle$1.prototype.area3D = function area3D () {
  32065. return Triangle$1.area3D(this.p0, this.p1, this.p2)
  32066. };
  32067. Triangle$1.prototype.centroid = function centroid () {
  32068. return Triangle$1.centroid(this.p0, this.p1, this.p2)
  32069. };
  32070. Triangle$1.prototype.inCentre = function inCentre () {
  32071. return Triangle$1.inCentre(this.p0, this.p1, this.p2)
  32072. };
  32073. Triangle$1.prototype.interfaces_ = function interfaces_ () {
  32074. return []
  32075. };
  32076. Triangle$1.prototype.getClass = function getClass () {
  32077. return Triangle$1
  32078. };
  32079. Triangle$1.area = function area (a, b, c) {
  32080. return Math.abs(((c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y)) / 2)
  32081. };
  32082. Triangle$1.signedArea = function signedArea (a, b, c) {
  32083. return ((c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y)) / 2
  32084. };
  32085. Triangle$1.det = function det (m00, m01, m10, m11) {
  32086. return m00 * m11 - m01 * m10
  32087. };
  32088. Triangle$1.interpolateZ = function interpolateZ (p, v0, v1, v2) {
  32089. var x0 = v0.x;
  32090. var y0 = v0.y;
  32091. var a = v1.x - x0;
  32092. var b = v2.x - x0;
  32093. var c = v1.y - y0;
  32094. var d = v2.y - y0;
  32095. var det = a * d - b * c;
  32096. var dx = p.x - x0;
  32097. var dy = p.y - y0;
  32098. var t = (d * dx - b * dy) / det;
  32099. var u = (-c * dx + a * dy) / det;
  32100. var z = v0.z + t * (v1.z - v0.z) + u * (v2.z - v0.z);
  32101. return z
  32102. };
  32103. Triangle$1.longestSideLength = function longestSideLength (a, b, c) {
  32104. var lenAB = a.distance(b);
  32105. var lenBC = b.distance(c);
  32106. var lenCA = c.distance(a);
  32107. var maxLen = lenAB;
  32108. if (lenBC > maxLen) { maxLen = lenBC; }
  32109. if (lenCA > maxLen) { maxLen = lenCA; }
  32110. return maxLen
  32111. };
  32112. Triangle$1.isAcute = function isAcute (a, b, c) {
  32113. if (!Angle.isAcute(a, b, c)) { return false }
  32114. if (!Angle.isAcute(b, c, a)) { return false }
  32115. if (!Angle.isAcute(c, a, b)) { return false }
  32116. return true
  32117. };
  32118. Triangle$1.circumcentre = function circumcentre (a, b, c) {
  32119. var cx = c.x;
  32120. var cy = c.y;
  32121. var ax = a.x - cx;
  32122. var ay = a.y - cy;
  32123. var bx = b.x - cx;
  32124. var by = b.y - cy;
  32125. var denom = 2 * Triangle$1.det(ax, ay, bx, by);
  32126. var numx = Triangle$1.det(ay, ax * ax + ay * ay, by, bx * bx + by * by);
  32127. var numy = Triangle$1.det(ax, ax * ax + ay * ay, bx, bx * bx + by * by);
  32128. var ccx = cx - numx / denom;
  32129. var ccy = cy + numy / denom;
  32130. return new Coordinate(ccx, ccy)
  32131. };
  32132. Triangle$1.perpendicularBisector = function perpendicularBisector (a, b) {
  32133. var dx = b.x - a.x;
  32134. var dy = b.y - a.y;
  32135. var l1 = new HCoordinate(a.x + dx / 2.0, a.y + dy / 2.0, 1.0);
  32136. var l2 = new HCoordinate(a.x - dy + dx / 2.0, a.y + dx + dy / 2.0, 1.0);
  32137. return new HCoordinate(l1, l2)
  32138. };
  32139. Triangle$1.angleBisector = function angleBisector (a, b, c) {
  32140. var len0 = b.distance(a);
  32141. var len2 = b.distance(c);
  32142. var frac = len0 / (len0 + len2);
  32143. var dx = c.x - a.x;
  32144. var dy = c.y - a.y;
  32145. var splitPt = new Coordinate(a.x + frac * dx, a.y + frac * dy);
  32146. return splitPt
  32147. };
  32148. Triangle$1.area3D = function area3D (a, b, c) {
  32149. var ux = b.x - a.x;
  32150. var uy = b.y - a.y;
  32151. var uz = b.z - a.z;
  32152. var vx = c.x - a.x;
  32153. var vy = c.y - a.y;
  32154. var vz = c.z - a.z;
  32155. var crossx = uy * vz - uz * vy;
  32156. var crossy = uz * vx - ux * vz;
  32157. var crossz = ux * vy - uy * vx;
  32158. var absSq = crossx * crossx + crossy * crossy + crossz * crossz;
  32159. var area3D = Math.sqrt(absSq) / 2;
  32160. return area3D
  32161. };
  32162. Triangle$1.centroid = function centroid (a, b, c) {
  32163. var x = (a.x + b.x + c.x) / 3;
  32164. var y = (a.y + b.y + c.y) / 3;
  32165. return new Coordinate(x, y)
  32166. };
  32167. Triangle$1.inCentre = function inCentre (a, b, c) {
  32168. var len0 = b.distance(c);
  32169. var len1 = a.distance(c);
  32170. var len2 = a.distance(b);
  32171. var circum = len0 + len1 + len2;
  32172. var inCentreX = (len0 * a.x + len1 * b.x + len2 * c.x) / circum;
  32173. var inCentreY = (len0 * a.y + len1 * b.y + len2 * c.y) / circum;
  32174. return new Coordinate(inCentreX, inCentreY)
  32175. };
  32176. var OffsetCurveSetBuilder = function OffsetCurveSetBuilder () {
  32177. this._inputGeom = null;
  32178. this._distance = null;
  32179. this._curveBuilder = null;
  32180. this._curveList = new ArrayList();
  32181. var inputGeom = arguments[0];
  32182. var distance = arguments[1];
  32183. var curveBuilder = arguments[2];
  32184. this._inputGeom = inputGeom;
  32185. this._distance = distance;
  32186. this._curveBuilder = curveBuilder;
  32187. };
  32188. OffsetCurveSetBuilder.prototype.addPoint = function addPoint (p) {
  32189. if (this._distance <= 0.0) { return null }
  32190. var coord = p.getCoordinates();
  32191. var curve = this._curveBuilder.getLineCurve(coord, this._distance);
  32192. this.addCurve(curve, Location.EXTERIOR, Location.INTERIOR);
  32193. };
  32194. OffsetCurveSetBuilder.prototype.addPolygon = function addPolygon (p) {
  32195. var this$1 = this;
  32196. var offsetDistance = this._distance;
  32197. var offsetSide = Position.LEFT;
  32198. if (this._distance < 0.0) {
  32199. offsetDistance = -this._distance;
  32200. offsetSide = Position.RIGHT;
  32201. }
  32202. var shell = p.getExteriorRing();
  32203. var shellCoord = CoordinateArrays.removeRepeatedPoints(shell.getCoordinates());
  32204. if (this._distance < 0.0 && this.isErodedCompletely(shell, this._distance)) { return null }
  32205. if (this._distance <= 0.0 && shellCoord.length < 3) { return null }
  32206. this.addPolygonRing(shellCoord, offsetDistance, offsetSide, Location.EXTERIOR, Location.INTERIOR);
  32207. for (var i = 0; i < p.getNumInteriorRing(); i++) {
  32208. var hole = p.getInteriorRingN(i);
  32209. var holeCoord = CoordinateArrays.removeRepeatedPoints(hole.getCoordinates());
  32210. if (this$1._distance > 0.0 && this$1.isErodedCompletely(hole, -this$1._distance)) { continue }
  32211. this$1.addPolygonRing(holeCoord, offsetDistance, Position.opposite(offsetSide), Location.INTERIOR, Location.EXTERIOR);
  32212. }
  32213. };
  32214. OffsetCurveSetBuilder.prototype.isTriangleErodedCompletely = function isTriangleErodedCompletely (triangleCoord, bufferDistance) {
  32215. var tri = new Triangle$1(triangleCoord[0], triangleCoord[1], triangleCoord[2]);
  32216. var inCentre = tri.inCentre();
  32217. var distToCentre = CGAlgorithms.distancePointLine(inCentre, tri.p0, tri.p1);
  32218. return distToCentre < Math.abs(bufferDistance)
  32219. };
  32220. OffsetCurveSetBuilder.prototype.addLineString = function addLineString (line) {
  32221. if (this._distance <= 0.0 && !this._curveBuilder.getBufferParameters().isSingleSided()) { return null }
  32222. var coord = CoordinateArrays.removeRepeatedPoints(line.getCoordinates());
  32223. var curve = this._curveBuilder.getLineCurve(coord, this._distance);
  32224. this.addCurve(curve, Location.EXTERIOR, Location.INTERIOR);
  32225. };
  32226. OffsetCurveSetBuilder.prototype.addCurve = function addCurve (coord, leftLoc, rightLoc) {
  32227. if (coord === null || coord.length < 2) { return null }
  32228. var e = new NodedSegmentString(coord, new Label(0, Location.BOUNDARY, leftLoc, rightLoc));
  32229. this._curveList.add(e);
  32230. };
  32231. OffsetCurveSetBuilder.prototype.getCurves = function getCurves () {
  32232. this.add(this._inputGeom);
  32233. return this._curveList
  32234. };
  32235. OffsetCurveSetBuilder.prototype.addPolygonRing = function addPolygonRing (coord, offsetDistance, side, cwLeftLoc, cwRightLoc) {
  32236. if (offsetDistance === 0.0 && coord.length < LinearRing.MINIMUM_VALID_SIZE) { return null }
  32237. var leftLoc = cwLeftLoc;
  32238. var rightLoc = cwRightLoc;
  32239. if (coord.length >= LinearRing.MINIMUM_VALID_SIZE && CGAlgorithms.isCCW(coord)) {
  32240. leftLoc = cwRightLoc;
  32241. rightLoc = cwLeftLoc;
  32242. side = Position.opposite(side);
  32243. }
  32244. var curve = this._curveBuilder.getRingCurve(coord, side, offsetDistance);
  32245. this.addCurve(curve, leftLoc, rightLoc);
  32246. };
  32247. OffsetCurveSetBuilder.prototype.add = function add (g) {
  32248. if (g.isEmpty()) { return null }
  32249. if (g instanceof Polygon) { this.addPolygon(g); }
  32250. else if (g instanceof LineString$1) { this.addLineString(g); }
  32251. else if (g instanceof Point) { this.addPoint(g); }
  32252. else if (g instanceof MultiPoint) { this.addCollection(g); }
  32253. else if (g instanceof MultiLineString) { this.addCollection(g); }
  32254. else if (g instanceof MultiPolygon) { this.addCollection(g); }
  32255. else if (g instanceof GeometryCollection) { this.addCollection(g); }
  32256. // else throw new UnsupportedOperationException(g.getClass().getName())
  32257. };
  32258. OffsetCurveSetBuilder.prototype.isErodedCompletely = function isErodedCompletely (ring, bufferDistance) {
  32259. var ringCoord = ring.getCoordinates();
  32260. // const minDiam = 0.0
  32261. if (ringCoord.length < 4) { return bufferDistance < 0 }
  32262. if (ringCoord.length === 4) { return this.isTriangleErodedCompletely(ringCoord, bufferDistance) }
  32263. var env = ring.getEnvelopeInternal();
  32264. var envMinDimension = Math.min(env.getHeight(), env.getWidth());
  32265. if (bufferDistance < 0.0 && 2 * Math.abs(bufferDistance) > envMinDimension) { return true }
  32266. return false
  32267. };
  32268. OffsetCurveSetBuilder.prototype.addCollection = function addCollection (gc) {
  32269. var this$1 = this;
  32270. for (var i = 0; i < gc.getNumGeometries(); i++) {
  32271. var g = gc.getGeometryN(i);
  32272. this$1.add(g);
  32273. }
  32274. };
  32275. OffsetCurveSetBuilder.prototype.interfaces_ = function interfaces_ () {
  32276. return []
  32277. };
  32278. OffsetCurveSetBuilder.prototype.getClass = function getClass () {
  32279. return OffsetCurveSetBuilder
  32280. };
  32281. var PointOnGeometryLocator = function PointOnGeometryLocator () {};
  32282. PointOnGeometryLocator.prototype.locate = function locate (p) {};
  32283. PointOnGeometryLocator.prototype.interfaces_ = function interfaces_ () {
  32284. return []
  32285. };
  32286. PointOnGeometryLocator.prototype.getClass = function getClass () {
  32287. return PointOnGeometryLocator
  32288. };
  32289. var GeometryCollectionIterator = function GeometryCollectionIterator () {
  32290. this._parent = null;
  32291. this._atStart = null;
  32292. this._max = null;
  32293. this._index = null;
  32294. this._subcollectionIterator = null;
  32295. var parent = arguments[0];
  32296. this._parent = parent;
  32297. this._atStart = true;
  32298. this._index = 0;
  32299. this._max = parent.getNumGeometries();
  32300. };
  32301. GeometryCollectionIterator.prototype.next = function next () {
  32302. if (this._atStart) {
  32303. this._atStart = false;
  32304. if (GeometryCollectionIterator.isAtomic(this._parent)) { this._index++; }
  32305. return this._parent
  32306. }
  32307. if (this._subcollectionIterator !== null) {
  32308. if (this._subcollectionIterator.hasNext()) {
  32309. return this._subcollectionIterator.next()
  32310. } else {
  32311. this._subcollectionIterator = null;
  32312. }
  32313. }
  32314. if (this._index >= this._max) {
  32315. throw new NoSuchElementException()
  32316. }
  32317. var obj = this._parent.getGeometryN(this._index++);
  32318. if (obj instanceof GeometryCollection) {
  32319. this._subcollectionIterator = new GeometryCollectionIterator(obj);
  32320. return this._subcollectionIterator.next()
  32321. }
  32322. return obj
  32323. };
  32324. GeometryCollectionIterator.prototype.remove = function remove () {
  32325. throw new Error(this.getClass().getName())
  32326. };
  32327. GeometryCollectionIterator.prototype.hasNext = function hasNext () {
  32328. if (this._atStart) {
  32329. return true
  32330. }
  32331. if (this._subcollectionIterator !== null) {
  32332. if (this._subcollectionIterator.hasNext()) {
  32333. return true
  32334. }
  32335. this._subcollectionIterator = null;
  32336. }
  32337. if (this._index >= this._max) {
  32338. return false
  32339. }
  32340. return true
  32341. };
  32342. GeometryCollectionIterator.prototype.interfaces_ = function interfaces_ () {
  32343. return [Iterator]
  32344. };
  32345. GeometryCollectionIterator.prototype.getClass = function getClass () {
  32346. return GeometryCollectionIterator
  32347. };
  32348. GeometryCollectionIterator.isAtomic = function isAtomic (geom) {
  32349. return !(geom instanceof GeometryCollection)
  32350. };
  32351. var SimplePointInAreaLocator = function SimplePointInAreaLocator () {
  32352. this._geom = null;
  32353. var geom = arguments[0];
  32354. this._geom = geom;
  32355. };
  32356. SimplePointInAreaLocator.prototype.locate = function locate (p) {
  32357. return SimplePointInAreaLocator.locate(p, this._geom)
  32358. };
  32359. SimplePointInAreaLocator.prototype.interfaces_ = function interfaces_ () {
  32360. return [PointOnGeometryLocator]
  32361. };
  32362. SimplePointInAreaLocator.prototype.getClass = function getClass () {
  32363. return SimplePointInAreaLocator
  32364. };
  32365. SimplePointInAreaLocator.isPointInRing = function isPointInRing (p, ring) {
  32366. if (!ring.getEnvelopeInternal().intersects(p)) { return false }
  32367. return CGAlgorithms.isPointInRing(p, ring.getCoordinates())
  32368. };
  32369. SimplePointInAreaLocator.containsPointInPolygon = function containsPointInPolygon (p, poly) {
  32370. if (poly.isEmpty()) { return false }
  32371. var shell = poly.getExteriorRing();
  32372. if (!SimplePointInAreaLocator.isPointInRing(p, shell)) { return false }
  32373. for (var i = 0; i < poly.getNumInteriorRing(); i++) {
  32374. var hole = poly.getInteriorRingN(i);
  32375. if (SimplePointInAreaLocator.isPointInRing(p, hole)) { return false }
  32376. }
  32377. return true
  32378. };
  32379. SimplePointInAreaLocator.containsPoint = function containsPoint (p, geom) {
  32380. if (geom instanceof Polygon) {
  32381. return SimplePointInAreaLocator.containsPointInPolygon(p, geom)
  32382. } else if (geom instanceof GeometryCollection) {
  32383. var geomi = new GeometryCollectionIterator(geom);
  32384. while (geomi.hasNext()) {
  32385. var g2 = geomi.next();
  32386. if (g2 !== geom) { if (SimplePointInAreaLocator.containsPoint(p, g2)) { return true } }
  32387. }
  32388. }
  32389. return false
  32390. };
  32391. SimplePointInAreaLocator.locate = function locate (p, geom) {
  32392. if (geom.isEmpty()) { return Location.EXTERIOR }
  32393. if (SimplePointInAreaLocator.containsPoint(p, geom)) { return Location.INTERIOR }
  32394. return Location.EXTERIOR
  32395. };
  32396. var EdgeEndStar = function EdgeEndStar () {
  32397. this._edgeMap = new TreeMap();
  32398. this._edgeList = null;
  32399. this._ptInAreaLocation = [Location.NONE, Location.NONE];
  32400. };
  32401. EdgeEndStar.prototype.getNextCW = function getNextCW (ee) {
  32402. this.getEdges();
  32403. var i = this._edgeList.indexOf(ee);
  32404. var iNextCW = i - 1;
  32405. if (i === 0) { iNextCW = this._edgeList.size() - 1; }
  32406. return this._edgeList.get(iNextCW)
  32407. };
  32408. EdgeEndStar.prototype.propagateSideLabels = function propagateSideLabels (geomIndex) {
  32409. var startLoc = Location.NONE;
  32410. for (var it = this.iterator(); it.hasNext();) {
  32411. var e = it.next();
  32412. var label = e.getLabel();
  32413. if (label.isArea(geomIndex) && label.getLocation(geomIndex, Position.LEFT) !== Location.NONE) { startLoc = label.getLocation(geomIndex, Position.LEFT); }
  32414. }
  32415. if (startLoc === Location.NONE) { return null }
  32416. var currLoc = startLoc;
  32417. for (var it$1 = this.iterator(); it$1.hasNext();) {
  32418. var e$1 = it$1.next();
  32419. var label$1 = e$1.getLabel();
  32420. if (label$1.getLocation(geomIndex, Position.ON) === Location.NONE) { label$1.setLocation(geomIndex, Position.ON, currLoc); }
  32421. if (label$1.isArea(geomIndex)) {
  32422. var leftLoc = label$1.getLocation(geomIndex, Position.LEFT);
  32423. var rightLoc = label$1.getLocation(geomIndex, Position.RIGHT);
  32424. if (rightLoc !== Location.NONE) {
  32425. if (rightLoc !== currLoc) { throw new TopologyException('side location conflict', e$1.getCoordinate()) }
  32426. if (leftLoc === Location.NONE) {
  32427. Assert.shouldNeverReachHere('found single null side (at ' + e$1.getCoordinate() + ')');
  32428. }
  32429. currLoc = leftLoc;
  32430. } else {
  32431. Assert.isTrue(label$1.getLocation(geomIndex, Position.LEFT) === Location.NONE, 'found single null side');
  32432. label$1.setLocation(geomIndex, Position.RIGHT, currLoc);
  32433. label$1.setLocation(geomIndex, Position.LEFT, currLoc);
  32434. }
  32435. }
  32436. }
  32437. };
  32438. EdgeEndStar.prototype.getCoordinate = function getCoordinate () {
  32439. var it = this.iterator();
  32440. if (!it.hasNext()) { return null }
  32441. var e = it.next();
  32442. return e.getCoordinate()
  32443. };
  32444. EdgeEndStar.prototype.print = function print (out) {
  32445. System.out.println('EdgeEndStar: ' + this.getCoordinate());
  32446. for (var it = this.iterator(); it.hasNext();) {
  32447. var e = it.next();
  32448. e.print(out);
  32449. }
  32450. };
  32451. EdgeEndStar.prototype.isAreaLabelsConsistent = function isAreaLabelsConsistent (geomGraph) {
  32452. this.computeEdgeEndLabels(geomGraph.getBoundaryNodeRule());
  32453. return this.checkAreaLabelsConsistent(0)
  32454. };
  32455. EdgeEndStar.prototype.checkAreaLabelsConsistent = function checkAreaLabelsConsistent (geomIndex) {
  32456. var edges = this.getEdges();
  32457. if (edges.size() <= 0) { return true }
  32458. var lastEdgeIndex = edges.size() - 1;
  32459. var startLabel = edges.get(lastEdgeIndex).getLabel();
  32460. var startLoc = startLabel.getLocation(geomIndex, Position.LEFT);
  32461. Assert.isTrue(startLoc !== Location.NONE, 'Found unlabelled area edge');
  32462. var currLoc = startLoc;
  32463. for (var it = this.iterator(); it.hasNext();) {
  32464. var e = it.next();
  32465. var label = e.getLabel();
  32466. Assert.isTrue(label.isArea(geomIndex), 'Found non-area edge');
  32467. var leftLoc = label.getLocation(geomIndex, Position.LEFT);
  32468. var rightLoc = label.getLocation(geomIndex, Position.RIGHT);
  32469. if (leftLoc === rightLoc) {
  32470. return false
  32471. }
  32472. if (rightLoc !== currLoc) {
  32473. return false
  32474. }
  32475. currLoc = leftLoc;
  32476. }
  32477. return true
  32478. };
  32479. EdgeEndStar.prototype.findIndex = function findIndex (eSearch) {
  32480. var this$1 = this;
  32481. this.iterator();
  32482. for (var i = 0; i < this._edgeList.size(); i++) {
  32483. var e = this$1._edgeList.get(i);
  32484. if (e === eSearch) { return i }
  32485. }
  32486. return -1
  32487. };
  32488. EdgeEndStar.prototype.iterator = function iterator () {
  32489. return this.getEdges().iterator()
  32490. };
  32491. EdgeEndStar.prototype.getEdges = function getEdges () {
  32492. if (this._edgeList === null) {
  32493. this._edgeList = new ArrayList(this._edgeMap.values());
  32494. }
  32495. return this._edgeList
  32496. };
  32497. EdgeEndStar.prototype.getLocation = function getLocation (geomIndex, p, geom) {
  32498. if (this._ptInAreaLocation[geomIndex] === Location.NONE) {
  32499. this._ptInAreaLocation[geomIndex] = SimplePointInAreaLocator.locate(p, geom[geomIndex].getGeometry());
  32500. }
  32501. return this._ptInAreaLocation[geomIndex]
  32502. };
  32503. EdgeEndStar.prototype.toString = function toString () {
  32504. var buf = new StringBuffer();
  32505. buf.append('EdgeEndStar: ' + this.getCoordinate());
  32506. buf.append('\n');
  32507. for (var it = this.iterator(); it.hasNext();) {
  32508. var e = it.next();
  32509. buf.append(e);
  32510. buf.append('\n');
  32511. }
  32512. return buf.toString()
  32513. };
  32514. EdgeEndStar.prototype.computeEdgeEndLabels = function computeEdgeEndLabels (boundaryNodeRule) {
  32515. for (var it = this.iterator(); it.hasNext();) {
  32516. var ee = it.next();
  32517. ee.computeLabel(boundaryNodeRule);
  32518. }
  32519. };
  32520. EdgeEndStar.prototype.computeLabelling = function computeLabelling (geomGraph) {
  32521. var this$1 = this;
  32522. this.computeEdgeEndLabels(geomGraph[0].getBoundaryNodeRule());
  32523. this.propagateSideLabels(0);
  32524. this.propagateSideLabels(1);
  32525. var hasDimensionalCollapseEdge = [false, false];
  32526. for (var it = this.iterator(); it.hasNext();) {
  32527. var e = it.next();
  32528. var label = e.getLabel();
  32529. for (var geomi = 0; geomi < 2; geomi++) {
  32530. if (label.isLine(geomi) && label.getLocation(geomi) === Location.BOUNDARY) { hasDimensionalCollapseEdge[geomi] = true; }
  32531. }
  32532. }
  32533. for (var it$1 = this.iterator(); it$1.hasNext();) {
  32534. var e$1 = it$1.next();
  32535. var label$1 = e$1.getLabel();
  32536. for (var geomi$1 = 0; geomi$1 < 2; geomi$1++) {
  32537. if (label$1.isAnyNull(geomi$1)) {
  32538. var loc = Location.NONE;
  32539. if (hasDimensionalCollapseEdge[geomi$1]) {
  32540. loc = Location.EXTERIOR;
  32541. } else {
  32542. var p = e$1.getCoordinate();
  32543. loc = this$1.getLocation(geomi$1, p, geomGraph);
  32544. }
  32545. label$1.setAllLocationsIfNull(geomi$1, loc);
  32546. }
  32547. }
  32548. }
  32549. };
  32550. EdgeEndStar.prototype.getDegree = function getDegree () {
  32551. return this._edgeMap.size()
  32552. };
  32553. EdgeEndStar.prototype.insertEdgeEnd = function insertEdgeEnd (e, obj) {
  32554. this._edgeMap.put(e, obj);
  32555. this._edgeList = null;
  32556. };
  32557. EdgeEndStar.prototype.interfaces_ = function interfaces_ () {
  32558. return []
  32559. };
  32560. EdgeEndStar.prototype.getClass = function getClass () {
  32561. return EdgeEndStar
  32562. };
  32563. var DirectedEdgeStar = (function (EdgeEndStar$$1) {
  32564. function DirectedEdgeStar () {
  32565. EdgeEndStar$$1.call(this);
  32566. this._resultAreaEdgeList = null;
  32567. this._label = null;
  32568. this._SCANNING_FOR_INCOMING = 1;
  32569. this._LINKING_TO_OUTGOING = 2;
  32570. }
  32571. if ( EdgeEndStar$$1 ) DirectedEdgeStar.__proto__ = EdgeEndStar$$1;
  32572. DirectedEdgeStar.prototype = Object.create( EdgeEndStar$$1 && EdgeEndStar$$1.prototype );
  32573. DirectedEdgeStar.prototype.constructor = DirectedEdgeStar;
  32574. DirectedEdgeStar.prototype.linkResultDirectedEdges = function linkResultDirectedEdges () {
  32575. var this$1 = this;
  32576. this.getResultAreaEdges();
  32577. var firstOut = null;
  32578. var incoming = null;
  32579. var state = this._SCANNING_FOR_INCOMING;
  32580. for (var i = 0; i < this._resultAreaEdgeList.size(); i++) {
  32581. var nextOut = this$1._resultAreaEdgeList.get(i);
  32582. var nextIn = nextOut.getSym();
  32583. if (!nextOut.getLabel().isArea()) { continue }
  32584. if (firstOut === null && nextOut.isInResult()) { firstOut = nextOut; }
  32585. switch (state) {
  32586. case this$1._SCANNING_FOR_INCOMING:
  32587. if (!nextIn.isInResult()) { continue }
  32588. incoming = nextIn;
  32589. state = this$1._LINKING_TO_OUTGOING;
  32590. break
  32591. case this$1._LINKING_TO_OUTGOING:
  32592. if (!nextOut.isInResult()) { continue }
  32593. incoming.setNext(nextOut);
  32594. state = this$1._SCANNING_FOR_INCOMING;
  32595. break
  32596. default:
  32597. }
  32598. }
  32599. if (state === this._LINKING_TO_OUTGOING) {
  32600. if (firstOut === null) { throw new TopologyException('no outgoing dirEdge found', this.getCoordinate()) }
  32601. Assert.isTrue(firstOut.isInResult(), 'unable to link last incoming dirEdge');
  32602. incoming.setNext(firstOut);
  32603. }
  32604. };
  32605. DirectedEdgeStar.prototype.insert = function insert (ee) {
  32606. var de = ee;
  32607. this.insertEdgeEnd(de, de);
  32608. };
  32609. DirectedEdgeStar.prototype.getRightmostEdge = function getRightmostEdge () {
  32610. var edges = this.getEdges();
  32611. var size = edges.size();
  32612. if (size < 1) { return null }
  32613. var de0 = edges.get(0);
  32614. if (size === 1) { return de0 }
  32615. var deLast = edges.get(size - 1);
  32616. var quad0 = de0.getQuadrant();
  32617. var quad1 = deLast.getQuadrant();
  32618. if (Quadrant.isNorthern(quad0) && Quadrant.isNorthern(quad1)) { return de0; } else if (!Quadrant.isNorthern(quad0) && !Quadrant.isNorthern(quad1)) { return deLast; } else {
  32619. // const nonHorizontalEdge = null
  32620. if (de0.getDy() !== 0) { return de0; } else if (deLast.getDy() !== 0) { return deLast }
  32621. }
  32622. Assert.shouldNeverReachHere('found two horizontal edges incident on node');
  32623. return null
  32624. };
  32625. DirectedEdgeStar.prototype.print = function print (out) {
  32626. System.out.println('DirectedEdgeStar: ' + this.getCoordinate());
  32627. for (var it = this.iterator(); it.hasNext();) {
  32628. var de = it.next();
  32629. out.print('out ');
  32630. de.print(out);
  32631. out.println();
  32632. out.print('in ');
  32633. de.getSym().print(out);
  32634. out.println();
  32635. }
  32636. };
  32637. DirectedEdgeStar.prototype.getResultAreaEdges = function getResultAreaEdges () {
  32638. var this$1 = this;
  32639. if (this._resultAreaEdgeList !== null) { return this._resultAreaEdgeList }
  32640. this._resultAreaEdgeList = new ArrayList();
  32641. for (var it = this.iterator(); it.hasNext();) {
  32642. var de = it.next();
  32643. if (de.isInResult() || de.getSym().isInResult()) { this$1._resultAreaEdgeList.add(de); }
  32644. }
  32645. return this._resultAreaEdgeList
  32646. };
  32647. DirectedEdgeStar.prototype.updateLabelling = function updateLabelling (nodeLabel) {
  32648. for (var it = this.iterator(); it.hasNext();) {
  32649. var de = it.next();
  32650. var label = de.getLabel();
  32651. label.setAllLocationsIfNull(0, nodeLabel.getLocation(0));
  32652. label.setAllLocationsIfNull(1, nodeLabel.getLocation(1));
  32653. }
  32654. };
  32655. DirectedEdgeStar.prototype.linkAllDirectedEdges = function linkAllDirectedEdges () {
  32656. var this$1 = this;
  32657. this.getEdges();
  32658. var prevOut = null;
  32659. var firstIn = null;
  32660. for (var i = this._edgeList.size() - 1; i >= 0; i--) {
  32661. var nextOut = this$1._edgeList.get(i);
  32662. var nextIn = nextOut.getSym();
  32663. if (firstIn === null) { firstIn = nextIn; }
  32664. if (prevOut !== null) { nextIn.setNext(prevOut); }
  32665. prevOut = nextOut;
  32666. }
  32667. firstIn.setNext(prevOut);
  32668. };
  32669. DirectedEdgeStar.prototype.computeDepths = function computeDepths () {
  32670. var this$1 = this;
  32671. if (arguments.length === 1) {
  32672. var de = arguments[0];
  32673. var edgeIndex = this.findIndex(de);
  32674. // const label = de.getLabel()
  32675. var startDepth = de.getDepth(Position.LEFT);
  32676. var targetLastDepth = de.getDepth(Position.RIGHT);
  32677. var nextDepth = this.computeDepths(edgeIndex + 1, this._edgeList.size(), startDepth);
  32678. var lastDepth = this.computeDepths(0, edgeIndex, nextDepth);
  32679. if (lastDepth !== targetLastDepth) { throw new TopologyException('depth mismatch at ' + de.getCoordinate()) }
  32680. } else if (arguments.length === 3) {
  32681. var startIndex = arguments[0];
  32682. var endIndex = arguments[1];
  32683. var startDepth$1 = arguments[2];
  32684. var currDepth = startDepth$1;
  32685. for (var i = startIndex; i < endIndex; i++) {
  32686. var nextDe = this$1._edgeList.get(i);
  32687. // const label = nextDe.getLabel()
  32688. nextDe.setEdgeDepths(Position.RIGHT, currDepth);
  32689. currDepth = nextDe.getDepth(Position.LEFT);
  32690. }
  32691. return currDepth
  32692. }
  32693. };
  32694. DirectedEdgeStar.prototype.mergeSymLabels = function mergeSymLabels () {
  32695. for (var it = this.iterator(); it.hasNext();) {
  32696. var de = it.next();
  32697. var label = de.getLabel();
  32698. label.merge(de.getSym().getLabel());
  32699. }
  32700. };
  32701. DirectedEdgeStar.prototype.linkMinimalDirectedEdges = function linkMinimalDirectedEdges (er) {
  32702. var this$1 = this;
  32703. var firstOut = null;
  32704. var incoming = null;
  32705. var state = this._SCANNING_FOR_INCOMING;
  32706. for (var i = this._resultAreaEdgeList.size() - 1; i >= 0; i--) {
  32707. var nextOut = this$1._resultAreaEdgeList.get(i);
  32708. var nextIn = nextOut.getSym();
  32709. if (firstOut === null && nextOut.getEdgeRing() === er) { firstOut = nextOut; }
  32710. switch (state) {
  32711. case this$1._SCANNING_FOR_INCOMING:
  32712. if (nextIn.getEdgeRing() !== er) { continue }
  32713. incoming = nextIn;
  32714. state = this$1._LINKING_TO_OUTGOING;
  32715. break
  32716. case this$1._LINKING_TO_OUTGOING:
  32717. if (nextOut.getEdgeRing() !== er) { continue }
  32718. incoming.setNextMin(nextOut);
  32719. state = this$1._SCANNING_FOR_INCOMING;
  32720. break
  32721. default:
  32722. }
  32723. }
  32724. if (state === this._LINKING_TO_OUTGOING) {
  32725. Assert.isTrue(firstOut !== null, 'found null for first outgoing dirEdge');
  32726. Assert.isTrue(firstOut.getEdgeRing() === er, 'unable to link last incoming dirEdge');
  32727. incoming.setNextMin(firstOut);
  32728. }
  32729. };
  32730. DirectedEdgeStar.prototype.getOutgoingDegree = function getOutgoingDegree () {
  32731. if (arguments.length === 0) {
  32732. var degree = 0;
  32733. for (var it = this.iterator(); it.hasNext();) {
  32734. var de = it.next();
  32735. if (de.isInResult()) { degree++; }
  32736. }
  32737. return degree
  32738. } else if (arguments.length === 1) {
  32739. var er = arguments[0];
  32740. var degree$1 = 0;
  32741. for (var it$1 = this.iterator(); it$1.hasNext();) {
  32742. var de$1 = it$1.next();
  32743. if (de$1.getEdgeRing() === er) { degree$1++; }
  32744. }
  32745. return degree$1
  32746. }
  32747. };
  32748. DirectedEdgeStar.prototype.getLabel = function getLabel () {
  32749. return this._label
  32750. };
  32751. DirectedEdgeStar.prototype.findCoveredLineEdges = function findCoveredLineEdges () {
  32752. var startLoc = Location.NONE;
  32753. for (var it = this.iterator(); it.hasNext();) {
  32754. var nextOut = it.next();
  32755. var nextIn = nextOut.getSym();
  32756. if (!nextOut.isLineEdge()) {
  32757. if (nextOut.isInResult()) {
  32758. startLoc = Location.INTERIOR;
  32759. break
  32760. }
  32761. if (nextIn.isInResult()) {
  32762. startLoc = Location.EXTERIOR;
  32763. break
  32764. }
  32765. }
  32766. }
  32767. if (startLoc === Location.NONE) { return null }
  32768. var currLoc = startLoc;
  32769. for (var it$1 = this.iterator(); it$1.hasNext();) {
  32770. var nextOut$1 = it$1.next();
  32771. var nextIn$1 = nextOut$1.getSym();
  32772. if (nextOut$1.isLineEdge()) {
  32773. nextOut$1.getEdge().setCovered(currLoc === Location.INTERIOR);
  32774. } else {
  32775. if (nextOut$1.isInResult()) { currLoc = Location.EXTERIOR; }
  32776. if (nextIn$1.isInResult()) { currLoc = Location.INTERIOR; }
  32777. }
  32778. }
  32779. };
  32780. DirectedEdgeStar.prototype.computeLabelling = function computeLabelling (geom) {
  32781. var this$1 = this;
  32782. EdgeEndStar$$1.prototype.computeLabelling.call(this, geom);
  32783. this._label = new Label(Location.NONE);
  32784. for (var it = this.iterator(); it.hasNext();) {
  32785. var ee = it.next();
  32786. var e = ee.getEdge();
  32787. var eLabel = e.getLabel();
  32788. for (var i = 0; i < 2; i++) {
  32789. var eLoc = eLabel.getLocation(i);
  32790. if (eLoc === Location.INTERIOR || eLoc === Location.BOUNDARY) { this$1._label.setLocation(i, Location.INTERIOR); }
  32791. }
  32792. }
  32793. };
  32794. DirectedEdgeStar.prototype.interfaces_ = function interfaces_ () {
  32795. return []
  32796. };
  32797. DirectedEdgeStar.prototype.getClass = function getClass () {
  32798. return DirectedEdgeStar
  32799. };
  32800. return DirectedEdgeStar;
  32801. }(EdgeEndStar));
  32802. var OverlayNodeFactory = (function (NodeFactory$$1) {
  32803. function OverlayNodeFactory () {
  32804. NodeFactory$$1.apply(this, arguments);
  32805. }
  32806. if ( NodeFactory$$1 ) OverlayNodeFactory.__proto__ = NodeFactory$$1;
  32807. OverlayNodeFactory.prototype = Object.create( NodeFactory$$1 && NodeFactory$$1.prototype );
  32808. OverlayNodeFactory.prototype.constructor = OverlayNodeFactory;
  32809. OverlayNodeFactory.prototype.createNode = function createNode (coord) {
  32810. return new Node$2(coord, new DirectedEdgeStar())
  32811. };
  32812. OverlayNodeFactory.prototype.interfaces_ = function interfaces_ () {
  32813. return []
  32814. };
  32815. OverlayNodeFactory.prototype.getClass = function getClass () {
  32816. return OverlayNodeFactory
  32817. };
  32818. return OverlayNodeFactory;
  32819. }(NodeFactory));
  32820. var OrientedCoordinateArray = function OrientedCoordinateArray () {
  32821. this._pts = null;
  32822. this._orientation = null;
  32823. var pts = arguments[0];
  32824. this._pts = pts;
  32825. this._orientation = OrientedCoordinateArray.orientation(pts);
  32826. };
  32827. OrientedCoordinateArray.prototype.compareTo = function compareTo (o1) {
  32828. var oca = o1;
  32829. var comp = OrientedCoordinateArray.compareOriented(this._pts, this._orientation, oca._pts, oca._orientation);
  32830. return comp
  32831. };
  32832. OrientedCoordinateArray.prototype.interfaces_ = function interfaces_ () {
  32833. return [Comparable]
  32834. };
  32835. OrientedCoordinateArray.prototype.getClass = function getClass () {
  32836. return OrientedCoordinateArray
  32837. };
  32838. OrientedCoordinateArray.orientation = function orientation (pts) {
  32839. return CoordinateArrays.increasingDirection(pts) === 1
  32840. };
  32841. OrientedCoordinateArray.compareOriented = function compareOriented (pts1, orientation1, pts2, orientation2) {
  32842. var dir1 = orientation1 ? 1 : -1;
  32843. var dir2 = orientation2 ? 1 : -1;
  32844. var limit1 = orientation1 ? pts1.length : -1;
  32845. var limit2 = orientation2 ? pts2.length : -1;
  32846. var i1 = orientation1 ? 0 : pts1.length - 1;
  32847. var i2 = orientation2 ? 0 : pts2.length - 1;
  32848. // const comp = 0
  32849. while (true) {
  32850. var compPt = pts1[i1].compareTo(pts2[i2]);
  32851. if (compPt !== 0) { return compPt }
  32852. i1 += dir1;
  32853. i2 += dir2;
  32854. var done1 = i1 === limit1;
  32855. var done2 = i2 === limit2;
  32856. if (done1 && !done2) { return -1 }
  32857. if (!done1 && done2) { return 1 }
  32858. if (done1 && done2) { return 0 }
  32859. }
  32860. };
  32861. var EdgeList = function EdgeList () {
  32862. this._edges = new ArrayList();
  32863. this._ocaMap = new TreeMap();
  32864. };
  32865. EdgeList.prototype.print = function print (out) {
  32866. var this$1 = this;
  32867. out.print('MULTILINESTRING ( ');
  32868. for (var j = 0; j < this._edges.size(); j++) {
  32869. var e = this$1._edges.get(j);
  32870. if (j > 0) { out.print(','); }
  32871. out.print('(');
  32872. var pts = e.getCoordinates();
  32873. for (var i = 0; i < pts.length; i++) {
  32874. if (i > 0) { out.print(','); }
  32875. out.print(pts[i].x + ' ' + pts[i].y);
  32876. }
  32877. out.println(')');
  32878. }
  32879. out.print(') ');
  32880. };
  32881. EdgeList.prototype.addAll = function addAll (edgeColl) {
  32882. var this$1 = this;
  32883. for (var i = edgeColl.iterator(); i.hasNext();) {
  32884. this$1.add(i.next());
  32885. }
  32886. };
  32887. EdgeList.prototype.findEdgeIndex = function findEdgeIndex (e) {
  32888. var this$1 = this;
  32889. for (var i = 0; i < this._edges.size(); i++) {
  32890. if (this$1._edges.get(i).equals(e)) { return i }
  32891. }
  32892. return -1
  32893. };
  32894. EdgeList.prototype.iterator = function iterator () {
  32895. return this._edges.iterator()
  32896. };
  32897. EdgeList.prototype.getEdges = function getEdges () {
  32898. return this._edges
  32899. };
  32900. EdgeList.prototype.get = function get (i) {
  32901. return this._edges.get(i)
  32902. };
  32903. EdgeList.prototype.findEqualEdge = function findEqualEdge (e) {
  32904. var oca = new OrientedCoordinateArray(e.getCoordinates());
  32905. var matchEdge = this._ocaMap.get(oca);
  32906. return matchEdge
  32907. };
  32908. EdgeList.prototype.add = function add (e) {
  32909. this._edges.add(e);
  32910. var oca = new OrientedCoordinateArray(e.getCoordinates());
  32911. this._ocaMap.put(oca, e);
  32912. };
  32913. EdgeList.prototype.interfaces_ = function interfaces_ () {
  32914. return []
  32915. };
  32916. EdgeList.prototype.getClass = function getClass () {
  32917. return EdgeList
  32918. };
  32919. var SegmentIntersector = function SegmentIntersector () {};
  32920. SegmentIntersector.prototype.processIntersections = function processIntersections (e0, segIndex0, e1, segIndex1) {};
  32921. SegmentIntersector.prototype.isDone = function isDone () {};
  32922. SegmentIntersector.prototype.interfaces_ = function interfaces_ () {
  32923. return []
  32924. };
  32925. SegmentIntersector.prototype.getClass = function getClass () {
  32926. return SegmentIntersector
  32927. };
  32928. var IntersectionAdder = function IntersectionAdder () {
  32929. this._hasIntersection = false;
  32930. this._hasProper = false;
  32931. this._hasProperInterior = false;
  32932. this._hasInterior = false;
  32933. this._properIntersectionPoint = null;
  32934. this._li = null;
  32935. this._isSelfIntersection = null;
  32936. this.numIntersections = 0;
  32937. this.numInteriorIntersections = 0;
  32938. this.numProperIntersections = 0;
  32939. this.numTests = 0;
  32940. var li = arguments[0];
  32941. this._li = li;
  32942. };
  32943. IntersectionAdder.prototype.isTrivialIntersection = function isTrivialIntersection (e0, segIndex0, e1, segIndex1) {
  32944. if (e0 === e1) {
  32945. if (this._li.getIntersectionNum() === 1) {
  32946. if (IntersectionAdder.isAdjacentSegments(segIndex0, segIndex1)) { return true }
  32947. if (e0.isClosed()) {
  32948. var maxSegIndex = e0.size() - 1;
  32949. if ((segIndex0 === 0 && segIndex1 === maxSegIndex) ||
  32950. (segIndex1 === 0 && segIndex0 === maxSegIndex)) {
  32951. return true
  32952. }
  32953. }
  32954. }
  32955. }
  32956. return false
  32957. };
  32958. IntersectionAdder.prototype.getProperIntersectionPoint = function getProperIntersectionPoint () {
  32959. return this._properIntersectionPoint
  32960. };
  32961. IntersectionAdder.prototype.hasProperInteriorIntersection = function hasProperInteriorIntersection () {
  32962. return this._hasProperInterior
  32963. };
  32964. IntersectionAdder.prototype.getLineIntersector = function getLineIntersector () {
  32965. return this._li
  32966. };
  32967. IntersectionAdder.prototype.hasProperIntersection = function hasProperIntersection () {
  32968. return this._hasProper
  32969. };
  32970. IntersectionAdder.prototype.processIntersections = function processIntersections (e0, segIndex0, e1, segIndex1) {
  32971. if (e0 === e1 && segIndex0 === segIndex1) { return null }
  32972. this.numTests++;
  32973. var p00 = e0.getCoordinates()[segIndex0];
  32974. var p01 = e0.getCoordinates()[segIndex0 + 1];
  32975. var p10 = e1.getCoordinates()[segIndex1];
  32976. var p11 = e1.getCoordinates()[segIndex1 + 1];
  32977. this._li.computeIntersection(p00, p01, p10, p11);
  32978. if (this._li.hasIntersection()) {
  32979. this.numIntersections++;
  32980. if (this._li.isInteriorIntersection()) {
  32981. this.numInteriorIntersections++;
  32982. this._hasInterior = true;
  32983. }
  32984. if (!this.isTrivialIntersection(e0, segIndex0, e1, segIndex1)) {
  32985. this._hasIntersection = true;
  32986. e0.addIntersections(this._li, segIndex0, 0);
  32987. e1.addIntersections(this._li, segIndex1, 1);
  32988. if (this._li.isProper()) {
  32989. this.numProperIntersections++;
  32990. this._hasProper = true;
  32991. this._hasProperInterior = true;
  32992. }
  32993. }
  32994. }
  32995. };
  32996. IntersectionAdder.prototype.hasIntersection = function hasIntersection () {
  32997. return this._hasIntersection
  32998. };
  32999. IntersectionAdder.prototype.isDone = function isDone () {
  33000. return false
  33001. };
  33002. IntersectionAdder.prototype.hasInteriorIntersection = function hasInteriorIntersection () {
  33003. return this._hasInterior
  33004. };
  33005. IntersectionAdder.prototype.interfaces_ = function interfaces_ () {
  33006. return [SegmentIntersector]
  33007. };
  33008. IntersectionAdder.prototype.getClass = function getClass () {
  33009. return IntersectionAdder
  33010. };
  33011. IntersectionAdder.isAdjacentSegments = function isAdjacentSegments (i1, i2) {
  33012. return Math.abs(i1 - i2) === 1
  33013. };
  33014. var EdgeIntersection = function EdgeIntersection () {
  33015. this.coord = null;
  33016. this.segmentIndex = null;
  33017. this.dist = null;
  33018. var coord = arguments[0];
  33019. var segmentIndex = arguments[1];
  33020. var dist = arguments[2];
  33021. this.coord = new Coordinate(coord);
  33022. this.segmentIndex = segmentIndex;
  33023. this.dist = dist;
  33024. };
  33025. EdgeIntersection.prototype.getSegmentIndex = function getSegmentIndex () {
  33026. return this.segmentIndex
  33027. };
  33028. EdgeIntersection.prototype.getCoordinate = function getCoordinate () {
  33029. return this.coord
  33030. };
  33031. EdgeIntersection.prototype.print = function print (out) {
  33032. out.print(this.coord);
  33033. out.print(' seg # = ' + this.segmentIndex);
  33034. out.println(' dist = ' + this.dist);
  33035. };
  33036. EdgeIntersection.prototype.compareTo = function compareTo (obj) {
  33037. var other = obj;
  33038. return this.compare(other.segmentIndex, other.dist)
  33039. };
  33040. EdgeIntersection.prototype.isEndPoint = function isEndPoint (maxSegmentIndex) {
  33041. if (this.segmentIndex === 0 && this.dist === 0.0) { return true }
  33042. if (this.segmentIndex === maxSegmentIndex) { return true }
  33043. return false
  33044. };
  33045. EdgeIntersection.prototype.toString = function toString () {
  33046. return this.coord + ' seg # = ' + this.segmentIndex + ' dist = ' + this.dist
  33047. };
  33048. EdgeIntersection.prototype.getDistance = function getDistance () {
  33049. return this.dist
  33050. };
  33051. EdgeIntersection.prototype.compare = function compare (segmentIndex, dist) {
  33052. if (this.segmentIndex < segmentIndex) { return -1 }
  33053. if (this.segmentIndex > segmentIndex) { return 1 }
  33054. if (this.dist < dist) { return -1 }
  33055. if (this.dist > dist) { return 1 }
  33056. return 0
  33057. };
  33058. EdgeIntersection.prototype.interfaces_ = function interfaces_ () {
  33059. return [Comparable]
  33060. };
  33061. EdgeIntersection.prototype.getClass = function getClass () {
  33062. return EdgeIntersection
  33063. };
  33064. var EdgeIntersectionList = function EdgeIntersectionList () {
  33065. this._nodeMap = new TreeMap();
  33066. this.edge = null;
  33067. var edge = arguments[0];
  33068. this.edge = edge;
  33069. };
  33070. EdgeIntersectionList.prototype.print = function print (out) {
  33071. out.println('Intersections:');
  33072. for (var it = this.iterator(); it.hasNext();) {
  33073. var ei = it.next();
  33074. ei.print(out);
  33075. }
  33076. };
  33077. EdgeIntersectionList.prototype.iterator = function iterator () {
  33078. return this._nodeMap.values().iterator()
  33079. };
  33080. EdgeIntersectionList.prototype.addSplitEdges = function addSplitEdges (edgeList) {
  33081. var this$1 = this;
  33082. this.addEndpoints();
  33083. var it = this.iterator();
  33084. var eiPrev = it.next();
  33085. while (it.hasNext()) {
  33086. var ei = it.next();
  33087. var newEdge = this$1.createSplitEdge(eiPrev, ei);
  33088. edgeList.add(newEdge);
  33089. eiPrev = ei;
  33090. }
  33091. };
  33092. EdgeIntersectionList.prototype.addEndpoints = function addEndpoints () {
  33093. var maxSegIndex = this.edge.pts.length - 1;
  33094. this.add(this.edge.pts[0], 0, 0.0);
  33095. this.add(this.edge.pts[maxSegIndex], maxSegIndex, 0.0);
  33096. };
  33097. EdgeIntersectionList.prototype.createSplitEdge = function createSplitEdge (ei0, ei1) {
  33098. var this$1 = this;
  33099. var npts = ei1.segmentIndex - ei0.segmentIndex + 2;
  33100. var lastSegStartPt = this.edge.pts[ei1.segmentIndex];
  33101. var useIntPt1 = ei1.dist > 0.0 || !ei1.coord.equals2D(lastSegStartPt);
  33102. if (!useIntPt1) {
  33103. npts--;
  33104. }
  33105. var pts = new Array(npts).fill(null);
  33106. var ipt = 0;
  33107. pts[ipt++] = new Coordinate(ei0.coord);
  33108. for (var i = ei0.segmentIndex + 1; i <= ei1.segmentIndex; i++) {
  33109. pts[ipt++] = this$1.edge.pts[i];
  33110. }
  33111. if (useIntPt1) { pts[ipt] = ei1.coord; }
  33112. return new Edge$1(pts, new Label(this.edge._label))
  33113. };
  33114. EdgeIntersectionList.prototype.add = function add (intPt, segmentIndex, dist) {
  33115. var eiNew = new EdgeIntersection(intPt, segmentIndex, dist);
  33116. var ei = this._nodeMap.get(eiNew);
  33117. if (ei !== null) {
  33118. return ei
  33119. }
  33120. this._nodeMap.put(eiNew, eiNew);
  33121. return eiNew
  33122. };
  33123. EdgeIntersectionList.prototype.isIntersection = function isIntersection (pt) {
  33124. for (var it = this.iterator(); it.hasNext();) {
  33125. var ei = it.next();
  33126. if (ei.coord.equals(pt)) { return true }
  33127. }
  33128. return false
  33129. };
  33130. EdgeIntersectionList.prototype.interfaces_ = function interfaces_ () {
  33131. return []
  33132. };
  33133. EdgeIntersectionList.prototype.getClass = function getClass () {
  33134. return EdgeIntersectionList
  33135. };
  33136. var MonotoneChainIndexer = function MonotoneChainIndexer () {};
  33137. MonotoneChainIndexer.prototype.getChainStartIndices = function getChainStartIndices (pts) {
  33138. var this$1 = this;
  33139. var start = 0;
  33140. var startIndexList = new ArrayList();
  33141. startIndexList.add(new Integer(start));
  33142. do {
  33143. var last = this$1.findChainEnd(pts, start);
  33144. startIndexList.add(new Integer(last));
  33145. start = last;
  33146. } while (start < pts.length - 1)
  33147. var startIndex = MonotoneChainIndexer.toIntArray(startIndexList);
  33148. return startIndex
  33149. };
  33150. MonotoneChainIndexer.prototype.findChainEnd = function findChainEnd (pts, start) {
  33151. var chainQuad = Quadrant.quadrant(pts[start], pts[start + 1]);
  33152. var last = start + 1;
  33153. while (last < pts.length) {
  33154. var quad = Quadrant.quadrant(pts[last - 1], pts[last]);
  33155. if (quad !== chainQuad) { break }
  33156. last++;
  33157. }
  33158. return last - 1
  33159. };
  33160. MonotoneChainIndexer.prototype.interfaces_ = function interfaces_ () {
  33161. return []
  33162. };
  33163. MonotoneChainIndexer.prototype.getClass = function getClass () {
  33164. return MonotoneChainIndexer
  33165. };
  33166. MonotoneChainIndexer.toIntArray = function toIntArray (list) {
  33167. var array = new Array(list.size()).fill(null);
  33168. for (var i = 0; i < array.length; i++) {
  33169. array[i] = list.get(i).intValue();
  33170. }
  33171. return array
  33172. };
  33173. var MonotoneChainEdge = function MonotoneChainEdge () {
  33174. this.e = null;
  33175. this.pts = null;
  33176. this.startIndex = null;
  33177. this.env1 = new Envelope();
  33178. this.env2 = new Envelope();
  33179. var e = arguments[0];
  33180. this.e = e;
  33181. this.pts = e.getCoordinates();
  33182. var mcb = new MonotoneChainIndexer();
  33183. this.startIndex = mcb.getChainStartIndices(this.pts);
  33184. };
  33185. MonotoneChainEdge.prototype.getCoordinates = function getCoordinates () {
  33186. return this.pts
  33187. };
  33188. MonotoneChainEdge.prototype.getMaxX = function getMaxX (chainIndex) {
  33189. var x1 = this.pts[this.startIndex[chainIndex]].x;
  33190. var x2 = this.pts[this.startIndex[chainIndex + 1]].x;
  33191. return x1 > x2 ? x1 : x2
  33192. };
  33193. MonotoneChainEdge.prototype.getMinX = function getMinX (chainIndex) {
  33194. var x1 = this.pts[this.startIndex[chainIndex]].x;
  33195. var x2 = this.pts[this.startIndex[chainIndex + 1]].x;
  33196. return x1 < x2 ? x1 : x2
  33197. };
  33198. MonotoneChainEdge.prototype.computeIntersectsForChain = function computeIntersectsForChain () {
  33199. if (arguments.length === 4) {
  33200. var chainIndex0 = arguments[0];
  33201. var mce = arguments[1];
  33202. var chainIndex1 = arguments[2];
  33203. var si = arguments[3];
  33204. this.computeIntersectsForChain(this.startIndex[chainIndex0], this.startIndex[chainIndex0 + 1], mce, mce.startIndex[chainIndex1], mce.startIndex[chainIndex1 + 1], si);
  33205. } else if (arguments.length === 6) {
  33206. var start0 = arguments[0];
  33207. var end0 = arguments[1];
  33208. var mce$1 = arguments[2];
  33209. var start1 = arguments[3];
  33210. var end1 = arguments[4];
  33211. var ei = arguments[5];
  33212. var p00 = this.pts[start0];
  33213. var p01 = this.pts[end0];
  33214. var p10 = mce$1.pts[start1];
  33215. var p11 = mce$1.pts[end1];
  33216. if (end0 - start0 === 1 && end1 - start1 === 1) {
  33217. ei.addIntersections(this.e, start0, mce$1.e, start1);
  33218. return null
  33219. }
  33220. this.env1.init(p00, p01);
  33221. this.env2.init(p10, p11);
  33222. if (!this.env1.intersects(this.env2)) { return null }
  33223. var mid0 = Math.trunc((start0 + end0) / 2);
  33224. var mid1 = Math.trunc((start1 + end1) / 2);
  33225. if (start0 < mid0) {
  33226. if (start1 < mid1) { this.computeIntersectsForChain(start0, mid0, mce$1, start1, mid1, ei); }
  33227. if (mid1 < end1) { this.computeIntersectsForChain(start0, mid0, mce$1, mid1, end1, ei); }
  33228. }
  33229. if (mid0 < end0) {
  33230. if (start1 < mid1) { this.computeIntersectsForChain(mid0, end0, mce$1, start1, mid1, ei); }
  33231. if (mid1 < end1) { this.computeIntersectsForChain(mid0, end0, mce$1, mid1, end1, ei); }
  33232. }
  33233. }
  33234. };
  33235. MonotoneChainEdge.prototype.getStartIndexes = function getStartIndexes () {
  33236. return this.startIndex
  33237. };
  33238. MonotoneChainEdge.prototype.computeIntersects = function computeIntersects (mce, si) {
  33239. var this$1 = this;
  33240. for (var i = 0; i < this.startIndex.length - 1; i++) {
  33241. for (var j = 0; j < mce.startIndex.length - 1; j++) {
  33242. this$1.computeIntersectsForChain(i, mce, j, si);
  33243. }
  33244. }
  33245. };
  33246. MonotoneChainEdge.prototype.interfaces_ = function interfaces_ () {
  33247. return []
  33248. };
  33249. MonotoneChainEdge.prototype.getClass = function getClass () {
  33250. return MonotoneChainEdge
  33251. };
  33252. var Depth = function Depth () {
  33253. var this$1 = this;
  33254. this._depth = Array(2).fill().map(function () { return Array(3); });
  33255. for (var i = 0; i < 2; i++) {
  33256. for (var j = 0; j < 3; j++) {
  33257. this$1._depth[i][j] = Depth.NULL_VALUE;
  33258. }
  33259. }
  33260. };
  33261. var staticAccessors$31 = { NULL_VALUE: { configurable: true } };
  33262. Depth.prototype.getDepth = function getDepth (geomIndex, posIndex) {
  33263. return this._depth[geomIndex][posIndex]
  33264. };
  33265. Depth.prototype.setDepth = function setDepth (geomIndex, posIndex, depthValue) {
  33266. this._depth[geomIndex][posIndex] = depthValue;
  33267. };
  33268. Depth.prototype.isNull = function isNull () {
  33269. var this$1 = this;
  33270. if (arguments.length === 0) {
  33271. for (var i = 0; i < 2; i++) {
  33272. for (var j = 0; j < 3; j++) {
  33273. if (this$1._depth[i][j] !== Depth.NULL_VALUE) { return false }
  33274. }
  33275. }
  33276. return true
  33277. } else if (arguments.length === 1) {
  33278. var geomIndex = arguments[0];
  33279. return this._depth[geomIndex][1] === Depth.NULL_VALUE
  33280. } else if (arguments.length === 2) {
  33281. var geomIndex$1 = arguments[0];
  33282. var posIndex = arguments[1];
  33283. return this._depth[geomIndex$1][posIndex] === Depth.NULL_VALUE
  33284. }
  33285. };
  33286. Depth.prototype.normalize = function normalize () {
  33287. var this$1 = this;
  33288. for (var i = 0; i < 2; i++) {
  33289. if (!this$1.isNull(i)) {
  33290. var minDepth = this$1._depth[i][1];
  33291. if (this$1._depth[i][2] < minDepth) { minDepth = this$1._depth[i][2]; }
  33292. if (minDepth < 0) { minDepth = 0; }
  33293. for (var j = 1; j < 3; j++) {
  33294. var newValue = 0;
  33295. if (this$1._depth[i][j] > minDepth) { newValue = 1; }
  33296. this$1._depth[i][j] = newValue;
  33297. }
  33298. }
  33299. }
  33300. };
  33301. Depth.prototype.getDelta = function getDelta (geomIndex) {
  33302. return this._depth[geomIndex][Position.RIGHT] - this._depth[geomIndex][Position.LEFT]
  33303. };
  33304. Depth.prototype.getLocation = function getLocation (geomIndex, posIndex) {
  33305. if (this._depth[geomIndex][posIndex] <= 0) { return Location.EXTERIOR }
  33306. return Location.INTERIOR
  33307. };
  33308. Depth.prototype.toString = function toString () {
  33309. return 'A: ' + this._depth[0][1] + ',' + this._depth[0][2] + ' B: ' + this._depth[1][1] + ',' + this._depth[1][2]
  33310. };
  33311. Depth.prototype.add = function add () {
  33312. var this$1 = this;
  33313. if (arguments.length === 1) {
  33314. var lbl = arguments[0];
  33315. for (var i = 0; i < 2; i++) {
  33316. for (var j = 1; j < 3; j++) {
  33317. var loc = lbl.getLocation(i, j);
  33318. if (loc === Location.EXTERIOR || loc === Location.INTERIOR) {
  33319. if (this$1.isNull(i, j)) {
  33320. this$1._depth[i][j] = Depth.depthAtLocation(loc);
  33321. } else { this$1._depth[i][j] += Depth.depthAtLocation(loc); }
  33322. }
  33323. }
  33324. }
  33325. } else if (arguments.length === 3) {
  33326. var geomIndex = arguments[0];
  33327. var posIndex = arguments[1];
  33328. var location = arguments[2];
  33329. if (location === Location.INTERIOR) { this._depth[geomIndex][posIndex]++; }
  33330. }
  33331. };
  33332. Depth.prototype.interfaces_ = function interfaces_ () {
  33333. return []
  33334. };
  33335. Depth.prototype.getClass = function getClass () {
  33336. return Depth
  33337. };
  33338. Depth.depthAtLocation = function depthAtLocation (location) {
  33339. if (location === Location.EXTERIOR) { return 0 }
  33340. if (location === Location.INTERIOR) { return 1 }
  33341. return Depth.NULL_VALUE
  33342. };
  33343. staticAccessors$31.NULL_VALUE.get = function () { return -1 };
  33344. Object.defineProperties( Depth, staticAccessors$31 );
  33345. var Edge$1 = (function (GraphComponent$$1) {
  33346. function Edge () {
  33347. GraphComponent$$1.call(this);
  33348. this.pts = null;
  33349. this._env = null;
  33350. this.eiList = new EdgeIntersectionList(this);
  33351. this._name = null;
  33352. this._mce = null;
  33353. this._isIsolated = true;
  33354. this._depth = new Depth();
  33355. this._depthDelta = 0;
  33356. if (arguments.length === 1) {
  33357. var pts = arguments[0];
  33358. Edge.call(this, pts, null);
  33359. } else if (arguments.length === 2) {
  33360. var pts$1 = arguments[0];
  33361. var label = arguments[1];
  33362. this.pts = pts$1;
  33363. this._label = label;
  33364. }
  33365. }
  33366. if ( GraphComponent$$1 ) Edge.__proto__ = GraphComponent$$1;
  33367. Edge.prototype = Object.create( GraphComponent$$1 && GraphComponent$$1.prototype );
  33368. Edge.prototype.constructor = Edge;
  33369. Edge.prototype.getDepth = function getDepth () {
  33370. return this._depth
  33371. };
  33372. Edge.prototype.getCollapsedEdge = function getCollapsedEdge () {
  33373. var newPts = new Array(2).fill(null);
  33374. newPts[0] = this.pts[0];
  33375. newPts[1] = this.pts[1];
  33376. var newe = new Edge(newPts, Label.toLineLabel(this._label));
  33377. return newe
  33378. };
  33379. Edge.prototype.isIsolated = function isIsolated () {
  33380. return this._isIsolated
  33381. };
  33382. Edge.prototype.getCoordinates = function getCoordinates () {
  33383. return this.pts
  33384. };
  33385. Edge.prototype.setIsolated = function setIsolated (isIsolated) {
  33386. this._isIsolated = isIsolated;
  33387. };
  33388. Edge.prototype.setName = function setName (name) {
  33389. this._name = name;
  33390. };
  33391. Edge.prototype.equals = function equals (o) {
  33392. var this$1 = this;
  33393. if (!(o instanceof Edge)) { return false }
  33394. var e = o;
  33395. if (this.pts.length !== e.pts.length) { return false }
  33396. var isEqualForward = true;
  33397. var isEqualReverse = true;
  33398. var iRev = this.pts.length;
  33399. for (var i = 0; i < this.pts.length; i++) {
  33400. if (!this$1.pts[i].equals2D(e.pts[i])) {
  33401. isEqualForward = false;
  33402. }
  33403. if (!this$1.pts[i].equals2D(e.pts[--iRev])) {
  33404. isEqualReverse = false;
  33405. }
  33406. if (!isEqualForward && !isEqualReverse) { return false }
  33407. }
  33408. return true
  33409. };
  33410. Edge.prototype.getCoordinate = function getCoordinate () {
  33411. if (arguments.length === 0) {
  33412. if (this.pts.length > 0) { return this.pts[0] }
  33413. return null
  33414. } else if (arguments.length === 1) {
  33415. var i = arguments[0];
  33416. return this.pts[i]
  33417. }
  33418. };
  33419. Edge.prototype.print = function print (out) {
  33420. var this$1 = this;
  33421. out.print('edge ' + this._name + ': ');
  33422. out.print('LINESTRING (');
  33423. for (var i = 0; i < this.pts.length; i++) {
  33424. if (i > 0) { out.print(','); }
  33425. out.print(this$1.pts[i].x + ' ' + this$1.pts[i].y);
  33426. }
  33427. out.print(') ' + this._label + ' ' + this._depthDelta);
  33428. };
  33429. Edge.prototype.computeIM = function computeIM (im) {
  33430. Edge.updateIM(this._label, im);
  33431. };
  33432. Edge.prototype.isCollapsed = function isCollapsed () {
  33433. if (!this._label.isArea()) { return false }
  33434. if (this.pts.length !== 3) { return false }
  33435. if (this.pts[0].equals(this.pts[2])) { return true }
  33436. return false
  33437. };
  33438. Edge.prototype.isClosed = function isClosed () {
  33439. return this.pts[0].equals(this.pts[this.pts.length - 1])
  33440. };
  33441. Edge.prototype.getMaximumSegmentIndex = function getMaximumSegmentIndex () {
  33442. return this.pts.length - 1
  33443. };
  33444. Edge.prototype.getDepthDelta = function getDepthDelta () {
  33445. return this._depthDelta
  33446. };
  33447. Edge.prototype.getNumPoints = function getNumPoints () {
  33448. return this.pts.length
  33449. };
  33450. Edge.prototype.printReverse = function printReverse (out) {
  33451. var this$1 = this;
  33452. out.print('edge ' + this._name + ': ');
  33453. for (var i = this.pts.length - 1; i >= 0; i--) {
  33454. out.print(this$1.pts[i] + ' ');
  33455. }
  33456. out.println('');
  33457. };
  33458. Edge.prototype.getMonotoneChainEdge = function getMonotoneChainEdge () {
  33459. if (this._mce === null) { this._mce = new MonotoneChainEdge(this); }
  33460. return this._mce
  33461. };
  33462. Edge.prototype.getEnvelope = function getEnvelope () {
  33463. var this$1 = this;
  33464. if (this._env === null) {
  33465. this._env = new Envelope();
  33466. for (var i = 0; i < this.pts.length; i++) {
  33467. this$1._env.expandToInclude(this$1.pts[i]);
  33468. }
  33469. }
  33470. return this._env
  33471. };
  33472. Edge.prototype.addIntersection = function addIntersection (li, segmentIndex, geomIndex, intIndex) {
  33473. var intPt = new Coordinate(li.getIntersection(intIndex));
  33474. var normalizedSegmentIndex = segmentIndex;
  33475. var dist = li.getEdgeDistance(geomIndex, intIndex);
  33476. var nextSegIndex = normalizedSegmentIndex + 1;
  33477. if (nextSegIndex < this.pts.length) {
  33478. var nextPt = this.pts[nextSegIndex];
  33479. if (intPt.equals2D(nextPt)) {
  33480. normalizedSegmentIndex = nextSegIndex;
  33481. dist = 0.0;
  33482. }
  33483. }
  33484. this.eiList.add(intPt, normalizedSegmentIndex, dist);
  33485. };
  33486. Edge.prototype.toString = function toString () {
  33487. var this$1 = this;
  33488. var buf = new StringBuffer();
  33489. buf.append('edge ' + this._name + ': ');
  33490. buf.append('LINESTRING (');
  33491. for (var i = 0; i < this.pts.length; i++) {
  33492. if (i > 0) { buf.append(','); }
  33493. buf.append(this$1.pts[i].x + ' ' + this$1.pts[i].y);
  33494. }
  33495. buf.append(') ' + this._label + ' ' + this._depthDelta);
  33496. return buf.toString()
  33497. };
  33498. Edge.prototype.isPointwiseEqual = function isPointwiseEqual (e) {
  33499. var this$1 = this;
  33500. if (this.pts.length !== e.pts.length) { return false }
  33501. for (var i = 0; i < this.pts.length; i++) {
  33502. if (!this$1.pts[i].equals2D(e.pts[i])) {
  33503. return false
  33504. }
  33505. }
  33506. return true
  33507. };
  33508. Edge.prototype.setDepthDelta = function setDepthDelta (depthDelta) {
  33509. this._depthDelta = depthDelta;
  33510. };
  33511. Edge.prototype.getEdgeIntersectionList = function getEdgeIntersectionList () {
  33512. return this.eiList
  33513. };
  33514. Edge.prototype.addIntersections = function addIntersections (li, segmentIndex, geomIndex) {
  33515. var this$1 = this;
  33516. for (var i = 0; i < li.getIntersectionNum(); i++) {
  33517. this$1.addIntersection(li, segmentIndex, geomIndex, i);
  33518. }
  33519. };
  33520. Edge.prototype.interfaces_ = function interfaces_ () {
  33521. return []
  33522. };
  33523. Edge.prototype.getClass = function getClass () {
  33524. return Edge
  33525. };
  33526. Edge.updateIM = function updateIM () {
  33527. if (arguments.length === 2) {
  33528. var label = arguments[0];
  33529. var im = arguments[1];
  33530. im.setAtLeastIfValid(label.getLocation(0, Position.ON), label.getLocation(1, Position.ON), 1);
  33531. if (label.isArea()) {
  33532. im.setAtLeastIfValid(label.getLocation(0, Position.LEFT), label.getLocation(1, Position.LEFT), 2);
  33533. im.setAtLeastIfValid(label.getLocation(0, Position.RIGHT), label.getLocation(1, Position.RIGHT), 2);
  33534. }
  33535. } else { return GraphComponent$$1.prototype.updateIM.apply(this, arguments) }
  33536. };
  33537. return Edge;
  33538. }(GraphComponent));
  33539. var BufferBuilder = function BufferBuilder (bufParams) {
  33540. this._workingPrecisionModel = null;
  33541. this._workingNoder = null;
  33542. this._geomFact = null;
  33543. this._graph = null;
  33544. this._edgeList = new EdgeList();
  33545. this._bufParams = bufParams || null;
  33546. };
  33547. BufferBuilder.prototype.setWorkingPrecisionModel = function setWorkingPrecisionModel (pm) {
  33548. this._workingPrecisionModel = pm;
  33549. };
  33550. BufferBuilder.prototype.insertUniqueEdge = function insertUniqueEdge (e) {
  33551. var existingEdge = this._edgeList.findEqualEdge(e);
  33552. if (existingEdge !== null) {
  33553. var existingLabel = existingEdge.getLabel();
  33554. var labelToMerge = e.getLabel();
  33555. if (!existingEdge.isPointwiseEqual(e)) {
  33556. labelToMerge = new Label(e.getLabel());
  33557. labelToMerge.flip();
  33558. }
  33559. existingLabel.merge(labelToMerge);
  33560. var mergeDelta = BufferBuilder.depthDelta(labelToMerge);
  33561. var existingDelta = existingEdge.getDepthDelta();
  33562. var newDelta = existingDelta + mergeDelta;
  33563. existingEdge.setDepthDelta(newDelta);
  33564. } else {
  33565. this._edgeList.add(e);
  33566. e.setDepthDelta(BufferBuilder.depthDelta(e.getLabel()));
  33567. }
  33568. };
  33569. BufferBuilder.prototype.buildSubgraphs = function buildSubgraphs (subgraphList, polyBuilder) {
  33570. var processedGraphs = new ArrayList();
  33571. for (var i = subgraphList.iterator(); i.hasNext();) {
  33572. var subgraph = i.next();
  33573. var p = subgraph.getRightmostCoordinate();
  33574. var locater = new SubgraphDepthLocater(processedGraphs);
  33575. var outsideDepth = locater.getDepth(p);
  33576. subgraph.computeDepth(outsideDepth);
  33577. subgraph.findResultEdges();
  33578. processedGraphs.add(subgraph);
  33579. polyBuilder.add(subgraph.getDirectedEdges(), subgraph.getNodes());
  33580. }
  33581. };
  33582. BufferBuilder.prototype.createSubgraphs = function createSubgraphs (graph) {
  33583. var subgraphList = new ArrayList();
  33584. for (var i = graph.getNodes().iterator(); i.hasNext();) {
  33585. var node = i.next();
  33586. if (!node.isVisited()) {
  33587. var subgraph = new BufferSubgraph();
  33588. subgraph.create(node);
  33589. subgraphList.add(subgraph);
  33590. }
  33591. }
  33592. Collections.sort(subgraphList, Collections.reverseOrder());
  33593. return subgraphList
  33594. };
  33595. BufferBuilder.prototype.createEmptyResultGeometry = function createEmptyResultGeometry () {
  33596. var emptyGeom = this._geomFact.createPolygon();
  33597. return emptyGeom
  33598. };
  33599. BufferBuilder.prototype.getNoder = function getNoder (precisionModel) {
  33600. if (this._workingNoder !== null) { return this._workingNoder }
  33601. var noder = new MCIndexNoder();
  33602. var li = new RobustLineIntersector();
  33603. li.setPrecisionModel(precisionModel);
  33604. noder.setSegmentIntersector(new IntersectionAdder(li));
  33605. return noder
  33606. };
  33607. BufferBuilder.prototype.buffer = function buffer (g, distance) {
  33608. var precisionModel = this._workingPrecisionModel;
  33609. if (precisionModel === null) { precisionModel = g.getPrecisionModel(); }
  33610. this._geomFact = g.getFactory();
  33611. var curveBuilder = new OffsetCurveBuilder(precisionModel, this._bufParams);
  33612. var curveSetBuilder = new OffsetCurveSetBuilder(g, distance, curveBuilder);
  33613. var bufferSegStrList = curveSetBuilder.getCurves();
  33614. if (bufferSegStrList.size() <= 0) {
  33615. return this.createEmptyResultGeometry()
  33616. }
  33617. this.computeNodedEdges(bufferSegStrList, precisionModel);
  33618. this._graph = new PlanarGraph(new OverlayNodeFactory());
  33619. this._graph.addEdges(this._edgeList.getEdges());
  33620. var subgraphList = this.createSubgraphs(this._graph);
  33621. var polyBuilder = new PolygonBuilder(this._geomFact);
  33622. this.buildSubgraphs(subgraphList, polyBuilder);
  33623. var resultPolyList = polyBuilder.getPolygons();
  33624. if (resultPolyList.size() <= 0) {
  33625. return this.createEmptyResultGeometry()
  33626. }
  33627. var resultGeom = this._geomFact.buildGeometry(resultPolyList);
  33628. return resultGeom
  33629. };
  33630. BufferBuilder.prototype.computeNodedEdges = function computeNodedEdges (bufferSegStrList, precisionModel) {
  33631. var this$1 = this;
  33632. var noder = this.getNoder(precisionModel);
  33633. noder.computeNodes(bufferSegStrList);
  33634. var nodedSegStrings = noder.getNodedSubstrings();
  33635. for (var i = nodedSegStrings.iterator(); i.hasNext();) {
  33636. var segStr = i.next();
  33637. var pts = segStr.getCoordinates();
  33638. if (pts.length === 2 && pts[0].equals2D(pts[1])) { continue }
  33639. var oldLabel = segStr.getData();
  33640. var edge = new Edge$1(segStr.getCoordinates(), new Label(oldLabel));
  33641. this$1.insertUniqueEdge(edge);
  33642. }
  33643. };
  33644. BufferBuilder.prototype.setNoder = function setNoder (noder) {
  33645. this._workingNoder = noder;
  33646. };
  33647. BufferBuilder.prototype.interfaces_ = function interfaces_ () {
  33648. return []
  33649. };
  33650. BufferBuilder.prototype.getClass = function getClass () {
  33651. return BufferBuilder
  33652. };
  33653. BufferBuilder.depthDelta = function depthDelta (label) {
  33654. var lLoc = label.getLocation(0, Position.LEFT);
  33655. var rLoc = label.getLocation(0, Position.RIGHT);
  33656. if (lLoc === Location.INTERIOR && rLoc === Location.EXTERIOR) { return 1; } else if (lLoc === Location.EXTERIOR && rLoc === Location.INTERIOR) { return -1 }
  33657. return 0
  33658. };
  33659. BufferBuilder.convertSegStrings = function convertSegStrings (it) {
  33660. var fact = new GeometryFactory();
  33661. var lines = new ArrayList();
  33662. while (it.hasNext()) {
  33663. var ss = it.next();
  33664. var line = fact.createLineString(ss.getCoordinates());
  33665. lines.add(line);
  33666. }
  33667. return fact.buildGeometry(lines)
  33668. };
  33669. var ScaledNoder = function ScaledNoder () {
  33670. this._noder = null;
  33671. this._scaleFactor = null;
  33672. this._offsetX = null;
  33673. this._offsetY = null;
  33674. this._isScaled = false;
  33675. if (arguments.length === 2) {
  33676. var noder = arguments[0];
  33677. var scaleFactor = arguments[1];
  33678. this._noder = noder;
  33679. this._scaleFactor = scaleFactor;
  33680. this._offsetX = 0.0;
  33681. this._offsetY = 0.0;
  33682. this._isScaled = !this.isIntegerPrecision();
  33683. } else if (arguments.length === 4) {
  33684. var noder$1 = arguments[0];
  33685. var scaleFactor$1 = arguments[1];
  33686. var offsetX = arguments[2];
  33687. var offsetY = arguments[3];
  33688. this._noder = noder$1;
  33689. this._scaleFactor = scaleFactor$1;
  33690. this._offsetX = offsetX;
  33691. this._offsetY = offsetY;
  33692. this._isScaled = !this.isIntegerPrecision();
  33693. }
  33694. };
  33695. ScaledNoder.prototype.rescale = function rescale () {
  33696. var this$1 = this;
  33697. if (hasInterface(arguments[0], Collection)) {
  33698. var segStrings = arguments[0];
  33699. for (var i = segStrings.iterator(); i.hasNext();) {
  33700. var ss = i.next();
  33701. this$1.rescale(ss.getCoordinates());
  33702. }
  33703. } else if (arguments[0] instanceof Array) {
  33704. var pts = arguments[0];
  33705. // let p0 = null
  33706. // let p1 = null
  33707. // if (pts.length === 2) {
  33708. // p0 = new Coordinate(pts[0])
  33709. // p1 = new Coordinate(pts[1])
  33710. // }
  33711. for (var i$1 = 0; i$1 < pts.length; i$1++) {
  33712. pts[i$1].x = pts[i$1].x / this$1._scaleFactor + this$1._offsetX;
  33713. pts[i$1].y = pts[i$1].y / this$1._scaleFactor + this$1._offsetY;
  33714. }
  33715. if (pts.length === 2 && pts[0].equals2D(pts[1])) {
  33716. System.out.println(pts);
  33717. }
  33718. }
  33719. };
  33720. ScaledNoder.prototype.scale = function scale () {
  33721. var this$1 = this;
  33722. if (hasInterface(arguments[0], Collection)) {
  33723. var segStrings = arguments[0];
  33724. var nodedSegmentStrings = new ArrayList();
  33725. for (var i = segStrings.iterator(); i.hasNext();) {
  33726. var ss = i.next();
  33727. nodedSegmentStrings.add(new NodedSegmentString(this$1.scale(ss.getCoordinates()), ss.getData()));
  33728. }
  33729. return nodedSegmentStrings
  33730. } else if (arguments[0] instanceof Array) {
  33731. var pts = arguments[0];
  33732. var roundPts = new Array(pts.length).fill(null);
  33733. for (var i$1 = 0; i$1 < pts.length; i$1++) {
  33734. roundPts[i$1] = new Coordinate(Math.round((pts[i$1].x - this$1._offsetX) * this$1._scaleFactor), Math.round((pts[i$1].y - this$1._offsetY) * this$1._scaleFactor), pts[i$1].z);
  33735. }
  33736. var roundPtsNoDup = CoordinateArrays.removeRepeatedPoints(roundPts);
  33737. return roundPtsNoDup
  33738. }
  33739. };
  33740. ScaledNoder.prototype.isIntegerPrecision = function isIntegerPrecision () {
  33741. return this._scaleFactor === 1.0
  33742. };
  33743. ScaledNoder.prototype.getNodedSubstrings = function getNodedSubstrings () {
  33744. var splitSS = this._noder.getNodedSubstrings();
  33745. if (this._isScaled) { this.rescale(splitSS); }
  33746. return splitSS
  33747. };
  33748. ScaledNoder.prototype.computeNodes = function computeNodes (inputSegStrings) {
  33749. var intSegStrings = inputSegStrings;
  33750. if (this._isScaled) { intSegStrings = this.scale(inputSegStrings); }
  33751. this._noder.computeNodes(intSegStrings);
  33752. };
  33753. ScaledNoder.prototype.interfaces_ = function interfaces_ () {
  33754. return [Noder]
  33755. };
  33756. ScaledNoder.prototype.getClass = function getClass () {
  33757. return ScaledNoder
  33758. };
  33759. var NodingValidator = function NodingValidator () {
  33760. this._li = new RobustLineIntersector();
  33761. this._segStrings = null;
  33762. var segStrings = arguments[0];
  33763. this._segStrings = segStrings;
  33764. };
  33765. var staticAccessors$33 = { fact: { configurable: true } };
  33766. NodingValidator.prototype.checkEndPtVertexIntersections = function checkEndPtVertexIntersections () {
  33767. var this$1 = this;
  33768. if (arguments.length === 0) {
  33769. for (var i = this._segStrings.iterator(); i.hasNext();) {
  33770. var ss = i.next();
  33771. var pts = ss.getCoordinates();
  33772. this$1.checkEndPtVertexIntersections(pts[0], this$1._segStrings);
  33773. this$1.checkEndPtVertexIntersections(pts[pts.length - 1], this$1._segStrings);
  33774. }
  33775. } else if (arguments.length === 2) {
  33776. var testPt = arguments[0];
  33777. var segStrings = arguments[1];
  33778. for (var i$1 = segStrings.iterator(); i$1.hasNext();) {
  33779. var ss$1 = i$1.next();
  33780. var pts$1 = ss$1.getCoordinates();
  33781. for (var j = 1; j < pts$1.length - 1; j++) {
  33782. if (pts$1[j].equals(testPt)) { throw new RuntimeException('found endpt/interior pt intersection at index ' + j + ' :pt ' + testPt) }
  33783. }
  33784. }
  33785. }
  33786. };
  33787. NodingValidator.prototype.checkInteriorIntersections = function checkInteriorIntersections () {
  33788. var this$1 = this;
  33789. if (arguments.length === 0) {
  33790. for (var i = this._segStrings.iterator(); i.hasNext();) {
  33791. var ss0 = i.next();
  33792. for (var j = this._segStrings.iterator(); j.hasNext();) {
  33793. var ss1 = j.next();
  33794. this$1.checkInteriorIntersections(ss0, ss1);
  33795. }
  33796. }
  33797. } else if (arguments.length === 2) {
  33798. var ss0$1 = arguments[0];
  33799. var ss1$1 = arguments[1];
  33800. var pts0 = ss0$1.getCoordinates();
  33801. var pts1 = ss1$1.getCoordinates();
  33802. for (var i0 = 0; i0 < pts0.length - 1; i0++) {
  33803. for (var i1 = 0; i1 < pts1.length - 1; i1++) {
  33804. this$1.checkInteriorIntersections(ss0$1, i0, ss1$1, i1);
  33805. }
  33806. }
  33807. } else if (arguments.length === 4) {
  33808. var e0 = arguments[0];
  33809. var segIndex0 = arguments[1];
  33810. var e1 = arguments[2];
  33811. var segIndex1 = arguments[3];
  33812. if (e0 === e1 && segIndex0 === segIndex1) { return null }
  33813. var p00 = e0.getCoordinates()[segIndex0];
  33814. var p01 = e0.getCoordinates()[segIndex0 + 1];
  33815. var p10 = e1.getCoordinates()[segIndex1];
  33816. var p11 = e1.getCoordinates()[segIndex1 + 1];
  33817. this._li.computeIntersection(p00, p01, p10, p11);
  33818. if (this._li.hasIntersection()) {
  33819. if (this._li.isProper() || this.hasInteriorIntersection(this._li, p00, p01) || this.hasInteriorIntersection(this._li, p10, p11)) {
  33820. throw new RuntimeException('found non-noded intersection at ' + p00 + '-' + p01 + ' and ' + p10 + '-' + p11)
  33821. }
  33822. }
  33823. }
  33824. };
  33825. NodingValidator.prototype.checkValid = function checkValid () {
  33826. this.checkEndPtVertexIntersections();
  33827. this.checkInteriorIntersections();
  33828. this.checkCollapses();
  33829. };
  33830. NodingValidator.prototype.checkCollapses = function checkCollapses () {
  33831. var this$1 = this;
  33832. if (arguments.length === 0) {
  33833. for (var i = this._segStrings.iterator(); i.hasNext();) {
  33834. var ss = i.next();
  33835. this$1.checkCollapses(ss);
  33836. }
  33837. } else if (arguments.length === 1) {
  33838. var ss$1 = arguments[0];
  33839. var pts = ss$1.getCoordinates();
  33840. for (var i$1 = 0; i$1 < pts.length - 2; i$1++) {
  33841. this$1.checkCollapse(pts[i$1], pts[i$1 + 1], pts[i$1 + 2]);
  33842. }
  33843. }
  33844. };
  33845. NodingValidator.prototype.hasInteriorIntersection = function hasInteriorIntersection (li, p0, p1) {
  33846. for (var i = 0; i < li.getIntersectionNum(); i++) {
  33847. var intPt = li.getIntersection(i);
  33848. if (!(intPt.equals(p0) || intPt.equals(p1))) { return true }
  33849. }
  33850. return false
  33851. };
  33852. NodingValidator.prototype.checkCollapse = function checkCollapse (p0, p1, p2) {
  33853. if (p0.equals(p2)) { throw new RuntimeException('found non-noded collapse at ' + NodingValidator.fact.createLineString([p0, p1, p2])) }
  33854. };
  33855. NodingValidator.prototype.interfaces_ = function interfaces_ () {
  33856. return []
  33857. };
  33858. NodingValidator.prototype.getClass = function getClass () {
  33859. return NodingValidator
  33860. };
  33861. staticAccessors$33.fact.get = function () { return new GeometryFactory() };
  33862. Object.defineProperties( NodingValidator, staticAccessors$33 );
  33863. var HotPixel = function HotPixel () {
  33864. this._li = null;
  33865. this._pt = null;
  33866. this._originalPt = null;
  33867. this._ptScaled = null;
  33868. this._p0Scaled = null;
  33869. this._p1Scaled = null;
  33870. this._scaleFactor = null;
  33871. this._minx = null;
  33872. this._maxx = null;
  33873. this._miny = null;
  33874. this._maxy = null;
  33875. this._corner = new Array(4).fill(null);
  33876. this._safeEnv = null;
  33877. var pt = arguments[0];
  33878. var scaleFactor = arguments[1];
  33879. var li = arguments[2];
  33880. this._originalPt = pt;
  33881. this._pt = pt;
  33882. this._scaleFactor = scaleFactor;
  33883. this._li = li;
  33884. if (scaleFactor <= 0) { throw new IllegalArgumentException('Scale factor must be non-zero') }
  33885. if (scaleFactor !== 1.0) {
  33886. this._pt = new Coordinate(this.scale(pt.x), this.scale(pt.y));
  33887. this._p0Scaled = new Coordinate();
  33888. this._p1Scaled = new Coordinate();
  33889. }
  33890. this.initCorners(this._pt);
  33891. };
  33892. var staticAccessors$34 = { SAFE_ENV_EXPANSION_FACTOR: { configurable: true } };
  33893. HotPixel.prototype.intersectsScaled = function intersectsScaled (p0, p1) {
  33894. var segMinx = Math.min(p0.x, p1.x);
  33895. var segMaxx = Math.max(p0.x, p1.x);
  33896. var segMiny = Math.min(p0.y, p1.y);
  33897. var segMaxy = Math.max(p0.y, p1.y);
  33898. var isOutsidePixelEnv = this._maxx < segMinx || this._minx > segMaxx || this._maxy < segMiny || this._miny > segMaxy;
  33899. if (isOutsidePixelEnv) { return false }
  33900. var intersects = this.intersectsToleranceSquare(p0, p1);
  33901. Assert.isTrue(!(isOutsidePixelEnv && intersects), 'Found bad envelope test');
  33902. return intersects
  33903. };
  33904. HotPixel.prototype.initCorners = function initCorners (pt) {
  33905. var tolerance = 0.5;
  33906. this._minx = pt.x - tolerance;
  33907. this._maxx = pt.x + tolerance;
  33908. this._miny = pt.y - tolerance;
  33909. this._maxy = pt.y + tolerance;
  33910. this._corner[0] = new Coordinate(this._maxx, this._maxy);
  33911. this._corner[1] = new Coordinate(this._minx, this._maxy);
  33912. this._corner[2] = new Coordinate(this._minx, this._miny);
  33913. this._corner[3] = new Coordinate(this._maxx, this._miny);
  33914. };
  33915. HotPixel.prototype.intersects = function intersects (p0, p1) {
  33916. if (this._scaleFactor === 1.0) { return this.intersectsScaled(p0, p1) }
  33917. this.copyScaled(p0, this._p0Scaled);
  33918. this.copyScaled(p1, this._p1Scaled);
  33919. return this.intersectsScaled(this._p0Scaled, this._p1Scaled)
  33920. };
  33921. HotPixel.prototype.scale = function scale (val) {
  33922. return Math.round(val * this._scaleFactor)
  33923. };
  33924. HotPixel.prototype.getCoordinate = function getCoordinate () {
  33925. return this._originalPt
  33926. };
  33927. HotPixel.prototype.copyScaled = function copyScaled (p, pScaled) {
  33928. pScaled.x = this.scale(p.x);
  33929. pScaled.y = this.scale(p.y);
  33930. };
  33931. HotPixel.prototype.getSafeEnvelope = function getSafeEnvelope () {
  33932. if (this._safeEnv === null) {
  33933. var safeTolerance = HotPixel.SAFE_ENV_EXPANSION_FACTOR / this._scaleFactor;
  33934. this._safeEnv = new Envelope(this._originalPt.x - safeTolerance, this._originalPt.x + safeTolerance, this._originalPt.y - safeTolerance, this._originalPt.y + safeTolerance);
  33935. }
  33936. return this._safeEnv
  33937. };
  33938. HotPixel.prototype.intersectsPixelClosure = function intersectsPixelClosure (p0, p1) {
  33939. this._li.computeIntersection(p0, p1, this._corner[0], this._corner[1]);
  33940. if (this._li.hasIntersection()) { return true }
  33941. this._li.computeIntersection(p0, p1, this._corner[1], this._corner[2]);
  33942. if (this._li.hasIntersection()) { return true }
  33943. this._li.computeIntersection(p0, p1, this._corner[2], this._corner[3]);
  33944. if (this._li.hasIntersection()) { return true }
  33945. this._li.computeIntersection(p0, p1, this._corner[3], this._corner[0]);
  33946. if (this._li.hasIntersection()) { return true }
  33947. return false
  33948. };
  33949. HotPixel.prototype.intersectsToleranceSquare = function intersectsToleranceSquare (p0, p1) {
  33950. var intersectsLeft = false;
  33951. var intersectsBottom = false;
  33952. this._li.computeIntersection(p0, p1, this._corner[0], this._corner[1]);
  33953. if (this._li.isProper()) { return true }
  33954. this._li.computeIntersection(p0, p1, this._corner[1], this._corner[2]);
  33955. if (this._li.isProper()) { return true }
  33956. if (this._li.hasIntersection()) { intersectsLeft = true; }
  33957. this._li.computeIntersection(p0, p1, this._corner[2], this._corner[3]);
  33958. if (this._li.isProper()) { return true }
  33959. if (this._li.hasIntersection()) { intersectsBottom = true; }
  33960. this._li.computeIntersection(p0, p1, this._corner[3], this._corner[0]);
  33961. if (this._li.isProper()) { return true }
  33962. if (intersectsLeft && intersectsBottom) { return true }
  33963. if (p0.equals(this._pt)) { return true }
  33964. if (p1.equals(this._pt)) { return true }
  33965. return false
  33966. };
  33967. HotPixel.prototype.addSnappedNode = function addSnappedNode (segStr, segIndex) {
  33968. var p0 = segStr.getCoordinate(segIndex);
  33969. var p1 = segStr.getCoordinate(segIndex + 1);
  33970. if (this.intersects(p0, p1)) {
  33971. segStr.addIntersection(this.getCoordinate(), segIndex);
  33972. return true
  33973. }
  33974. return false
  33975. };
  33976. HotPixel.prototype.interfaces_ = function interfaces_ () {
  33977. return []
  33978. };
  33979. HotPixel.prototype.getClass = function getClass () {
  33980. return HotPixel
  33981. };
  33982. staticAccessors$34.SAFE_ENV_EXPANSION_FACTOR.get = function () { return 0.75 };
  33983. Object.defineProperties( HotPixel, staticAccessors$34 );
  33984. var MonotoneChainSelectAction = function MonotoneChainSelectAction () {
  33985. this.tempEnv1 = new Envelope();
  33986. this.selectedSegment = new LineSegment();
  33987. };
  33988. MonotoneChainSelectAction.prototype.select = function select () {
  33989. if (arguments.length === 1) {
  33990. // const seg = arguments[0]
  33991. } else if (arguments.length === 2) {
  33992. var mc = arguments[0];
  33993. var startIndex = arguments[1];
  33994. mc.getLineSegment(startIndex, this.selectedSegment);
  33995. this.select(this.selectedSegment);
  33996. }
  33997. };
  33998. MonotoneChainSelectAction.prototype.interfaces_ = function interfaces_ () {
  33999. return []
  34000. };
  34001. MonotoneChainSelectAction.prototype.getClass = function getClass () {
  34002. return MonotoneChainSelectAction
  34003. };
  34004. var MCIndexPointSnapper = function MCIndexPointSnapper () {
  34005. this._index = null;
  34006. var index = arguments[0];
  34007. this._index = index;
  34008. };
  34009. var staticAccessors$35 = { HotPixelSnapAction: { configurable: true } };
  34010. MCIndexPointSnapper.prototype.snap = function snap () {
  34011. if (arguments.length === 1) {
  34012. var hotPixel = arguments[0];
  34013. return this.snap(hotPixel, null, -1)
  34014. } else if (arguments.length === 3) {
  34015. var hotPixel$1 = arguments[0];
  34016. var parentEdge = arguments[1];
  34017. var hotPixelVertexIndex = arguments[2];
  34018. var pixelEnv = hotPixel$1.getSafeEnvelope();
  34019. var hotPixelSnapAction = new HotPixelSnapAction(hotPixel$1, parentEdge, hotPixelVertexIndex);
  34020. this._index.query(pixelEnv, {
  34021. interfaces_: function () {
  34022. return [ItemVisitor]
  34023. },
  34024. visitItem: function (item) {
  34025. var testChain = item;
  34026. testChain.select(pixelEnv, hotPixelSnapAction);
  34027. }
  34028. });
  34029. return hotPixelSnapAction.isNodeAdded()
  34030. }
  34031. };
  34032. MCIndexPointSnapper.prototype.interfaces_ = function interfaces_ () {
  34033. return []
  34034. };
  34035. MCIndexPointSnapper.prototype.getClass = function getClass () {
  34036. return MCIndexPointSnapper
  34037. };
  34038. staticAccessors$35.HotPixelSnapAction.get = function () { return HotPixelSnapAction };
  34039. Object.defineProperties( MCIndexPointSnapper, staticAccessors$35 );
  34040. var HotPixelSnapAction = (function (MonotoneChainSelectAction$$1) {
  34041. function HotPixelSnapAction () {
  34042. MonotoneChainSelectAction$$1.call(this);
  34043. this._hotPixel = null;
  34044. this._parentEdge = null;
  34045. this._hotPixelVertexIndex = null;
  34046. this._isNodeAdded = false;
  34047. var hotPixel = arguments[0];
  34048. var parentEdge = arguments[1];
  34049. var hotPixelVertexIndex = arguments[2];
  34050. this._hotPixel = hotPixel;
  34051. this._parentEdge = parentEdge;
  34052. this._hotPixelVertexIndex = hotPixelVertexIndex;
  34053. }
  34054. if ( MonotoneChainSelectAction$$1 ) HotPixelSnapAction.__proto__ = MonotoneChainSelectAction$$1;
  34055. HotPixelSnapAction.prototype = Object.create( MonotoneChainSelectAction$$1 && MonotoneChainSelectAction$$1.prototype );
  34056. HotPixelSnapAction.prototype.constructor = HotPixelSnapAction;
  34057. HotPixelSnapAction.prototype.isNodeAdded = function isNodeAdded () {
  34058. return this._isNodeAdded
  34059. };
  34060. HotPixelSnapAction.prototype.select = function select () {
  34061. if (arguments.length === 2) {
  34062. var mc = arguments[0];
  34063. var startIndex = arguments[1];
  34064. var ss = mc.getContext();
  34065. if (this._parentEdge !== null) {
  34066. if (ss === this._parentEdge && startIndex === this._hotPixelVertexIndex) { return null }
  34067. }
  34068. this._isNodeAdded = this._hotPixel.addSnappedNode(ss, startIndex);
  34069. } else { return MonotoneChainSelectAction$$1.prototype.select.apply(this, arguments) }
  34070. };
  34071. HotPixelSnapAction.prototype.interfaces_ = function interfaces_ () {
  34072. return []
  34073. };
  34074. HotPixelSnapAction.prototype.getClass = function getClass () {
  34075. return HotPixelSnapAction
  34076. };
  34077. return HotPixelSnapAction;
  34078. }(MonotoneChainSelectAction));
  34079. var InteriorIntersectionFinderAdder = function InteriorIntersectionFinderAdder () {
  34080. this._li = null;
  34081. this._interiorIntersections = null;
  34082. var li = arguments[0];
  34083. this._li = li;
  34084. this._interiorIntersections = new ArrayList();
  34085. };
  34086. InteriorIntersectionFinderAdder.prototype.processIntersections = function processIntersections (e0, segIndex0, e1, segIndex1) {
  34087. var this$1 = this;
  34088. if (e0 === e1 && segIndex0 === segIndex1) { return null }
  34089. var p00 = e0.getCoordinates()[segIndex0];
  34090. var p01 = e0.getCoordinates()[segIndex0 + 1];
  34091. var p10 = e1.getCoordinates()[segIndex1];
  34092. var p11 = e1.getCoordinates()[segIndex1 + 1];
  34093. this._li.computeIntersection(p00, p01, p10, p11);
  34094. if (this._li.hasIntersection()) {
  34095. if (this._li.isInteriorIntersection()) {
  34096. for (var intIndex = 0; intIndex < this._li.getIntersectionNum(); intIndex++) {
  34097. this$1._interiorIntersections.add(this$1._li.getIntersection(intIndex));
  34098. }
  34099. e0.addIntersections(this._li, segIndex0, 0);
  34100. e1.addIntersections(this._li, segIndex1, 1);
  34101. }
  34102. }
  34103. };
  34104. InteriorIntersectionFinderAdder.prototype.isDone = function isDone () {
  34105. return false
  34106. };
  34107. InteriorIntersectionFinderAdder.prototype.getInteriorIntersections = function getInteriorIntersections () {
  34108. return this._interiorIntersections
  34109. };
  34110. InteriorIntersectionFinderAdder.prototype.interfaces_ = function interfaces_ () {
  34111. return [SegmentIntersector]
  34112. };
  34113. InteriorIntersectionFinderAdder.prototype.getClass = function getClass () {
  34114. return InteriorIntersectionFinderAdder
  34115. };
  34116. var MCIndexSnapRounder = function MCIndexSnapRounder () {
  34117. this._pm = null;
  34118. this._li = null;
  34119. this._scaleFactor = null;
  34120. this._noder = null;
  34121. this._pointSnapper = null;
  34122. this._nodedSegStrings = null;
  34123. var pm = arguments[0];
  34124. this._pm = pm;
  34125. this._li = new RobustLineIntersector();
  34126. this._li.setPrecisionModel(pm);
  34127. this._scaleFactor = pm.getScale();
  34128. };
  34129. MCIndexSnapRounder.prototype.checkCorrectness = function checkCorrectness (inputSegmentStrings) {
  34130. var resultSegStrings = NodedSegmentString.getNodedSubstrings(inputSegmentStrings);
  34131. var nv = new NodingValidator(resultSegStrings);
  34132. try {
  34133. nv.checkValid();
  34134. } catch (ex) {
  34135. if (ex instanceof Exception) {
  34136. ex.printStackTrace();
  34137. } else { throw ex }
  34138. } finally {}
  34139. };
  34140. MCIndexSnapRounder.prototype.getNodedSubstrings = function getNodedSubstrings () {
  34141. return NodedSegmentString.getNodedSubstrings(this._nodedSegStrings)
  34142. };
  34143. MCIndexSnapRounder.prototype.snapRound = function snapRound (segStrings, li) {
  34144. var intersections = this.findInteriorIntersections(segStrings, li);
  34145. this.computeIntersectionSnaps(intersections);
  34146. this.computeVertexSnaps(segStrings);
  34147. };
  34148. MCIndexSnapRounder.prototype.findInteriorIntersections = function findInteriorIntersections (segStrings, li) {
  34149. var intFinderAdder = new InteriorIntersectionFinderAdder(li);
  34150. this._noder.setSegmentIntersector(intFinderAdder);
  34151. this._noder.computeNodes(segStrings);
  34152. return intFinderAdder.getInteriorIntersections()
  34153. };
  34154. MCIndexSnapRounder.prototype.computeVertexSnaps = function computeVertexSnaps () {
  34155. var this$1 = this;
  34156. if (hasInterface(arguments[0], Collection)) {
  34157. var edges = arguments[0];
  34158. for (var i0 = edges.iterator(); i0.hasNext();) {
  34159. var edge0 = i0.next();
  34160. this$1.computeVertexSnaps(edge0);
  34161. }
  34162. } else if (arguments[0] instanceof NodedSegmentString) {
  34163. var e = arguments[0];
  34164. var pts0 = e.getCoordinates();
  34165. for (var i = 0; i < pts0.length; i++) {
  34166. var hotPixel = new HotPixel(pts0[i], this$1._scaleFactor, this$1._li);
  34167. var isNodeAdded = this$1._pointSnapper.snap(hotPixel, e, i);
  34168. if (isNodeAdded) {
  34169. e.addIntersection(pts0[i], i);
  34170. }
  34171. }
  34172. }
  34173. };
  34174. MCIndexSnapRounder.prototype.computeNodes = function computeNodes (inputSegmentStrings) {
  34175. this._nodedSegStrings = inputSegmentStrings;
  34176. this._noder = new MCIndexNoder();
  34177. this._pointSnapper = new MCIndexPointSnapper(this._noder.getIndex());
  34178. this.snapRound(inputSegmentStrings, this._li);
  34179. };
  34180. MCIndexSnapRounder.prototype.computeIntersectionSnaps = function computeIntersectionSnaps (snapPts) {
  34181. var this$1 = this;
  34182. for (var it = snapPts.iterator(); it.hasNext();) {
  34183. var snapPt = it.next();
  34184. var hotPixel = new HotPixel(snapPt, this$1._scaleFactor, this$1._li);
  34185. this$1._pointSnapper.snap(hotPixel);
  34186. }
  34187. };
  34188. MCIndexSnapRounder.prototype.interfaces_ = function interfaces_ () {
  34189. return [Noder]
  34190. };
  34191. MCIndexSnapRounder.prototype.getClass = function getClass () {
  34192. return MCIndexSnapRounder
  34193. };
  34194. var BufferOp = function BufferOp () {
  34195. this._argGeom = null;
  34196. this._distance = null;
  34197. this._bufParams = new BufferParameters();
  34198. this._resultGeometry = null;
  34199. this._saveException = null;
  34200. if (arguments.length === 1) {
  34201. var g = arguments[0];
  34202. this._argGeom = g;
  34203. } else if (arguments.length === 2) {
  34204. var g$1 = arguments[0];
  34205. var bufParams = arguments[1];
  34206. this._argGeom = g$1;
  34207. this._bufParams = bufParams;
  34208. }
  34209. };
  34210. var staticAccessors$32 = { CAP_ROUND: { configurable: true },CAP_BUTT: { configurable: true },CAP_FLAT: { configurable: true },CAP_SQUARE: { configurable: true },MAX_PRECISION_DIGITS: { configurable: true } };
  34211. BufferOp.prototype.bufferFixedPrecision = function bufferFixedPrecision (fixedPM) {
  34212. var noder = new ScaledNoder(new MCIndexSnapRounder(new PrecisionModel(1.0)), fixedPM.getScale());
  34213. var bufBuilder = new BufferBuilder(this._bufParams);
  34214. bufBuilder.setWorkingPrecisionModel(fixedPM);
  34215. bufBuilder.setNoder(noder);
  34216. this._resultGeometry = bufBuilder.buffer(this._argGeom, this._distance);
  34217. };
  34218. BufferOp.prototype.bufferReducedPrecision = function bufferReducedPrecision () {
  34219. var this$1 = this;
  34220. if (arguments.length === 0) {
  34221. for (var precDigits = BufferOp.MAX_PRECISION_DIGITS; precDigits >= 0; precDigits--) {
  34222. try {
  34223. this$1.bufferReducedPrecision(precDigits);
  34224. } catch (ex) {
  34225. if (ex instanceof TopologyException) {
  34226. this$1._saveException = ex;
  34227. } else { throw ex }
  34228. } finally {}
  34229. if (this$1._resultGeometry !== null) { return null }
  34230. }
  34231. throw this._saveException
  34232. } else if (arguments.length === 1) {
  34233. var precisionDigits = arguments[0];
  34234. var sizeBasedScaleFactor = BufferOp.precisionScaleFactor(this._argGeom, this._distance, precisionDigits);
  34235. var fixedPM = new PrecisionModel(sizeBasedScaleFactor);
  34236. this.bufferFixedPrecision(fixedPM);
  34237. }
  34238. };
  34239. BufferOp.prototype.computeGeometry = function computeGeometry () {
  34240. this.bufferOriginalPrecision();
  34241. if (this._resultGeometry !== null) { return null }
  34242. var argPM = this._argGeom.getFactory().getPrecisionModel();
  34243. if (argPM.getType() === PrecisionModel.FIXED) { this.bufferFixedPrecision(argPM); } else { this.bufferReducedPrecision(); }
  34244. };
  34245. BufferOp.prototype.setQuadrantSegments = function setQuadrantSegments (quadrantSegments) {
  34246. this._bufParams.setQuadrantSegments(quadrantSegments);
  34247. };
  34248. BufferOp.prototype.bufferOriginalPrecision = function bufferOriginalPrecision () {
  34249. try {
  34250. var bufBuilder = new BufferBuilder(this._bufParams);
  34251. this._resultGeometry = bufBuilder.buffer(this._argGeom, this._distance);
  34252. } catch (ex) {
  34253. if (ex instanceof RuntimeException) {
  34254. this._saveException = ex;
  34255. } else { throw ex }
  34256. } finally {}
  34257. };
  34258. BufferOp.prototype.getResultGeometry = function getResultGeometry (distance) {
  34259. this._distance = distance;
  34260. this.computeGeometry();
  34261. return this._resultGeometry
  34262. };
  34263. BufferOp.prototype.setEndCapStyle = function setEndCapStyle (endCapStyle) {
  34264. this._bufParams.setEndCapStyle(endCapStyle);
  34265. };
  34266. BufferOp.prototype.interfaces_ = function interfaces_ () {
  34267. return []
  34268. };
  34269. BufferOp.prototype.getClass = function getClass () {
  34270. return BufferOp
  34271. };
  34272. BufferOp.bufferOp = function bufferOp () {
  34273. if (arguments.length === 2) {
  34274. var g = arguments[0];
  34275. var distance = arguments[1];
  34276. var gBuf = new BufferOp(g);
  34277. var geomBuf = gBuf.getResultGeometry(distance);
  34278. return geomBuf
  34279. } else if (arguments.length === 3) {
  34280. if (Number.isInteger(arguments[2]) && (arguments[0] instanceof Geometry && typeof arguments[1] === 'number')) {
  34281. var g$1 = arguments[0];
  34282. var distance$1 = arguments[1];
  34283. var quadrantSegments = arguments[2];
  34284. var bufOp = new BufferOp(g$1);
  34285. bufOp.setQuadrantSegments(quadrantSegments);
  34286. var geomBuf$1 = bufOp.getResultGeometry(distance$1);
  34287. return geomBuf$1
  34288. } else if (arguments[2] instanceof BufferParameters && (arguments[0] instanceof Geometry && typeof arguments[1] === 'number')) {
  34289. var g$2 = arguments[0];
  34290. var distance$2 = arguments[1];
  34291. var params = arguments[2];
  34292. var bufOp$1 = new BufferOp(g$2, params);
  34293. var geomBuf$2 = bufOp$1.getResultGeometry(distance$2);
  34294. return geomBuf$2
  34295. }
  34296. } else if (arguments.length === 4) {
  34297. var g$3 = arguments[0];
  34298. var distance$3 = arguments[1];
  34299. var quadrantSegments$1 = arguments[2];
  34300. var endCapStyle = arguments[3];
  34301. var bufOp$2 = new BufferOp(g$3);
  34302. bufOp$2.setQuadrantSegments(quadrantSegments$1);
  34303. bufOp$2.setEndCapStyle(endCapStyle);
  34304. var geomBuf$3 = bufOp$2.getResultGeometry(distance$3);
  34305. return geomBuf$3
  34306. }
  34307. };
  34308. BufferOp.precisionScaleFactor = function precisionScaleFactor (g, distance, maxPrecisionDigits) {
  34309. var env = g.getEnvelopeInternal();
  34310. var envMax = MathUtil.max(Math.abs(env.getMaxX()), Math.abs(env.getMaxY()), Math.abs(env.getMinX()), Math.abs(env.getMinY()));
  34311. var expandByDistance = distance > 0.0 ? distance : 0.0;
  34312. var bufEnvMax = envMax + 2 * expandByDistance;
  34313. var bufEnvPrecisionDigits = Math.trunc(Math.log(bufEnvMax) / Math.log(10) + 1.0);
  34314. var minUnitLog10 = maxPrecisionDigits - bufEnvPrecisionDigits;
  34315. var scaleFactor = Math.pow(10.0, minUnitLog10);
  34316. return scaleFactor
  34317. };
  34318. staticAccessors$32.CAP_ROUND.get = function () { return BufferParameters.CAP_ROUND };
  34319. staticAccessors$32.CAP_BUTT.get = function () { return BufferParameters.CAP_FLAT };
  34320. staticAccessors$32.CAP_FLAT.get = function () { return BufferParameters.CAP_FLAT };
  34321. staticAccessors$32.CAP_SQUARE.get = function () { return BufferParameters.CAP_SQUARE };
  34322. staticAccessors$32.MAX_PRECISION_DIGITS.get = function () { return 12 };
  34323. Object.defineProperties( BufferOp, staticAccessors$32 );
  34324. var PointPairDistance = function PointPairDistance () {
  34325. this._pt = [new Coordinate(), new Coordinate()];
  34326. this._distance = Double.NaN;
  34327. this._isNull = true;
  34328. };
  34329. PointPairDistance.prototype.getCoordinates = function getCoordinates () {
  34330. return this._pt
  34331. };
  34332. PointPairDistance.prototype.getCoordinate = function getCoordinate (i) {
  34333. return this._pt[i]
  34334. };
  34335. PointPairDistance.prototype.setMinimum = function setMinimum () {
  34336. if (arguments.length === 1) {
  34337. var ptDist = arguments[0];
  34338. this.setMinimum(ptDist._pt[0], ptDist._pt[1]);
  34339. } else if (arguments.length === 2) {
  34340. var p0 = arguments[0];
  34341. var p1 = arguments[1];
  34342. if (this._isNull) {
  34343. this.initialize(p0, p1);
  34344. return null
  34345. }
  34346. var dist = p0.distance(p1);
  34347. if (dist < this._distance) { this.initialize(p0, p1, dist); }
  34348. }
  34349. };
  34350. PointPairDistance.prototype.initialize = function initialize () {
  34351. if (arguments.length === 0) {
  34352. this._isNull = true;
  34353. } else if (arguments.length === 2) {
  34354. var p0 = arguments[0];
  34355. var p1 = arguments[1];
  34356. this._pt[0].setCoordinate(p0);
  34357. this._pt[1].setCoordinate(p1);
  34358. this._distance = p0.distance(p1);
  34359. this._isNull = false;
  34360. } else if (arguments.length === 3) {
  34361. var p0$1 = arguments[0];
  34362. var p1$1 = arguments[1];
  34363. var distance = arguments[2];
  34364. this._pt[0].setCoordinate(p0$1);
  34365. this._pt[1].setCoordinate(p1$1);
  34366. this._distance = distance;
  34367. this._isNull = false;
  34368. }
  34369. };
  34370. PointPairDistance.prototype.getDistance = function getDistance () {
  34371. return this._distance
  34372. };
  34373. PointPairDistance.prototype.setMaximum = function setMaximum () {
  34374. if (arguments.length === 1) {
  34375. var ptDist = arguments[0];
  34376. this.setMaximum(ptDist._pt[0], ptDist._pt[1]);
  34377. } else if (arguments.length === 2) {
  34378. var p0 = arguments[0];
  34379. var p1 = arguments[1];
  34380. if (this._isNull) {
  34381. this.initialize(p0, p1);
  34382. return null
  34383. }
  34384. var dist = p0.distance(p1);
  34385. if (dist > this._distance) { this.initialize(p0, p1, dist); }
  34386. }
  34387. };
  34388. PointPairDistance.prototype.interfaces_ = function interfaces_ () {
  34389. return []
  34390. };
  34391. PointPairDistance.prototype.getClass = function getClass () {
  34392. return PointPairDistance
  34393. };
  34394. var DistanceToPointFinder = function DistanceToPointFinder () {};
  34395. DistanceToPointFinder.prototype.interfaces_ = function interfaces_ () {
  34396. return []
  34397. };
  34398. DistanceToPointFinder.prototype.getClass = function getClass () {
  34399. return DistanceToPointFinder
  34400. };
  34401. DistanceToPointFinder.computeDistance = function computeDistance () {
  34402. if (arguments[2] instanceof PointPairDistance && (arguments[0] instanceof LineString$1 && arguments[1] instanceof Coordinate)) {
  34403. var line = arguments[0];
  34404. var pt = arguments[1];
  34405. var ptDist = arguments[2];
  34406. var coords = line.getCoordinates();
  34407. var tempSegment = new LineSegment();
  34408. for (var i = 0; i < coords.length - 1; i++) {
  34409. tempSegment.setCoordinates(coords[i], coords[i + 1]);
  34410. var closestPt = tempSegment.closestPoint(pt);
  34411. ptDist.setMinimum(closestPt, pt);
  34412. }
  34413. } else if (arguments[2] instanceof PointPairDistance && (arguments[0] instanceof Polygon && arguments[1] instanceof Coordinate)) {
  34414. var poly = arguments[0];
  34415. var pt$1 = arguments[1];
  34416. var ptDist$1 = arguments[2];
  34417. DistanceToPointFinder.computeDistance(poly.getExteriorRing(), pt$1, ptDist$1);
  34418. for (var i$1 = 0; i$1 < poly.getNumInteriorRing(); i$1++) {
  34419. DistanceToPointFinder.computeDistance(poly.getInteriorRingN(i$1), pt$1, ptDist$1);
  34420. }
  34421. } else if (arguments[2] instanceof PointPairDistance && (arguments[0] instanceof Geometry && arguments[1] instanceof Coordinate)) {
  34422. var geom = arguments[0];
  34423. var pt$2 = arguments[1];
  34424. var ptDist$2 = arguments[2];
  34425. if (geom instanceof LineString$1) {
  34426. DistanceToPointFinder.computeDistance(geom, pt$2, ptDist$2);
  34427. } else if (geom instanceof Polygon) {
  34428. DistanceToPointFinder.computeDistance(geom, pt$2, ptDist$2);
  34429. } else if (geom instanceof GeometryCollection) {
  34430. var gc = geom;
  34431. for (var i$2 = 0; i$2 < gc.getNumGeometries(); i$2++) {
  34432. var g = gc.getGeometryN(i$2);
  34433. DistanceToPointFinder.computeDistance(g, pt$2, ptDist$2);
  34434. }
  34435. } else {
  34436. ptDist$2.setMinimum(geom.getCoordinate(), pt$2);
  34437. }
  34438. } else if (arguments[2] instanceof PointPairDistance && (arguments[0] instanceof LineSegment && arguments[1] instanceof Coordinate)) {
  34439. var segment = arguments[0];
  34440. var pt$3 = arguments[1];
  34441. var ptDist$3 = arguments[2];
  34442. var closestPt$1 = segment.closestPoint(pt$3);
  34443. ptDist$3.setMinimum(closestPt$1, pt$3);
  34444. }
  34445. };
  34446. var BufferCurveMaximumDistanceFinder = function BufferCurveMaximumDistanceFinder (inputGeom) {
  34447. this._maxPtDist = new PointPairDistance();
  34448. this._inputGeom = inputGeom || null;
  34449. };
  34450. var staticAccessors$36 = { MaxPointDistanceFilter: { configurable: true },MaxMidpointDistanceFilter: { configurable: true } };
  34451. BufferCurveMaximumDistanceFinder.prototype.computeMaxMidpointDistance = function computeMaxMidpointDistance (curve) {
  34452. var distFilter = new MaxMidpointDistanceFilter(this._inputGeom);
  34453. curve.apply(distFilter);
  34454. this._maxPtDist.setMaximum(distFilter.getMaxPointDistance());
  34455. };
  34456. BufferCurveMaximumDistanceFinder.prototype.computeMaxVertexDistance = function computeMaxVertexDistance (curve) {
  34457. var distFilter = new MaxPointDistanceFilter(this._inputGeom);
  34458. curve.apply(distFilter);
  34459. this._maxPtDist.setMaximum(distFilter.getMaxPointDistance());
  34460. };
  34461. BufferCurveMaximumDistanceFinder.prototype.findDistance = function findDistance (bufferCurve) {
  34462. this.computeMaxVertexDistance(bufferCurve);
  34463. this.computeMaxMidpointDistance(bufferCurve);
  34464. return this._maxPtDist.getDistance()
  34465. };
  34466. BufferCurveMaximumDistanceFinder.prototype.getDistancePoints = function getDistancePoints () {
  34467. return this._maxPtDist
  34468. };
  34469. BufferCurveMaximumDistanceFinder.prototype.interfaces_ = function interfaces_ () {
  34470. return []
  34471. };
  34472. BufferCurveMaximumDistanceFinder.prototype.getClass = function getClass () {
  34473. return BufferCurveMaximumDistanceFinder
  34474. };
  34475. staticAccessors$36.MaxPointDistanceFilter.get = function () { return MaxPointDistanceFilter };
  34476. staticAccessors$36.MaxMidpointDistanceFilter.get = function () { return MaxMidpointDistanceFilter };
  34477. Object.defineProperties( BufferCurveMaximumDistanceFinder, staticAccessors$36 );
  34478. var MaxPointDistanceFilter = function MaxPointDistanceFilter (geom) {
  34479. this._maxPtDist = new PointPairDistance();
  34480. this._minPtDist = new PointPairDistance();
  34481. this._geom = geom || null;
  34482. };
  34483. MaxPointDistanceFilter.prototype.filter = function filter (pt) {
  34484. this._minPtDist.initialize();
  34485. DistanceToPointFinder.computeDistance(this._geom, pt, this._minPtDist);
  34486. this._maxPtDist.setMaximum(this._minPtDist);
  34487. };
  34488. MaxPointDistanceFilter.prototype.getMaxPointDistance = function getMaxPointDistance () {
  34489. return this._maxPtDist
  34490. };
  34491. MaxPointDistanceFilter.prototype.interfaces_ = function interfaces_ () {
  34492. return [CoordinateFilter]
  34493. };
  34494. MaxPointDistanceFilter.prototype.getClass = function getClass () {
  34495. return MaxPointDistanceFilter
  34496. };
  34497. var MaxMidpointDistanceFilter = function MaxMidpointDistanceFilter (geom) {
  34498. this._maxPtDist = new PointPairDistance();
  34499. this._minPtDist = new PointPairDistance();
  34500. this._geom = geom || null;
  34501. };
  34502. MaxMidpointDistanceFilter.prototype.filter = function filter (seq, index) {
  34503. if (index === 0) { return null }
  34504. var p0 = seq.getCoordinate(index - 1);
  34505. var p1 = seq.getCoordinate(index);
  34506. var midPt = new Coordinate((p0.x + p1.x) / 2, (p0.y + p1.y) / 2);
  34507. this._minPtDist.initialize();
  34508. DistanceToPointFinder.computeDistance(this._geom, midPt, this._minPtDist);
  34509. this._maxPtDist.setMaximum(this._minPtDist);
  34510. };
  34511. MaxMidpointDistanceFilter.prototype.isDone = function isDone () {
  34512. return false
  34513. };
  34514. MaxMidpointDistanceFilter.prototype.isGeometryChanged = function isGeometryChanged () {
  34515. return false
  34516. };
  34517. MaxMidpointDistanceFilter.prototype.getMaxPointDistance = function getMaxPointDistance () {
  34518. return this._maxPtDist
  34519. };
  34520. MaxMidpointDistanceFilter.prototype.interfaces_ = function interfaces_ () {
  34521. return [CoordinateSequenceFilter]
  34522. };
  34523. MaxMidpointDistanceFilter.prototype.getClass = function getClass () {
  34524. return MaxMidpointDistanceFilter
  34525. };
  34526. var PolygonExtracter = function PolygonExtracter (comps) {
  34527. this._comps = comps || null;
  34528. };
  34529. PolygonExtracter.prototype.filter = function filter (geom) {
  34530. if (geom instanceof Polygon) { this._comps.add(geom); }
  34531. };
  34532. PolygonExtracter.prototype.interfaces_ = function interfaces_ () {
  34533. return [GeometryFilter]
  34534. };
  34535. PolygonExtracter.prototype.getClass = function getClass () {
  34536. return PolygonExtracter
  34537. };
  34538. PolygonExtracter.getPolygons = function getPolygons () {
  34539. if (arguments.length === 1) {
  34540. var geom = arguments[0];
  34541. return PolygonExtracter.getPolygons(geom, new ArrayList())
  34542. } else if (arguments.length === 2) {
  34543. var geom$1 = arguments[0];
  34544. var list = arguments[1];
  34545. if (geom$1 instanceof Polygon) {
  34546. list.add(geom$1);
  34547. } else if (geom$1 instanceof GeometryCollection) {
  34548. geom$1.apply(new PolygonExtracter(list));
  34549. }
  34550. return list
  34551. }
  34552. };
  34553. var LinearComponentExtracter = function LinearComponentExtracter () {
  34554. this._lines = null;
  34555. this._isForcedToLineString = false;
  34556. if (arguments.length === 1) {
  34557. var lines = arguments[0];
  34558. this._lines = lines;
  34559. } else if (arguments.length === 2) {
  34560. var lines$1 = arguments[0];
  34561. var isForcedToLineString = arguments[1];
  34562. this._lines = lines$1;
  34563. this._isForcedToLineString = isForcedToLineString;
  34564. }
  34565. };
  34566. LinearComponentExtracter.prototype.filter = function filter (geom) {
  34567. if (this._isForcedToLineString && geom instanceof LinearRing) {
  34568. var line = geom.getFactory().createLineString(geom.getCoordinateSequence());
  34569. this._lines.add(line);
  34570. return null
  34571. }
  34572. if (geom instanceof LineString$1) { this._lines.add(geom); }
  34573. };
  34574. LinearComponentExtracter.prototype.setForceToLineString = function setForceToLineString (isForcedToLineString) {
  34575. this._isForcedToLineString = isForcedToLineString;
  34576. };
  34577. LinearComponentExtracter.prototype.interfaces_ = function interfaces_ () {
  34578. return [GeometryComponentFilter]
  34579. };
  34580. LinearComponentExtracter.prototype.getClass = function getClass () {
  34581. return LinearComponentExtracter
  34582. };
  34583. LinearComponentExtracter.getGeometry = function getGeometry () {
  34584. if (arguments.length === 1) {
  34585. var geom = arguments[0];
  34586. return geom.getFactory().buildGeometry(LinearComponentExtracter.getLines(geom))
  34587. } else if (arguments.length === 2) {
  34588. var geom$1 = arguments[0];
  34589. var forceToLineString = arguments[1];
  34590. return geom$1.getFactory().buildGeometry(LinearComponentExtracter.getLines(geom$1, forceToLineString))
  34591. }
  34592. };
  34593. LinearComponentExtracter.getLines = function getLines () {
  34594. if (arguments.length === 1) {
  34595. var geom = arguments[0];
  34596. return LinearComponentExtracter.getLines(geom, false)
  34597. } else if (arguments.length === 2) {
  34598. if (hasInterface(arguments[0], Collection) && hasInterface(arguments[1], Collection)) {
  34599. var geoms = arguments[0];
  34600. var lines$1 = arguments[1];
  34601. for (var i = geoms.iterator(); i.hasNext();) {
  34602. var g = i.next();
  34603. LinearComponentExtracter.getLines(g, lines$1);
  34604. }
  34605. return lines$1
  34606. } else if (arguments[0] instanceof Geometry && typeof arguments[1] === 'boolean') {
  34607. var geom$1 = arguments[0];
  34608. var forceToLineString = arguments[1];
  34609. var lines = new ArrayList();
  34610. geom$1.apply(new LinearComponentExtracter(lines, forceToLineString));
  34611. return lines
  34612. } else if (arguments[0] instanceof Geometry && hasInterface(arguments[1], Collection)) {
  34613. var geom$2 = arguments[0];
  34614. var lines$2 = arguments[1];
  34615. if (geom$2 instanceof LineString$1) {
  34616. lines$2.add(geom$2);
  34617. } else {
  34618. geom$2.apply(new LinearComponentExtracter(lines$2));
  34619. }
  34620. return lines$2
  34621. }
  34622. } else if (arguments.length === 3) {
  34623. if (typeof arguments[2] === 'boolean' && (hasInterface(arguments[0], Collection) && hasInterface(arguments[1], Collection))) {
  34624. var geoms$1 = arguments[0];
  34625. var lines$3 = arguments[1];
  34626. var forceToLineString$1 = arguments[2];
  34627. for (var i$1 = geoms$1.iterator(); i$1.hasNext();) {
  34628. var g$1 = i$1.next();
  34629. LinearComponentExtracter.getLines(g$1, lines$3, forceToLineString$1);
  34630. }
  34631. return lines$3
  34632. } else if (typeof arguments[2] === 'boolean' && (arguments[0] instanceof Geometry && hasInterface(arguments[1], Collection))) {
  34633. var geom$3 = arguments[0];
  34634. var lines$4 = arguments[1];
  34635. var forceToLineString$2 = arguments[2];
  34636. geom$3.apply(new LinearComponentExtracter(lines$4, forceToLineString$2));
  34637. return lines$4
  34638. }
  34639. }
  34640. };
  34641. var PointLocator = function PointLocator () {
  34642. this._boundaryRule = BoundaryNodeRule.OGC_SFS_BOUNDARY_RULE;
  34643. this._isIn = null;
  34644. this._numBoundaries = null;
  34645. if (arguments.length === 0) {} else if (arguments.length === 1) {
  34646. var boundaryRule = arguments[0];
  34647. if (boundaryRule === null) { throw new IllegalArgumentException('Rule must be non-null') }
  34648. this._boundaryRule = boundaryRule;
  34649. }
  34650. };
  34651. PointLocator.prototype.locateInternal = function locateInternal () {
  34652. var this$1 = this;
  34653. if (arguments[0] instanceof Coordinate && arguments[1] instanceof Polygon) {
  34654. var p = arguments[0];
  34655. var poly = arguments[1];
  34656. if (poly.isEmpty()) { return Location.EXTERIOR }
  34657. var shell = poly.getExteriorRing();
  34658. var shellLoc = this.locateInPolygonRing(p, shell);
  34659. if (shellLoc === Location.EXTERIOR) { return Location.EXTERIOR }
  34660. if (shellLoc === Location.BOUNDARY) { return Location.BOUNDARY }
  34661. for (var i = 0; i < poly.getNumInteriorRing(); i++) {
  34662. var hole = poly.getInteriorRingN(i);
  34663. var holeLoc = this$1.locateInPolygonRing(p, hole);
  34664. if (holeLoc === Location.INTERIOR) { return Location.EXTERIOR }
  34665. if (holeLoc === Location.BOUNDARY) { return Location.BOUNDARY }
  34666. }
  34667. return Location.INTERIOR
  34668. } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof LineString$1) {
  34669. var p$1 = arguments[0];
  34670. var l = arguments[1];
  34671. if (!l.getEnvelopeInternal().intersects(p$1)) { return Location.EXTERIOR }
  34672. var pt = l.getCoordinates();
  34673. if (!l.isClosed()) {
  34674. if (p$1.equals(pt[0]) || p$1.equals(pt[pt.length - 1])) {
  34675. return Location.BOUNDARY
  34676. }
  34677. }
  34678. if (CGAlgorithms.isOnLine(p$1, pt)) { return Location.INTERIOR }
  34679. return Location.EXTERIOR
  34680. } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Point) {
  34681. var p$2 = arguments[0];
  34682. var pt$1 = arguments[1];
  34683. var ptCoord = pt$1.getCoordinate();
  34684. if (ptCoord.equals2D(p$2)) { return Location.INTERIOR }
  34685. return Location.EXTERIOR
  34686. }
  34687. };
  34688. PointLocator.prototype.locateInPolygonRing = function locateInPolygonRing (p, ring) {
  34689. if (!ring.getEnvelopeInternal().intersects(p)) { return Location.EXTERIOR }
  34690. return CGAlgorithms.locatePointInRing(p, ring.getCoordinates())
  34691. };
  34692. PointLocator.prototype.intersects = function intersects (p, geom) {
  34693. return this.locate(p, geom) !== Location.EXTERIOR
  34694. };
  34695. PointLocator.prototype.updateLocationInfo = function updateLocationInfo (loc) {
  34696. if (loc === Location.INTERIOR) { this._isIn = true; }
  34697. if (loc === Location.BOUNDARY) { this._numBoundaries++; }
  34698. };
  34699. PointLocator.prototype.computeLocation = function computeLocation (p, geom) {
  34700. var this$1 = this;
  34701. if (geom instanceof Point) {
  34702. this.updateLocationInfo(this.locateInternal(p, geom));
  34703. }
  34704. if (geom instanceof LineString$1) {
  34705. this.updateLocationInfo(this.locateInternal(p, geom));
  34706. } else if (geom instanceof Polygon) {
  34707. this.updateLocationInfo(this.locateInternal(p, geom));
  34708. } else if (geom instanceof MultiLineString) {
  34709. var ml = geom;
  34710. for (var i = 0; i < ml.getNumGeometries(); i++) {
  34711. var l = ml.getGeometryN(i);
  34712. this$1.updateLocationInfo(this$1.locateInternal(p, l));
  34713. }
  34714. } else if (geom instanceof MultiPolygon) {
  34715. var mpoly = geom;
  34716. for (var i$1 = 0; i$1 < mpoly.getNumGeometries(); i$1++) {
  34717. var poly = mpoly.getGeometryN(i$1);
  34718. this$1.updateLocationInfo(this$1.locateInternal(p, poly));
  34719. }
  34720. } else if (geom instanceof GeometryCollection) {
  34721. var geomi = new GeometryCollectionIterator(geom);
  34722. while (geomi.hasNext()) {
  34723. var g2 = geomi.next();
  34724. if (g2 !== geom) { this$1.computeLocation(p, g2); }
  34725. }
  34726. }
  34727. };
  34728. PointLocator.prototype.locate = function locate (p, geom) {
  34729. if (geom.isEmpty()) { return Location.EXTERIOR }
  34730. if (geom instanceof LineString$1) {
  34731. return this.locateInternal(p, geom)
  34732. } else if (geom instanceof Polygon) {
  34733. return this.locateInternal(p, geom)
  34734. }
  34735. this._isIn = false;
  34736. this._numBoundaries = 0;
  34737. this.computeLocation(p, geom);
  34738. if (this._boundaryRule.isInBoundary(this._numBoundaries)) { return Location.BOUNDARY }
  34739. if (this._numBoundaries > 0 || this._isIn) { return Location.INTERIOR }
  34740. return Location.EXTERIOR
  34741. };
  34742. PointLocator.prototype.interfaces_ = function interfaces_ () {
  34743. return []
  34744. };
  34745. PointLocator.prototype.getClass = function getClass () {
  34746. return PointLocator
  34747. };
  34748. var GeometryLocation = function GeometryLocation () {
  34749. this._component = null;
  34750. this._segIndex = null;
  34751. this._pt = null;
  34752. if (arguments.length === 2) {
  34753. var component = arguments[0];
  34754. var pt = arguments[1];
  34755. GeometryLocation.call(this, component, GeometryLocation.INSIDE_AREA, pt);
  34756. } else if (arguments.length === 3) {
  34757. var component$1 = arguments[0];
  34758. var segIndex = arguments[1];
  34759. var pt$1 = arguments[2];
  34760. this._component = component$1;
  34761. this._segIndex = segIndex;
  34762. this._pt = pt$1;
  34763. }
  34764. };
  34765. var staticAccessors$38 = { INSIDE_AREA: { configurable: true } };
  34766. GeometryLocation.prototype.isInsideArea = function isInsideArea () {
  34767. return this._segIndex === GeometryLocation.INSIDE_AREA
  34768. };
  34769. GeometryLocation.prototype.getCoordinate = function getCoordinate () {
  34770. return this._pt
  34771. };
  34772. GeometryLocation.prototype.getGeometryComponent = function getGeometryComponent () {
  34773. return this._component
  34774. };
  34775. GeometryLocation.prototype.getSegmentIndex = function getSegmentIndex () {
  34776. return this._segIndex
  34777. };
  34778. GeometryLocation.prototype.interfaces_ = function interfaces_ () {
  34779. return []
  34780. };
  34781. GeometryLocation.prototype.getClass = function getClass () {
  34782. return GeometryLocation
  34783. };
  34784. staticAccessors$38.INSIDE_AREA.get = function () { return -1 };
  34785. Object.defineProperties( GeometryLocation, staticAccessors$38 );
  34786. var PointExtracter = function PointExtracter (pts) {
  34787. this._pts = pts || null;
  34788. };
  34789. PointExtracter.prototype.filter = function filter (geom) {
  34790. if (geom instanceof Point) { this._pts.add(geom); }
  34791. };
  34792. PointExtracter.prototype.interfaces_ = function interfaces_ () {
  34793. return [GeometryFilter]
  34794. };
  34795. PointExtracter.prototype.getClass = function getClass () {
  34796. return PointExtracter
  34797. };
  34798. PointExtracter.getPoints = function getPoints () {
  34799. if (arguments.length === 1) {
  34800. var geom = arguments[0];
  34801. if (geom instanceof Point) {
  34802. return Collections.singletonList(geom)
  34803. }
  34804. return PointExtracter.getPoints(geom, new ArrayList())
  34805. } else if (arguments.length === 2) {
  34806. var geom$1 = arguments[0];
  34807. var list = arguments[1];
  34808. if (geom$1 instanceof Point) {
  34809. list.add(geom$1);
  34810. } else if (geom$1 instanceof GeometryCollection) {
  34811. geom$1.apply(new PointExtracter(list));
  34812. }
  34813. return list
  34814. }
  34815. };
  34816. var ConnectedElementLocationFilter = function ConnectedElementLocationFilter () {
  34817. this._locations = null;
  34818. var locations = arguments[0];
  34819. this._locations = locations;
  34820. };
  34821. ConnectedElementLocationFilter.prototype.filter = function filter (geom) {
  34822. if (geom instanceof Point || geom instanceof LineString$1 || geom instanceof Polygon) { this._locations.add(new GeometryLocation(geom, 0, geom.getCoordinate())); }
  34823. };
  34824. ConnectedElementLocationFilter.prototype.interfaces_ = function interfaces_ () {
  34825. return [GeometryFilter]
  34826. };
  34827. ConnectedElementLocationFilter.prototype.getClass = function getClass () {
  34828. return ConnectedElementLocationFilter
  34829. };
  34830. ConnectedElementLocationFilter.getLocations = function getLocations (geom) {
  34831. var locations = new ArrayList();
  34832. geom.apply(new ConnectedElementLocationFilter(locations));
  34833. return locations
  34834. };
  34835. var DistanceOp = function DistanceOp () {
  34836. this._geom = null;
  34837. this._terminateDistance = 0.0;
  34838. this._ptLocator = new PointLocator();
  34839. this._minDistanceLocation = null;
  34840. this._minDistance = Double.MAX_VALUE;
  34841. if (arguments.length === 2) {
  34842. var g0 = arguments[0];
  34843. var g1 = arguments[1];
  34844. this._geom = [g0, g1];
  34845. this._terminateDistance = 0.0;
  34846. } else if (arguments.length === 3) {
  34847. var g0$1 = arguments[0];
  34848. var g1$1 = arguments[1];
  34849. var terminateDistance = arguments[2];
  34850. this._geom = new Array(2).fill(null);
  34851. this._geom[0] = g0$1;
  34852. this._geom[1] = g1$1;
  34853. this._terminateDistance = terminateDistance;
  34854. }
  34855. };
  34856. DistanceOp.prototype.computeContainmentDistance = function computeContainmentDistance () {
  34857. var this$1 = this;
  34858. if (arguments.length === 0) {
  34859. var locPtPoly = new Array(2).fill(null);
  34860. this.computeContainmentDistance(0, locPtPoly);
  34861. if (this._minDistance <= this._terminateDistance) { return null }
  34862. this.computeContainmentDistance(1, locPtPoly);
  34863. } else if (arguments.length === 2) {
  34864. var polyGeomIndex = arguments[0];
  34865. var locPtPoly$1 = arguments[1];
  34866. var locationsIndex = 1 - polyGeomIndex;
  34867. var polys = PolygonExtracter.getPolygons(this._geom[polyGeomIndex]);
  34868. if (polys.size() > 0) {
  34869. var insideLocs = ConnectedElementLocationFilter.getLocations(this._geom[locationsIndex]);
  34870. this.computeContainmentDistance(insideLocs, polys, locPtPoly$1);
  34871. if (this._minDistance <= this._terminateDistance) {
  34872. this._minDistanceLocation[locationsIndex] = locPtPoly$1[0];
  34873. this._minDistanceLocation[polyGeomIndex] = locPtPoly$1[1];
  34874. return null
  34875. }
  34876. }
  34877. } else if (arguments.length === 3) {
  34878. if (arguments[2] instanceof Array && (hasInterface(arguments[0], List) && hasInterface(arguments[1], List))) {
  34879. var locs = arguments[0];
  34880. var polys$1 = arguments[1];
  34881. var locPtPoly$2 = arguments[2];
  34882. for (var i = 0; i < locs.size(); i++) {
  34883. var loc = locs.get(i);
  34884. for (var j = 0; j < polys$1.size(); j++) {
  34885. this$1.computeContainmentDistance(loc, polys$1.get(j), locPtPoly$2);
  34886. if (this$1._minDistance <= this$1._terminateDistance) { return null }
  34887. }
  34888. }
  34889. } else if (arguments[2] instanceof Array && (arguments[0] instanceof GeometryLocation && arguments[1] instanceof Polygon)) {
  34890. var ptLoc = arguments[0];
  34891. var poly = arguments[1];
  34892. var locPtPoly$3 = arguments[2];
  34893. var pt = ptLoc.getCoordinate();
  34894. if (Location.EXTERIOR !== this._ptLocator.locate(pt, poly)) {
  34895. this._minDistance = 0.0;
  34896. locPtPoly$3[0] = ptLoc;
  34897. locPtPoly$3[1] = new GeometryLocation(poly, pt);
  34898. return null
  34899. }
  34900. }
  34901. }
  34902. };
  34903. DistanceOp.prototype.computeMinDistanceLinesPoints = function computeMinDistanceLinesPoints (lines, points, locGeom) {
  34904. var this$1 = this;
  34905. for (var i = 0; i < lines.size(); i++) {
  34906. var line = lines.get(i);
  34907. for (var j = 0; j < points.size(); j++) {
  34908. var pt = points.get(j);
  34909. this$1.computeMinDistance(line, pt, locGeom);
  34910. if (this$1._minDistance <= this$1._terminateDistance) { return null }
  34911. }
  34912. }
  34913. };
  34914. DistanceOp.prototype.computeFacetDistance = function computeFacetDistance () {
  34915. var locGeom = new Array(2).fill(null);
  34916. var lines0 = LinearComponentExtracter.getLines(this._geom[0]);
  34917. var lines1 = LinearComponentExtracter.getLines(this._geom[1]);
  34918. var pts0 = PointExtracter.getPoints(this._geom[0]);
  34919. var pts1 = PointExtracter.getPoints(this._geom[1]);
  34920. this.computeMinDistanceLines(lines0, lines1, locGeom);
  34921. this.updateMinDistance(locGeom, false);
  34922. if (this._minDistance <= this._terminateDistance) { return null }
  34923. locGeom[0] = null;
  34924. locGeom[1] = null;
  34925. this.computeMinDistanceLinesPoints(lines0, pts1, locGeom);
  34926. this.updateMinDistance(locGeom, false);
  34927. if (this._minDistance <= this._terminateDistance) { return null }
  34928. locGeom[0] = null;
  34929. locGeom[1] = null;
  34930. this.computeMinDistanceLinesPoints(lines1, pts0, locGeom);
  34931. this.updateMinDistance(locGeom, true);
  34932. if (this._minDistance <= this._terminateDistance) { return null }
  34933. locGeom[0] = null;
  34934. locGeom[1] = null;
  34935. this.computeMinDistancePoints(pts0, pts1, locGeom);
  34936. this.updateMinDistance(locGeom, false);
  34937. };
  34938. DistanceOp.prototype.nearestLocations = function nearestLocations () {
  34939. this.computeMinDistance();
  34940. return this._minDistanceLocation
  34941. };
  34942. DistanceOp.prototype.updateMinDistance = function updateMinDistance (locGeom, flip) {
  34943. if (locGeom[0] === null) { return null }
  34944. if (flip) {
  34945. this._minDistanceLocation[0] = locGeom[1];
  34946. this._minDistanceLocation[1] = locGeom[0];
  34947. } else {
  34948. this._minDistanceLocation[0] = locGeom[0];
  34949. this._minDistanceLocation[1] = locGeom[1];
  34950. }
  34951. };
  34952. DistanceOp.prototype.nearestPoints = function nearestPoints () {
  34953. this.computeMinDistance();
  34954. var nearestPts = [this._minDistanceLocation[0].getCoordinate(), this._minDistanceLocation[1].getCoordinate()];
  34955. return nearestPts
  34956. };
  34957. DistanceOp.prototype.computeMinDistance = function computeMinDistance () {
  34958. var this$1 = this;
  34959. if (arguments.length === 0) {
  34960. if (this._minDistanceLocation !== null) { return null }
  34961. this._minDistanceLocation = new Array(2).fill(null);
  34962. this.computeContainmentDistance();
  34963. if (this._minDistance <= this._terminateDistance) { return null }
  34964. this.computeFacetDistance();
  34965. } else if (arguments.length === 3) {
  34966. if (arguments[2] instanceof Array && (arguments[0] instanceof LineString$1 && arguments[1] instanceof Point)) {
  34967. var line = arguments[0];
  34968. var pt = arguments[1];
  34969. var locGeom = arguments[2];
  34970. if (line.getEnvelopeInternal().distance(pt.getEnvelopeInternal()) > this._minDistance) { return null }
  34971. var coord0 = line.getCoordinates();
  34972. var coord = pt.getCoordinate();
  34973. for (var i = 0; i < coord0.length - 1; i++) {
  34974. var dist = CGAlgorithms.distancePointLine(coord, coord0[i], coord0[i + 1]);
  34975. if (dist < this$1._minDistance) {
  34976. this$1._minDistance = dist;
  34977. var seg = new LineSegment(coord0[i], coord0[i + 1]);
  34978. var segClosestPoint = seg.closestPoint(coord);
  34979. locGeom[0] = new GeometryLocation(line, i, segClosestPoint);
  34980. locGeom[1] = new GeometryLocation(pt, 0, coord);
  34981. }
  34982. if (this$1._minDistance <= this$1._terminateDistance) { return null }
  34983. }
  34984. } else if (arguments[2] instanceof Array && (arguments[0] instanceof LineString$1 && arguments[1] instanceof LineString$1)) {
  34985. var line0 = arguments[0];
  34986. var line1 = arguments[1];
  34987. var locGeom$1 = arguments[2];
  34988. if (line0.getEnvelopeInternal().distance(line1.getEnvelopeInternal()) > this._minDistance) { return null }
  34989. var coord0$1 = line0.getCoordinates();
  34990. var coord1 = line1.getCoordinates();
  34991. for (var i$1 = 0; i$1 < coord0$1.length - 1; i$1++) {
  34992. for (var j = 0; j < coord1.length - 1; j++) {
  34993. var dist$1 = CGAlgorithms.distanceLineLine(coord0$1[i$1], coord0$1[i$1 + 1], coord1[j], coord1[j + 1]);
  34994. if (dist$1 < this$1._minDistance) {
  34995. this$1._minDistance = dist$1;
  34996. var seg0 = new LineSegment(coord0$1[i$1], coord0$1[i$1 + 1]);
  34997. var seg1 = new LineSegment(coord1[j], coord1[j + 1]);
  34998. var closestPt = seg0.closestPoints(seg1);
  34999. locGeom$1[0] = new GeometryLocation(line0, i$1, closestPt[0]);
  35000. locGeom$1[1] = new GeometryLocation(line1, j, closestPt[1]);
  35001. }
  35002. if (this$1._minDistance <= this$1._terminateDistance) { return null }
  35003. }
  35004. }
  35005. }
  35006. }
  35007. };
  35008. DistanceOp.prototype.computeMinDistancePoints = function computeMinDistancePoints (points0, points1, locGeom) {
  35009. var this$1 = this;
  35010. for (var i = 0; i < points0.size(); i++) {
  35011. var pt0 = points0.get(i);
  35012. for (var j = 0; j < points1.size(); j++) {
  35013. var pt1 = points1.get(j);
  35014. var dist = pt0.getCoordinate().distance(pt1.getCoordinate());
  35015. if (dist < this$1._minDistance) {
  35016. this$1._minDistance = dist;
  35017. locGeom[0] = new GeometryLocation(pt0, 0, pt0.getCoordinate());
  35018. locGeom[1] = new GeometryLocation(pt1, 0, pt1.getCoordinate());
  35019. }
  35020. if (this$1._minDistance <= this$1._terminateDistance) { return null }
  35021. }
  35022. }
  35023. };
  35024. DistanceOp.prototype.distance = function distance () {
  35025. if (this._geom[0] === null || this._geom[1] === null) { throw new IllegalArgumentException('null geometries are not supported') }
  35026. if (this._geom[0].isEmpty() || this._geom[1].isEmpty()) { return 0.0 }
  35027. this.computeMinDistance();
  35028. return this._minDistance
  35029. };
  35030. DistanceOp.prototype.computeMinDistanceLines = function computeMinDistanceLines (lines0, lines1, locGeom) {
  35031. var this$1 = this;
  35032. for (var i = 0; i < lines0.size(); i++) {
  35033. var line0 = lines0.get(i);
  35034. for (var j = 0; j < lines1.size(); j++) {
  35035. var line1 = lines1.get(j);
  35036. this$1.computeMinDistance(line0, line1, locGeom);
  35037. if (this$1._minDistance <= this$1._terminateDistance) { return null }
  35038. }
  35039. }
  35040. };
  35041. DistanceOp.prototype.interfaces_ = function interfaces_ () {
  35042. return []
  35043. };
  35044. DistanceOp.prototype.getClass = function getClass () {
  35045. return DistanceOp
  35046. };
  35047. DistanceOp.distance = function distance (g0, g1) {
  35048. var distOp = new DistanceOp(g0, g1);
  35049. return distOp.distance()
  35050. };
  35051. DistanceOp.isWithinDistance = function isWithinDistance (g0, g1, distance) {
  35052. var distOp = new DistanceOp(g0, g1, distance);
  35053. return distOp.distance() <= distance
  35054. };
  35055. DistanceOp.nearestPoints = function nearestPoints (g0, g1) {
  35056. var distOp = new DistanceOp(g0, g1);
  35057. return distOp.nearestPoints()
  35058. };
  35059. var PointPairDistance$2 = function PointPairDistance () {
  35060. this._pt = [new Coordinate(), new Coordinate()];
  35061. this._distance = Double.NaN;
  35062. this._isNull = true;
  35063. };
  35064. PointPairDistance$2.prototype.getCoordinates = function getCoordinates () {
  35065. return this._pt
  35066. };
  35067. PointPairDistance$2.prototype.getCoordinate = function getCoordinate (i) {
  35068. return this._pt[i]
  35069. };
  35070. PointPairDistance$2.prototype.setMinimum = function setMinimum () {
  35071. if (arguments.length === 1) {
  35072. var ptDist = arguments[0];
  35073. this.setMinimum(ptDist._pt[0], ptDist._pt[1]);
  35074. } else if (arguments.length === 2) {
  35075. var p0 = arguments[0];
  35076. var p1 = arguments[1];
  35077. if (this._isNull) {
  35078. this.initialize(p0, p1);
  35079. return null
  35080. }
  35081. var dist = p0.distance(p1);
  35082. if (dist < this._distance) { this.initialize(p0, p1, dist); }
  35083. }
  35084. };
  35085. PointPairDistance$2.prototype.initialize = function initialize () {
  35086. if (arguments.length === 0) {
  35087. this._isNull = true;
  35088. } else if (arguments.length === 2) {
  35089. var p0 = arguments[0];
  35090. var p1 = arguments[1];
  35091. this._pt[0].setCoordinate(p0);
  35092. this._pt[1].setCoordinate(p1);
  35093. this._distance = p0.distance(p1);
  35094. this._isNull = false;
  35095. } else if (arguments.length === 3) {
  35096. var p0$1 = arguments[0];
  35097. var p1$1 = arguments[1];
  35098. var distance = arguments[2];
  35099. this._pt[0].setCoordinate(p0$1);
  35100. this._pt[1].setCoordinate(p1$1);
  35101. this._distance = distance;
  35102. this._isNull = false;
  35103. }
  35104. };
  35105. PointPairDistance$2.prototype.toString = function toString () {
  35106. return WKTWriter.toLineString(this._pt[0], this._pt[1])
  35107. };
  35108. PointPairDistance$2.prototype.getDistance = function getDistance () {
  35109. return this._distance
  35110. };
  35111. PointPairDistance$2.prototype.setMaximum = function setMaximum () {
  35112. if (arguments.length === 1) {
  35113. var ptDist = arguments[0];
  35114. this.setMaximum(ptDist._pt[0], ptDist._pt[1]);
  35115. } else if (arguments.length === 2) {
  35116. var p0 = arguments[0];
  35117. var p1 = arguments[1];
  35118. if (this._isNull) {
  35119. this.initialize(p0, p1);
  35120. return null
  35121. }
  35122. var dist = p0.distance(p1);
  35123. if (dist > this._distance) { this.initialize(p0, p1, dist); }
  35124. }
  35125. };
  35126. PointPairDistance$2.prototype.interfaces_ = function interfaces_ () {
  35127. return []
  35128. };
  35129. PointPairDistance$2.prototype.getClass = function getClass () {
  35130. return PointPairDistance$2
  35131. };
  35132. var DistanceToPoint = function DistanceToPoint () {};
  35133. DistanceToPoint.prototype.interfaces_ = function interfaces_ () {
  35134. return []
  35135. };
  35136. DistanceToPoint.prototype.getClass = function getClass () {
  35137. return DistanceToPoint
  35138. };
  35139. DistanceToPoint.computeDistance = function computeDistance () {
  35140. if (arguments[2] instanceof PointPairDistance$2 && (arguments[0] instanceof LineString$1 && arguments[1] instanceof Coordinate)) {
  35141. var line = arguments[0];
  35142. var pt = arguments[1];
  35143. var ptDist = arguments[2];
  35144. var tempSegment = new LineSegment();
  35145. var coords = line.getCoordinates();
  35146. for (var i = 0; i < coords.length - 1; i++) {
  35147. tempSegment.setCoordinates(coords[i], coords[i + 1]);
  35148. var closestPt = tempSegment.closestPoint(pt);
  35149. ptDist.setMinimum(closestPt, pt);
  35150. }
  35151. } else if (arguments[2] instanceof PointPairDistance$2 && (arguments[0] instanceof Polygon && arguments[1] instanceof Coordinate)) {
  35152. var poly = arguments[0];
  35153. var pt$1 = arguments[1];
  35154. var ptDist$1 = arguments[2];
  35155. DistanceToPoint.computeDistance(poly.getExteriorRing(), pt$1, ptDist$1);
  35156. for (var i$1 = 0; i$1 < poly.getNumInteriorRing(); i$1++) {
  35157. DistanceToPoint.computeDistance(poly.getInteriorRingN(i$1), pt$1, ptDist$1);
  35158. }
  35159. } else if (arguments[2] instanceof PointPairDistance$2 && (arguments[0] instanceof Geometry && arguments[1] instanceof Coordinate)) {
  35160. var geom = arguments[0];
  35161. var pt$2 = arguments[1];
  35162. var ptDist$2 = arguments[2];
  35163. if (geom instanceof LineString$1) {
  35164. DistanceToPoint.computeDistance(geom, pt$2, ptDist$2);
  35165. } else if (geom instanceof Polygon) {
  35166. DistanceToPoint.computeDistance(geom, pt$2, ptDist$2);
  35167. } else if (geom instanceof GeometryCollection) {
  35168. var gc = geom;
  35169. for (var i$2 = 0; i$2 < gc.getNumGeometries(); i$2++) {
  35170. var g = gc.getGeometryN(i$2);
  35171. DistanceToPoint.computeDistance(g, pt$2, ptDist$2);
  35172. }
  35173. } else {
  35174. ptDist$2.setMinimum(geom.getCoordinate(), pt$2);
  35175. }
  35176. } else if (arguments[2] instanceof PointPairDistance$2 && (arguments[0] instanceof LineSegment && arguments[1] instanceof Coordinate)) {
  35177. var segment = arguments[0];
  35178. var pt$3 = arguments[1];
  35179. var ptDist$3 = arguments[2];
  35180. var closestPt$1 = segment.closestPoint(pt$3);
  35181. ptDist$3.setMinimum(closestPt$1, pt$3);
  35182. }
  35183. };
  35184. var DiscreteHausdorffDistance = function DiscreteHausdorffDistance () {
  35185. this._g0 = null;
  35186. this._g1 = null;
  35187. this._ptDist = new PointPairDistance$2();
  35188. this._densifyFrac = 0.0;
  35189. var g0 = arguments[0];
  35190. var g1 = arguments[1];
  35191. this._g0 = g0;
  35192. this._g1 = g1;
  35193. };
  35194. var staticAccessors$39 = { MaxPointDistanceFilter: { configurable: true },MaxDensifiedByFractionDistanceFilter: { configurable: true } };
  35195. DiscreteHausdorffDistance.prototype.getCoordinates = function getCoordinates () {
  35196. return this._ptDist.getCoordinates()
  35197. };
  35198. DiscreteHausdorffDistance.prototype.setDensifyFraction = function setDensifyFraction (densifyFrac) {
  35199. if (densifyFrac > 1.0 || densifyFrac <= 0.0) { throw new IllegalArgumentException('Fraction is not in range (0.0 - 1.0]') }
  35200. this._densifyFrac = densifyFrac;
  35201. };
  35202. DiscreteHausdorffDistance.prototype.compute = function compute (g0, g1) {
  35203. this.computeOrientedDistance(g0, g1, this._ptDist);
  35204. this.computeOrientedDistance(g1, g0, this._ptDist);
  35205. };
  35206. DiscreteHausdorffDistance.prototype.distance = function distance () {
  35207. this.compute(this._g0, this._g1);
  35208. return this._ptDist.getDistance()
  35209. };
  35210. DiscreteHausdorffDistance.prototype.computeOrientedDistance = function computeOrientedDistance (discreteGeom, geom, ptDist) {
  35211. var distFilter = new MaxPointDistanceFilter$1(geom);
  35212. discreteGeom.apply(distFilter);
  35213. ptDist.setMaximum(distFilter.getMaxPointDistance());
  35214. if (this._densifyFrac > 0) {
  35215. var fracFilter = new MaxDensifiedByFractionDistanceFilter(geom, this._densifyFrac);
  35216. discreteGeom.apply(fracFilter);
  35217. ptDist.setMaximum(fracFilter.getMaxPointDistance());
  35218. }
  35219. };
  35220. DiscreteHausdorffDistance.prototype.orientedDistance = function orientedDistance () {
  35221. this.computeOrientedDistance(this._g0, this._g1, this._ptDist);
  35222. return this._ptDist.getDistance()
  35223. };
  35224. DiscreteHausdorffDistance.prototype.interfaces_ = function interfaces_ () {
  35225. return []
  35226. };
  35227. DiscreteHausdorffDistance.prototype.getClass = function getClass () {
  35228. return DiscreteHausdorffDistance
  35229. };
  35230. DiscreteHausdorffDistance.distance = function distance () {
  35231. if (arguments.length === 2) {
  35232. var g0 = arguments[0];
  35233. var g1 = arguments[1];
  35234. var dist = new DiscreteHausdorffDistance(g0, g1);
  35235. return dist.distance()
  35236. } else if (arguments.length === 3) {
  35237. var g0$1 = arguments[0];
  35238. var g1$1 = arguments[1];
  35239. var densifyFrac = arguments[2];
  35240. var dist$1 = new DiscreteHausdorffDistance(g0$1, g1$1);
  35241. dist$1.setDensifyFraction(densifyFrac);
  35242. return dist$1.distance()
  35243. }
  35244. };
  35245. staticAccessors$39.MaxPointDistanceFilter.get = function () { return MaxPointDistanceFilter$1 };
  35246. staticAccessors$39.MaxDensifiedByFractionDistanceFilter.get = function () { return MaxDensifiedByFractionDistanceFilter };
  35247. Object.defineProperties( DiscreteHausdorffDistance, staticAccessors$39 );
  35248. var MaxPointDistanceFilter$1 = function MaxPointDistanceFilter () {
  35249. this._maxPtDist = new PointPairDistance$2();
  35250. this._minPtDist = new PointPairDistance$2();
  35251. this._euclideanDist = new DistanceToPoint();
  35252. this._geom = null;
  35253. var geom = arguments[0];
  35254. this._geom = geom;
  35255. };
  35256. MaxPointDistanceFilter$1.prototype.filter = function filter (pt) {
  35257. this._minPtDist.initialize();
  35258. DistanceToPoint.computeDistance(this._geom, pt, this._minPtDist);
  35259. this._maxPtDist.setMaximum(this._minPtDist);
  35260. };
  35261. MaxPointDistanceFilter$1.prototype.getMaxPointDistance = function getMaxPointDistance () {
  35262. return this._maxPtDist
  35263. };
  35264. MaxPointDistanceFilter$1.prototype.interfaces_ = function interfaces_ () {
  35265. return [CoordinateFilter]
  35266. };
  35267. MaxPointDistanceFilter$1.prototype.getClass = function getClass () {
  35268. return MaxPointDistanceFilter$1
  35269. };
  35270. var MaxDensifiedByFractionDistanceFilter = function MaxDensifiedByFractionDistanceFilter () {
  35271. this._maxPtDist = new PointPairDistance$2();
  35272. this._minPtDist = new PointPairDistance$2();
  35273. this._geom = null;
  35274. this._numSubSegs = 0;
  35275. var geom = arguments[0];
  35276. var fraction = arguments[1];
  35277. this._geom = geom;
  35278. this._numSubSegs = Math.trunc(Math.round(1.0 / fraction));
  35279. };
  35280. MaxDensifiedByFractionDistanceFilter.prototype.filter = function filter (seq, index) {
  35281. var this$1 = this;
  35282. if (index === 0) { return null }
  35283. var p0 = seq.getCoordinate(index - 1);
  35284. var p1 = seq.getCoordinate(index);
  35285. var delx = (p1.x - p0.x) / this._numSubSegs;
  35286. var dely = (p1.y - p0.y) / this._numSubSegs;
  35287. for (var i = 0; i < this._numSubSegs; i++) {
  35288. var x = p0.x + i * delx;
  35289. var y = p0.y + i * dely;
  35290. var pt = new Coordinate(x, y);
  35291. this$1._minPtDist.initialize();
  35292. DistanceToPoint.computeDistance(this$1._geom, pt, this$1._minPtDist);
  35293. this$1._maxPtDist.setMaximum(this$1._minPtDist);
  35294. }
  35295. };
  35296. MaxDensifiedByFractionDistanceFilter.prototype.isDone = function isDone () {
  35297. return false
  35298. };
  35299. MaxDensifiedByFractionDistanceFilter.prototype.isGeometryChanged = function isGeometryChanged () {
  35300. return false
  35301. };
  35302. MaxDensifiedByFractionDistanceFilter.prototype.getMaxPointDistance = function getMaxPointDistance () {
  35303. return this._maxPtDist
  35304. };
  35305. MaxDensifiedByFractionDistanceFilter.prototype.interfaces_ = function interfaces_ () {
  35306. return [CoordinateSequenceFilter]
  35307. };
  35308. MaxDensifiedByFractionDistanceFilter.prototype.getClass = function getClass () {
  35309. return MaxDensifiedByFractionDistanceFilter
  35310. };
  35311. var BufferDistanceValidator = function BufferDistanceValidator (input, bufDistance, result) {
  35312. this._minValidDistance = null;
  35313. this._maxValidDistance = null;
  35314. this._minDistanceFound = null;
  35315. this._maxDistanceFound = null;
  35316. this._isValid = true;
  35317. this._errMsg = null;
  35318. this._errorLocation = null;
  35319. this._errorIndicator = null;
  35320. this._input = input || null;
  35321. this._bufDistance = bufDistance || null;
  35322. this._result = result || null;
  35323. };
  35324. var staticAccessors$37 = { VERBOSE: { configurable: true },MAX_DISTANCE_DIFF_FRAC: { configurable: true } };
  35325. BufferDistanceValidator.prototype.checkMaximumDistance = function checkMaximumDistance (input, bufCurve, maxDist) {
  35326. var haus = new DiscreteHausdorffDistance(bufCurve, input);
  35327. haus.setDensifyFraction(0.25);
  35328. this._maxDistanceFound = haus.orientedDistance();
  35329. if (this._maxDistanceFound > maxDist) {
  35330. this._isValid = false;
  35331. var pts = haus.getCoordinates();
  35332. this._errorLocation = pts[1];
  35333. this._errorIndicator = input.getFactory().createLineString(pts);
  35334. this._errMsg = 'Distance between buffer curve and input is too large (' + this._maxDistanceFound + ' at ' + WKTWriter.toLineString(pts[0], pts[1]) + ')';
  35335. }
  35336. };
  35337. BufferDistanceValidator.prototype.isValid = function isValid () {
  35338. var posDistance = Math.abs(this._bufDistance);
  35339. var distDelta = BufferDistanceValidator.MAX_DISTANCE_DIFF_FRAC * posDistance;
  35340. this._minValidDistance = posDistance - distDelta;
  35341. this._maxValidDistance = posDistance + distDelta;
  35342. if (this._input.isEmpty() || this._result.isEmpty()) { return true }
  35343. if (this._bufDistance > 0.0) {
  35344. this.checkPositiveValid();
  35345. } else {
  35346. this.checkNegativeValid();
  35347. }
  35348. if (BufferDistanceValidator.VERBOSE) {
  35349. System.out.println('Min Dist= ' + this._minDistanceFound + ' err= ' + (1.0 - this._minDistanceFound / this._bufDistance) + ' Max Dist= ' + this._maxDistanceFound + ' err= ' + (this._maxDistanceFound / this._bufDistance - 1.0));
  35350. }
  35351. return this._isValid
  35352. };
  35353. BufferDistanceValidator.prototype.checkNegativeValid = function checkNegativeValid () {
  35354. if (!(this._input instanceof Polygon || this._input instanceof MultiPolygon || this._input instanceof GeometryCollection)) {
  35355. return null
  35356. }
  35357. var inputCurve = this.getPolygonLines(this._input);
  35358. this.checkMinimumDistance(inputCurve, this._result, this._minValidDistance);
  35359. if (!this._isValid) { return null }
  35360. this.checkMaximumDistance(inputCurve, this._result, this._maxValidDistance);
  35361. };
  35362. BufferDistanceValidator.prototype.getErrorIndicator = function getErrorIndicator () {
  35363. return this._errorIndicator
  35364. };
  35365. BufferDistanceValidator.prototype.checkMinimumDistance = function checkMinimumDistance (g1, g2, minDist) {
  35366. var distOp = new DistanceOp(g1, g2, minDist);
  35367. this._minDistanceFound = distOp.distance();
  35368. if (this._minDistanceFound < minDist) {
  35369. this._isValid = false;
  35370. var pts = distOp.nearestPoints();
  35371. this._errorLocation = distOp.nearestPoints()[1];
  35372. this._errorIndicator = g1.getFactory().createLineString(pts);
  35373. this._errMsg = 'Distance between buffer curve and input is too small (' + this._minDistanceFound + ' at ' + WKTWriter.toLineString(pts[0], pts[1]) + ' )';
  35374. }
  35375. };
  35376. BufferDistanceValidator.prototype.checkPositiveValid = function checkPositiveValid () {
  35377. var bufCurve = this._result.getBoundary();
  35378. this.checkMinimumDistance(this._input, bufCurve, this._minValidDistance);
  35379. if (!this._isValid) { return null }
  35380. this.checkMaximumDistance(this._input, bufCurve, this._maxValidDistance);
  35381. };
  35382. BufferDistanceValidator.prototype.getErrorLocation = function getErrorLocation () {
  35383. return this._errorLocation
  35384. };
  35385. BufferDistanceValidator.prototype.getPolygonLines = function getPolygonLines (g) {
  35386. var lines = new ArrayList();
  35387. var lineExtracter = new LinearComponentExtracter(lines);
  35388. var polys = PolygonExtracter.getPolygons(g);
  35389. for (var i = polys.iterator(); i.hasNext();) {
  35390. var poly = i.next();
  35391. poly.apply(lineExtracter);
  35392. }
  35393. return g.getFactory().buildGeometry(lines)
  35394. };
  35395. BufferDistanceValidator.prototype.getErrorMessage = function getErrorMessage () {
  35396. return this._errMsg
  35397. };
  35398. BufferDistanceValidator.prototype.interfaces_ = function interfaces_ () {
  35399. return []
  35400. };
  35401. BufferDistanceValidator.prototype.getClass = function getClass () {
  35402. return BufferDistanceValidator
  35403. };
  35404. staticAccessors$37.VERBOSE.get = function () { return false };
  35405. staticAccessors$37.MAX_DISTANCE_DIFF_FRAC.get = function () { return 0.012 };
  35406. Object.defineProperties( BufferDistanceValidator, staticAccessors$37 );
  35407. var BufferResultValidator = function BufferResultValidator (input, distance, result) {
  35408. this._isValid = true;
  35409. this._errorMsg = null;
  35410. this._errorLocation = null;
  35411. this._errorIndicator = null;
  35412. this._input = input || null;
  35413. this._distance = distance || null;
  35414. this._result = result || null;
  35415. };
  35416. var staticAccessors$40 = { VERBOSE: { configurable: true },MAX_ENV_DIFF_FRAC: { configurable: true } };
  35417. BufferResultValidator.prototype.isValid = function isValid () {
  35418. this.checkPolygonal();
  35419. if (!this._isValid) { return this._isValid }
  35420. this.checkExpectedEmpty();
  35421. if (!this._isValid) { return this._isValid }
  35422. this.checkEnvelope();
  35423. if (!this._isValid) { return this._isValid }
  35424. this.checkArea();
  35425. if (!this._isValid) { return this._isValid }
  35426. this.checkDistance();
  35427. return this._isValid
  35428. };
  35429. BufferResultValidator.prototype.checkEnvelope = function checkEnvelope () {
  35430. if (this._distance < 0.0) { return null }
  35431. var padding = this._distance * BufferResultValidator.MAX_ENV_DIFF_FRAC;
  35432. if (padding === 0.0) { padding = 0.001; }
  35433. var expectedEnv = new Envelope(this._input.getEnvelopeInternal());
  35434. expectedEnv.expandBy(this._distance);
  35435. var bufEnv = new Envelope(this._result.getEnvelopeInternal());
  35436. bufEnv.expandBy(padding);
  35437. if (!bufEnv.contains(expectedEnv)) {
  35438. this._isValid = false;
  35439. this._errorMsg = 'Buffer envelope is incorrect';
  35440. this._errorIndicator = this._input.getFactory().toGeometry(bufEnv);
  35441. }
  35442. this.report('Envelope');
  35443. };
  35444. BufferResultValidator.prototype.checkDistance = function checkDistance () {
  35445. var distValid = new BufferDistanceValidator(this._input, this._distance, this._result);
  35446. if (!distValid.isValid()) {
  35447. this._isValid = false;
  35448. this._errorMsg = distValid.getErrorMessage();
  35449. this._errorLocation = distValid.getErrorLocation();
  35450. this._errorIndicator = distValid.getErrorIndicator();
  35451. }
  35452. this.report('Distance');
  35453. };
  35454. BufferResultValidator.prototype.checkArea = function checkArea () {
  35455. var inputArea = this._input.getArea();
  35456. var resultArea = this._result.getArea();
  35457. if (this._distance > 0.0 && inputArea > resultArea) {
  35458. this._isValid = false;
  35459. this._errorMsg = 'Area of positive buffer is smaller than input';
  35460. this._errorIndicator = this._result;
  35461. }
  35462. if (this._distance < 0.0 && inputArea < resultArea) {
  35463. this._isValid = false;
  35464. this._errorMsg = 'Area of negative buffer is larger than input';
  35465. this._errorIndicator = this._result;
  35466. }
  35467. this.report('Area');
  35468. };
  35469. BufferResultValidator.prototype.checkPolygonal = function checkPolygonal () {
  35470. if (!(this._result instanceof Polygon || this._result instanceof MultiPolygon)) { this._isValid = false; }
  35471. this._errorMsg = 'Result is not polygonal';
  35472. this._errorIndicator = this._result;
  35473. this.report('Polygonal');
  35474. };
  35475. BufferResultValidator.prototype.getErrorIndicator = function getErrorIndicator () {
  35476. return this._errorIndicator
  35477. };
  35478. BufferResultValidator.prototype.getErrorLocation = function getErrorLocation () {
  35479. return this._errorLocation
  35480. };
  35481. BufferResultValidator.prototype.checkExpectedEmpty = function checkExpectedEmpty () {
  35482. if (this._input.getDimension() >= 2) { return null }
  35483. if (this._distance > 0.0) { return null }
  35484. if (!this._result.isEmpty()) {
  35485. this._isValid = false;
  35486. this._errorMsg = 'Result is non-empty';
  35487. this._errorIndicator = this._result;
  35488. }
  35489. this.report('ExpectedEmpty');
  35490. };
  35491. BufferResultValidator.prototype.report = function report (checkName) {
  35492. if (!BufferResultValidator.VERBOSE) { return null }
  35493. System.out.println('Check ' + checkName + ': ' + (this._isValid ? 'passed' : 'FAILED'));
  35494. };
  35495. BufferResultValidator.prototype.getErrorMessage = function getErrorMessage () {
  35496. return this._errorMsg
  35497. };
  35498. BufferResultValidator.prototype.interfaces_ = function interfaces_ () {
  35499. return []
  35500. };
  35501. BufferResultValidator.prototype.getClass = function getClass () {
  35502. return BufferResultValidator
  35503. };
  35504. BufferResultValidator.isValidMsg = function isValidMsg (g, distance, result) {
  35505. var validator = new BufferResultValidator(g, distance, result);
  35506. if (!validator.isValid()) { return validator.getErrorMessage() }
  35507. return null
  35508. };
  35509. BufferResultValidator.isValid = function isValid (g, distance, result) {
  35510. var validator = new BufferResultValidator(g, distance, result);
  35511. if (validator.isValid()) { return true }
  35512. return false
  35513. };
  35514. staticAccessors$40.VERBOSE.get = function () { return false };
  35515. staticAccessors$40.MAX_ENV_DIFF_FRAC.get = function () { return 0.012 };
  35516. Object.defineProperties( BufferResultValidator, staticAccessors$40 );
  35517. // operation.buffer
  35518. var BasicSegmentString = function BasicSegmentString () {
  35519. this._pts = null;
  35520. this._data = null;
  35521. var pts = arguments[0];
  35522. var data = arguments[1];
  35523. this._pts = pts;
  35524. this._data = data;
  35525. };
  35526. BasicSegmentString.prototype.getCoordinates = function getCoordinates () {
  35527. return this._pts
  35528. };
  35529. BasicSegmentString.prototype.size = function size () {
  35530. return this._pts.length
  35531. };
  35532. BasicSegmentString.prototype.getCoordinate = function getCoordinate (i) {
  35533. return this._pts[i]
  35534. };
  35535. BasicSegmentString.prototype.isClosed = function isClosed () {
  35536. return this._pts[0].equals(this._pts[this._pts.length - 1])
  35537. };
  35538. BasicSegmentString.prototype.getSegmentOctant = function getSegmentOctant (index) {
  35539. if (index === this._pts.length - 1) { return -1 }
  35540. return Octant.octant(this.getCoordinate(index), this.getCoordinate(index + 1))
  35541. };
  35542. BasicSegmentString.prototype.setData = function setData (data) {
  35543. this._data = data;
  35544. };
  35545. BasicSegmentString.prototype.getData = function getData () {
  35546. return this._data
  35547. };
  35548. BasicSegmentString.prototype.toString = function toString () {
  35549. return WKTWriter.toLineString(new CoordinateArraySequence(this._pts))
  35550. };
  35551. BasicSegmentString.prototype.interfaces_ = function interfaces_ () {
  35552. return [SegmentString]
  35553. };
  35554. BasicSegmentString.prototype.getClass = function getClass () {
  35555. return BasicSegmentString
  35556. };
  35557. var InteriorIntersectionFinder = function InteriorIntersectionFinder () {
  35558. this._findAllIntersections = false;
  35559. this._isCheckEndSegmentsOnly = false;
  35560. this._li = null;
  35561. this._interiorIntersection = null;
  35562. this._intSegments = null;
  35563. this._intersections = new ArrayList();
  35564. this._intersectionCount = 0;
  35565. this._keepIntersections = true;
  35566. var li = arguments[0];
  35567. this._li = li;
  35568. this._interiorIntersection = null;
  35569. };
  35570. InteriorIntersectionFinder.prototype.getInteriorIntersection = function getInteriorIntersection () {
  35571. return this._interiorIntersection
  35572. };
  35573. InteriorIntersectionFinder.prototype.setCheckEndSegmentsOnly = function setCheckEndSegmentsOnly (isCheckEndSegmentsOnly) {
  35574. this._isCheckEndSegmentsOnly = isCheckEndSegmentsOnly;
  35575. };
  35576. InteriorIntersectionFinder.prototype.getIntersectionSegments = function getIntersectionSegments () {
  35577. return this._intSegments
  35578. };
  35579. InteriorIntersectionFinder.prototype.count = function count () {
  35580. return this._intersectionCount
  35581. };
  35582. InteriorIntersectionFinder.prototype.getIntersections = function getIntersections () {
  35583. return this._intersections
  35584. };
  35585. InteriorIntersectionFinder.prototype.setFindAllIntersections = function setFindAllIntersections (findAllIntersections) {
  35586. this._findAllIntersections = findAllIntersections;
  35587. };
  35588. InteriorIntersectionFinder.prototype.setKeepIntersections = function setKeepIntersections (keepIntersections) {
  35589. this._keepIntersections = keepIntersections;
  35590. };
  35591. InteriorIntersectionFinder.prototype.processIntersections = function processIntersections (e0, segIndex0, e1, segIndex1) {
  35592. if (!this._findAllIntersections && this.hasIntersection()) { return null }
  35593. if (e0 === e1 && segIndex0 === segIndex1) { return null }
  35594. if (this._isCheckEndSegmentsOnly) {
  35595. var isEndSegPresent = this.isEndSegment(e0, segIndex0) || this.isEndSegment(e1, segIndex1);
  35596. if (!isEndSegPresent) { return null }
  35597. }
  35598. var p00 = e0.getCoordinates()[segIndex0];
  35599. var p01 = e0.getCoordinates()[segIndex0 + 1];
  35600. var p10 = e1.getCoordinates()[segIndex1];
  35601. var p11 = e1.getCoordinates()[segIndex1 + 1];
  35602. this._li.computeIntersection(p00, p01, p10, p11);
  35603. if (this._li.hasIntersection()) {
  35604. if (this._li.isInteriorIntersection()) {
  35605. this._intSegments = new Array(4).fill(null);
  35606. this._intSegments[0] = p00;
  35607. this._intSegments[1] = p01;
  35608. this._intSegments[2] = p10;
  35609. this._intSegments[3] = p11;
  35610. this._interiorIntersection = this._li.getIntersection(0);
  35611. if (this._keepIntersections) { this._intersections.add(this._interiorIntersection); }
  35612. this._intersectionCount++;
  35613. }
  35614. }
  35615. };
  35616. InteriorIntersectionFinder.prototype.isEndSegment = function isEndSegment (segStr, index) {
  35617. if (index === 0) { return true }
  35618. if (index >= segStr.size() - 2) { return true }
  35619. return false
  35620. };
  35621. InteriorIntersectionFinder.prototype.hasIntersection = function hasIntersection () {
  35622. return this._interiorIntersection !== null
  35623. };
  35624. InteriorIntersectionFinder.prototype.isDone = function isDone () {
  35625. if (this._findAllIntersections) { return false }
  35626. return this._interiorIntersection !== null
  35627. };
  35628. InteriorIntersectionFinder.prototype.interfaces_ = function interfaces_ () {
  35629. return [SegmentIntersector]
  35630. };
  35631. InteriorIntersectionFinder.prototype.getClass = function getClass () {
  35632. return InteriorIntersectionFinder
  35633. };
  35634. InteriorIntersectionFinder.createAllIntersectionsFinder = function createAllIntersectionsFinder (li) {
  35635. var finder = new InteriorIntersectionFinder(li);
  35636. finder.setFindAllIntersections(true);
  35637. return finder
  35638. };
  35639. InteriorIntersectionFinder.createAnyIntersectionFinder = function createAnyIntersectionFinder (li) {
  35640. return new InteriorIntersectionFinder(li)
  35641. };
  35642. InteriorIntersectionFinder.createIntersectionCounter = function createIntersectionCounter (li) {
  35643. var finder = new InteriorIntersectionFinder(li);
  35644. finder.setFindAllIntersections(true);
  35645. finder.setKeepIntersections(false);
  35646. return finder
  35647. };
  35648. var FastNodingValidator = function FastNodingValidator () {
  35649. this._li = new RobustLineIntersector();
  35650. this._segStrings = null;
  35651. this._findAllIntersections = false;
  35652. this._segInt = null;
  35653. this._isValid = true;
  35654. var segStrings = arguments[0];
  35655. this._segStrings = segStrings;
  35656. };
  35657. FastNodingValidator.prototype.execute = function execute () {
  35658. if (this._segInt !== null) { return null }
  35659. this.checkInteriorIntersections();
  35660. };
  35661. FastNodingValidator.prototype.getIntersections = function getIntersections () {
  35662. return this._segInt.getIntersections()
  35663. };
  35664. FastNodingValidator.prototype.isValid = function isValid () {
  35665. this.execute();
  35666. return this._isValid
  35667. };
  35668. FastNodingValidator.prototype.setFindAllIntersections = function setFindAllIntersections (findAllIntersections) {
  35669. this._findAllIntersections = findAllIntersections;
  35670. };
  35671. FastNodingValidator.prototype.checkInteriorIntersections = function checkInteriorIntersections () {
  35672. this._isValid = true;
  35673. this._segInt = new InteriorIntersectionFinder(this._li);
  35674. this._segInt.setFindAllIntersections(this._findAllIntersections);
  35675. var noder = new MCIndexNoder();
  35676. noder.setSegmentIntersector(this._segInt);
  35677. noder.computeNodes(this._segStrings);
  35678. if (this._segInt.hasIntersection()) {
  35679. this._isValid = false;
  35680. return null
  35681. }
  35682. };
  35683. FastNodingValidator.prototype.checkValid = function checkValid () {
  35684. this.execute();
  35685. if (!this._isValid) { throw new TopologyException(this.getErrorMessage(), this._segInt.getInteriorIntersection()) }
  35686. };
  35687. FastNodingValidator.prototype.getErrorMessage = function getErrorMessage () {
  35688. if (this._isValid) { return 'no intersections found' }
  35689. var intSegs = this._segInt.getIntersectionSegments();
  35690. return 'found non-noded intersection between ' + WKTWriter.toLineString(intSegs[0], intSegs[1]) + ' and ' + WKTWriter.toLineString(intSegs[2], intSegs[3])
  35691. };
  35692. FastNodingValidator.prototype.interfaces_ = function interfaces_ () {
  35693. return []
  35694. };
  35695. FastNodingValidator.prototype.getClass = function getClass () {
  35696. return FastNodingValidator
  35697. };
  35698. FastNodingValidator.computeIntersections = function computeIntersections (segStrings) {
  35699. var nv = new FastNodingValidator(segStrings);
  35700. nv.setFindAllIntersections(true);
  35701. nv.isValid();
  35702. return nv.getIntersections()
  35703. };
  35704. var EdgeNodingValidator = function EdgeNodingValidator () {
  35705. this._nv = null;
  35706. var edges = arguments[0];
  35707. this._nv = new FastNodingValidator(EdgeNodingValidator.toSegmentStrings(edges));
  35708. };
  35709. EdgeNodingValidator.prototype.checkValid = function checkValid () {
  35710. this._nv.checkValid();
  35711. };
  35712. EdgeNodingValidator.prototype.interfaces_ = function interfaces_ () {
  35713. return []
  35714. };
  35715. EdgeNodingValidator.prototype.getClass = function getClass () {
  35716. return EdgeNodingValidator
  35717. };
  35718. EdgeNodingValidator.toSegmentStrings = function toSegmentStrings (edges) {
  35719. var segStrings = new ArrayList();
  35720. for (var i = edges.iterator(); i.hasNext();) {
  35721. var e = i.next();
  35722. segStrings.add(new BasicSegmentString(e.getCoordinates(), e));
  35723. }
  35724. return segStrings
  35725. };
  35726. EdgeNodingValidator.checkValid = function checkValid (edges) {
  35727. var validator = new EdgeNodingValidator(edges);
  35728. validator.checkValid();
  35729. };
  35730. var GeometryCollectionMapper = function GeometryCollectionMapper (mapOp) {
  35731. this._mapOp = mapOp;
  35732. };
  35733. GeometryCollectionMapper.prototype.map = function map (gc) {
  35734. var this$1 = this;
  35735. var mapped = new ArrayList();
  35736. for (var i = 0; i < gc.getNumGeometries(); i++) {
  35737. var g = this$1._mapOp.map(gc.getGeometryN(i));
  35738. if (!g.isEmpty()) { mapped.add(g); }
  35739. }
  35740. return gc.getFactory().createGeometryCollection(GeometryFactory.toGeometryArray(mapped))
  35741. };
  35742. GeometryCollectionMapper.prototype.interfaces_ = function interfaces_ () {
  35743. return []
  35744. };
  35745. GeometryCollectionMapper.prototype.getClass = function getClass () {
  35746. return GeometryCollectionMapper
  35747. };
  35748. GeometryCollectionMapper.map = function map (gc, op) {
  35749. var mapper = new GeometryCollectionMapper(op);
  35750. return mapper.map(gc)
  35751. };
  35752. var LineBuilder = function LineBuilder () {
  35753. this._op = null;
  35754. this._geometryFactory = null;
  35755. this._ptLocator = null;
  35756. this._lineEdgesList = new ArrayList();
  35757. this._resultLineList = new ArrayList();
  35758. var op = arguments[0];
  35759. var geometryFactory = arguments[1];
  35760. var ptLocator = arguments[2];
  35761. this._op = op;
  35762. this._geometryFactory = geometryFactory;
  35763. this._ptLocator = ptLocator;
  35764. };
  35765. LineBuilder.prototype.collectLines = function collectLines (opCode) {
  35766. var this$1 = this;
  35767. for (var it = this._op.getGraph().getEdgeEnds().iterator(); it.hasNext();) {
  35768. var de = it.next();
  35769. this$1.collectLineEdge(de, opCode, this$1._lineEdgesList);
  35770. this$1.collectBoundaryTouchEdge(de, opCode, this$1._lineEdgesList);
  35771. }
  35772. };
  35773. LineBuilder.prototype.labelIsolatedLine = function labelIsolatedLine (e, targetIndex) {
  35774. var loc = this._ptLocator.locate(e.getCoordinate(), this._op.getArgGeometry(targetIndex));
  35775. e.getLabel().setLocation(targetIndex, loc);
  35776. };
  35777. LineBuilder.prototype.build = function build (opCode) {
  35778. this.findCoveredLineEdges();
  35779. this.collectLines(opCode);
  35780. this.buildLines(opCode);
  35781. return this._resultLineList
  35782. };
  35783. LineBuilder.prototype.collectLineEdge = function collectLineEdge (de, opCode, edges) {
  35784. var label = de.getLabel();
  35785. var e = de.getEdge();
  35786. if (de.isLineEdge()) {
  35787. if (!de.isVisited() && OverlayOp.isResultOfOp(label, opCode) && !e.isCovered()) {
  35788. edges.add(e);
  35789. de.setVisitedEdge(true);
  35790. }
  35791. }
  35792. };
  35793. LineBuilder.prototype.findCoveredLineEdges = function findCoveredLineEdges () {
  35794. var this$1 = this;
  35795. for (var nodeit = this._op.getGraph().getNodes().iterator(); nodeit.hasNext();) {
  35796. var node = nodeit.next();
  35797. node.getEdges().findCoveredLineEdges();
  35798. }
  35799. for (var it = this._op.getGraph().getEdgeEnds().iterator(); it.hasNext();) {
  35800. var de = it.next();
  35801. var e = de.getEdge();
  35802. if (de.isLineEdge() && !e.isCoveredSet()) {
  35803. var isCovered = this$1._op.isCoveredByA(de.getCoordinate());
  35804. e.setCovered(isCovered);
  35805. }
  35806. }
  35807. };
  35808. LineBuilder.prototype.labelIsolatedLines = function labelIsolatedLines (edgesList) {
  35809. var this$1 = this;
  35810. for (var it = edgesList.iterator(); it.hasNext();) {
  35811. var e = it.next();
  35812. var label = e.getLabel();
  35813. if (e.isIsolated()) {
  35814. if (label.isNull(0)) { this$1.labelIsolatedLine(e, 0); } else { this$1.labelIsolatedLine(e, 1); }
  35815. }
  35816. }
  35817. };
  35818. LineBuilder.prototype.buildLines = function buildLines (opCode) {
  35819. var this$1 = this;
  35820. for (var it = this._lineEdgesList.iterator(); it.hasNext();) {
  35821. var e = it.next();
  35822. // const label = e.getLabel()
  35823. var line = this$1._geometryFactory.createLineString(e.getCoordinates());
  35824. this$1._resultLineList.add(line);
  35825. e.setInResult(true);
  35826. }
  35827. };
  35828. LineBuilder.prototype.collectBoundaryTouchEdge = function collectBoundaryTouchEdge (de, opCode, edges) {
  35829. var label = de.getLabel();
  35830. if (de.isLineEdge()) { return null }
  35831. if (de.isVisited()) { return null }
  35832. if (de.isInteriorAreaEdge()) { return null }
  35833. if (de.getEdge().isInResult()) { return null }
  35834. Assert.isTrue(!(de.isInResult() || de.getSym().isInResult()) || !de.getEdge().isInResult());
  35835. if (OverlayOp.isResultOfOp(label, opCode) && opCode === OverlayOp.INTERSECTION) {
  35836. edges.add(de.getEdge());
  35837. de.setVisitedEdge(true);
  35838. }
  35839. };
  35840. LineBuilder.prototype.interfaces_ = function interfaces_ () {
  35841. return []
  35842. };
  35843. LineBuilder.prototype.getClass = function getClass () {
  35844. return LineBuilder
  35845. };
  35846. var PointBuilder = function PointBuilder () {
  35847. this._op = null;
  35848. this._geometryFactory = null;
  35849. this._resultPointList = new ArrayList();
  35850. var op = arguments[0];
  35851. var geometryFactory = arguments[1];
  35852. // const ptLocator = arguments[2]
  35853. this._op = op;
  35854. this._geometryFactory = geometryFactory;
  35855. };
  35856. PointBuilder.prototype.filterCoveredNodeToPoint = function filterCoveredNodeToPoint (n) {
  35857. var coord = n.getCoordinate();
  35858. if (!this._op.isCoveredByLA(coord)) {
  35859. var pt = this._geometryFactory.createPoint(coord);
  35860. this._resultPointList.add(pt);
  35861. }
  35862. };
  35863. PointBuilder.prototype.extractNonCoveredResultNodes = function extractNonCoveredResultNodes (opCode) {
  35864. var this$1 = this;
  35865. for (var nodeit = this._op.getGraph().getNodes().iterator(); nodeit.hasNext();) {
  35866. var n = nodeit.next();
  35867. if (n.isInResult()) { continue }
  35868. if (n.isIncidentEdgeInResult()) { continue }
  35869. if (n.getEdges().getDegree() === 0 || opCode === OverlayOp.INTERSECTION) {
  35870. var label = n.getLabel();
  35871. if (OverlayOp.isResultOfOp(label, opCode)) {
  35872. this$1.filterCoveredNodeToPoint(n);
  35873. }
  35874. }
  35875. }
  35876. };
  35877. PointBuilder.prototype.build = function build (opCode) {
  35878. this.extractNonCoveredResultNodes(opCode);
  35879. return this._resultPointList
  35880. };
  35881. PointBuilder.prototype.interfaces_ = function interfaces_ () {
  35882. return []
  35883. };
  35884. PointBuilder.prototype.getClass = function getClass () {
  35885. return PointBuilder
  35886. };
  35887. var GeometryTransformer = function GeometryTransformer () {
  35888. this._inputGeom = null;
  35889. this._factory = null;
  35890. this._pruneEmptyGeometry = true;
  35891. this._preserveGeometryCollectionType = true;
  35892. this._preserveCollections = false;
  35893. this._preserveType = false;
  35894. };
  35895. GeometryTransformer.prototype.transformPoint = function transformPoint (geom, parent) {
  35896. return this._factory.createPoint(this.transformCoordinates(geom.getCoordinateSequence(), geom))
  35897. };
  35898. GeometryTransformer.prototype.transformPolygon = function transformPolygon (geom, parent) {
  35899. var this$1 = this;
  35900. var isAllValidLinearRings = true;
  35901. var shell = this.transformLinearRing(geom.getExteriorRing(), geom);
  35902. if (shell === null || !(shell instanceof LinearRing) || shell.isEmpty()) { isAllValidLinearRings = false; }
  35903. var holes = new ArrayList();
  35904. for (var i = 0; i < geom.getNumInteriorRing(); i++) {
  35905. var hole = this$1.transformLinearRing(geom.getInteriorRingN(i), geom);
  35906. if (hole === null || hole.isEmpty()) {
  35907. continue
  35908. }
  35909. if (!(hole instanceof LinearRing)) { isAllValidLinearRings = false; }
  35910. holes.add(hole);
  35911. }
  35912. if (isAllValidLinearRings) { return this._factory.createPolygon(shell, holes.toArray([])); } else {
  35913. var components = new ArrayList();
  35914. if (shell !== null) { components.add(shell); }
  35915. components.addAll(holes);
  35916. return this._factory.buildGeometry(components)
  35917. }
  35918. };
  35919. GeometryTransformer.prototype.createCoordinateSequence = function createCoordinateSequence (coords) {
  35920. return this._factory.getCoordinateSequenceFactory().create(coords)
  35921. };
  35922. GeometryTransformer.prototype.getInputGeometry = function getInputGeometry () {
  35923. return this._inputGeom
  35924. };
  35925. GeometryTransformer.prototype.transformMultiLineString = function transformMultiLineString (geom, parent) {
  35926. var this$1 = this;
  35927. var transGeomList = new ArrayList();
  35928. for (var i = 0; i < geom.getNumGeometries(); i++) {
  35929. var transformGeom = this$1.transformLineString(geom.getGeometryN(i), geom);
  35930. if (transformGeom === null) { continue }
  35931. if (transformGeom.isEmpty()) { continue }
  35932. transGeomList.add(transformGeom);
  35933. }
  35934. return this._factory.buildGeometry(transGeomList)
  35935. };
  35936. GeometryTransformer.prototype.transformCoordinates = function transformCoordinates (coords, parent) {
  35937. return this.copy(coords)
  35938. };
  35939. GeometryTransformer.prototype.transformLineString = function transformLineString (geom, parent) {
  35940. return this._factory.createLineString(this.transformCoordinates(geom.getCoordinateSequence(), geom))
  35941. };
  35942. GeometryTransformer.prototype.transformMultiPoint = function transformMultiPoint (geom, parent) {
  35943. var this$1 = this;
  35944. var transGeomList = new ArrayList();
  35945. for (var i = 0; i < geom.getNumGeometries(); i++) {
  35946. var transformGeom = this$1.transformPoint(geom.getGeometryN(i), geom);
  35947. if (transformGeom === null) { continue }
  35948. if (transformGeom.isEmpty()) { continue }
  35949. transGeomList.add(transformGeom);
  35950. }
  35951. return this._factory.buildGeometry(transGeomList)
  35952. };
  35953. GeometryTransformer.prototype.transformMultiPolygon = function transformMultiPolygon (geom, parent) {
  35954. var this$1 = this;
  35955. var transGeomList = new ArrayList();
  35956. for (var i = 0; i < geom.getNumGeometries(); i++) {
  35957. var transformGeom = this$1.transformPolygon(geom.getGeometryN(i), geom);
  35958. if (transformGeom === null) { continue }
  35959. if (transformGeom.isEmpty()) { continue }
  35960. transGeomList.add(transformGeom);
  35961. }
  35962. return this._factory.buildGeometry(transGeomList)
  35963. };
  35964. GeometryTransformer.prototype.copy = function copy (seq) {
  35965. return seq.copy()
  35966. };
  35967. GeometryTransformer.prototype.transformGeometryCollection = function transformGeometryCollection (geom, parent) {
  35968. var this$1 = this;
  35969. var transGeomList = new ArrayList();
  35970. for (var i = 0; i < geom.getNumGeometries(); i++) {
  35971. var transformGeom = this$1.transform(geom.getGeometryN(i));
  35972. if (transformGeom === null) { continue }
  35973. if (this$1._pruneEmptyGeometry && transformGeom.isEmpty()) { continue }
  35974. transGeomList.add(transformGeom);
  35975. }
  35976. if (this._preserveGeometryCollectionType) { return this._factory.createGeometryCollection(GeometryFactory.toGeometryArray(transGeomList)) }
  35977. return this._factory.buildGeometry(transGeomList)
  35978. };
  35979. GeometryTransformer.prototype.transform = function transform (inputGeom) {
  35980. this._inputGeom = inputGeom;
  35981. this._factory = inputGeom.getFactory();
  35982. if (inputGeom instanceof Point) { return this.transformPoint(inputGeom, null) }
  35983. if (inputGeom instanceof MultiPoint) { return this.transformMultiPoint(inputGeom, null) }
  35984. if (inputGeom instanceof LinearRing) { return this.transformLinearRing(inputGeom, null) }
  35985. if (inputGeom instanceof LineString$1) { return this.transformLineString(inputGeom, null) }
  35986. if (inputGeom instanceof MultiLineString) { return this.transformMultiLineString(inputGeom, null) }
  35987. if (inputGeom instanceof Polygon) { return this.transformPolygon(inputGeom, null) }
  35988. if (inputGeom instanceof MultiPolygon) { return this.transformMultiPolygon(inputGeom, null) }
  35989. if (inputGeom instanceof GeometryCollection) { return this.transformGeometryCollection(inputGeom, null) }
  35990. throw new IllegalArgumentException('Unknown Geometry subtype: ' + inputGeom.getClass().getName())
  35991. };
  35992. GeometryTransformer.prototype.transformLinearRing = function transformLinearRing (geom, parent) {
  35993. var seq = this.transformCoordinates(geom.getCoordinateSequence(), geom);
  35994. if (seq === null) { return this._factory.createLinearRing(null) }
  35995. var seqSize = seq.size();
  35996. if (seqSize > 0 && seqSize < 4 && !this._preserveType) { return this._factory.createLineString(seq) }
  35997. return this._factory.createLinearRing(seq)
  35998. };
  35999. GeometryTransformer.prototype.interfaces_ = function interfaces_ () {
  36000. return []
  36001. };
  36002. GeometryTransformer.prototype.getClass = function getClass () {
  36003. return GeometryTransformer
  36004. };
  36005. var LineStringSnapper = function LineStringSnapper () {
  36006. this._snapTolerance = 0.0;
  36007. this._srcPts = null;
  36008. this._seg = new LineSegment();
  36009. this._allowSnappingToSourceVertices = false;
  36010. this._isClosed = false;
  36011. if (arguments[0] instanceof LineString$1 && typeof arguments[1] === 'number') {
  36012. var srcLine = arguments[0];
  36013. var snapTolerance = arguments[1];
  36014. LineStringSnapper.call(this, srcLine.getCoordinates(), snapTolerance);
  36015. } else if (arguments[0] instanceof Array && typeof arguments[1] === 'number') {
  36016. var srcPts = arguments[0];
  36017. var snapTolerance$1 = arguments[1];
  36018. this._srcPts = srcPts;
  36019. this._isClosed = LineStringSnapper.isClosed(srcPts);
  36020. this._snapTolerance = snapTolerance$1;
  36021. }
  36022. };
  36023. LineStringSnapper.prototype.snapVertices = function snapVertices (srcCoords, snapPts) {
  36024. var this$1 = this;
  36025. var end = this._isClosed ? srcCoords.size() - 1 : srcCoords.size();
  36026. for (var i = 0; i < end; i++) {
  36027. var srcPt = srcCoords.get(i);
  36028. var snapVert = this$1.findSnapForVertex(srcPt, snapPts);
  36029. if (snapVert !== null) {
  36030. srcCoords.set(i, new Coordinate(snapVert));
  36031. if (i === 0 && this$1._isClosed) { srcCoords.set(srcCoords.size() - 1, new Coordinate(snapVert)); }
  36032. }
  36033. }
  36034. };
  36035. LineStringSnapper.prototype.findSnapForVertex = function findSnapForVertex (pt, snapPts) {
  36036. var this$1 = this;
  36037. for (var i = 0; i < snapPts.length; i++) {
  36038. if (pt.equals2D(snapPts[i])) { return null }
  36039. if (pt.distance(snapPts[i]) < this$1._snapTolerance) { return snapPts[i] }
  36040. }
  36041. return null
  36042. };
  36043. LineStringSnapper.prototype.snapTo = function snapTo (snapPts) {
  36044. var coordList = new CoordinateList(this._srcPts);
  36045. this.snapVertices(coordList, snapPts);
  36046. this.snapSegments(coordList, snapPts);
  36047. var newPts = coordList.toCoordinateArray();
  36048. return newPts
  36049. };
  36050. LineStringSnapper.prototype.snapSegments = function snapSegments (srcCoords, snapPts) {
  36051. var this$1 = this;
  36052. if (snapPts.length === 0) { return null }
  36053. var distinctPtCount = snapPts.length;
  36054. if (snapPts[0].equals2D(snapPts[snapPts.length - 1])) { distinctPtCount = snapPts.length - 1; }
  36055. for (var i = 0; i < distinctPtCount; i++) {
  36056. var snapPt = snapPts[i];
  36057. var index = this$1.findSegmentIndexToSnap(snapPt, srcCoords);
  36058. if (index >= 0) {
  36059. srcCoords.add(index + 1, new Coordinate(snapPt), false);
  36060. }
  36061. }
  36062. };
  36063. LineStringSnapper.prototype.findSegmentIndexToSnap = function findSegmentIndexToSnap (snapPt, srcCoords) {
  36064. var this$1 = this;
  36065. var minDist = Double.MAX_VALUE;
  36066. var snapIndex = -1;
  36067. for (var i = 0; i < srcCoords.size() - 1; i++) {
  36068. this$1._seg.p0 = srcCoords.get(i);
  36069. this$1._seg.p1 = srcCoords.get(i + 1);
  36070. if (this$1._seg.p0.equals2D(snapPt) || this$1._seg.p1.equals2D(snapPt)) {
  36071. if (this$1._allowSnappingToSourceVertices) { continue; } else { return -1 }
  36072. }
  36073. var dist = this$1._seg.distance(snapPt);
  36074. if (dist < this$1._snapTolerance && dist < minDist) {
  36075. minDist = dist;
  36076. snapIndex = i;
  36077. }
  36078. }
  36079. return snapIndex
  36080. };
  36081. LineStringSnapper.prototype.setAllowSnappingToSourceVertices = function setAllowSnappingToSourceVertices (allowSnappingToSourceVertices) {
  36082. this._allowSnappingToSourceVertices = allowSnappingToSourceVertices;
  36083. };
  36084. LineStringSnapper.prototype.interfaces_ = function interfaces_ () {
  36085. return []
  36086. };
  36087. LineStringSnapper.prototype.getClass = function getClass () {
  36088. return LineStringSnapper
  36089. };
  36090. LineStringSnapper.isClosed = function isClosed (pts) {
  36091. if (pts.length <= 1) { return false }
  36092. return pts[0].equals2D(pts[pts.length - 1])
  36093. };
  36094. var GeometrySnapper = function GeometrySnapper (srcGeom) {
  36095. this._srcGeom = srcGeom || null;
  36096. };
  36097. var staticAccessors$41 = { SNAP_PRECISION_FACTOR: { configurable: true } };
  36098. GeometrySnapper.prototype.snapTo = function snapTo (snapGeom, snapTolerance) {
  36099. var snapPts = this.extractTargetCoordinates(snapGeom);
  36100. var snapTrans = new SnapTransformer(snapTolerance, snapPts);
  36101. return snapTrans.transform(this._srcGeom)
  36102. };
  36103. GeometrySnapper.prototype.snapToSelf = function snapToSelf (snapTolerance, cleanResult) {
  36104. var snapPts = this.extractTargetCoordinates(this._srcGeom);
  36105. var snapTrans = new SnapTransformer(snapTolerance, snapPts, true);
  36106. var snappedGeom = snapTrans.transform(this._srcGeom);
  36107. var result = snappedGeom;
  36108. if (cleanResult && hasInterface(result, Polygonal)) {
  36109. result = snappedGeom.buffer(0);
  36110. }
  36111. return result
  36112. };
  36113. GeometrySnapper.prototype.computeSnapTolerance = function computeSnapTolerance (ringPts) {
  36114. var minSegLen = this.computeMinimumSegmentLength(ringPts);
  36115. var snapTol = minSegLen / 10;
  36116. return snapTol
  36117. };
  36118. GeometrySnapper.prototype.extractTargetCoordinates = function extractTargetCoordinates (g) {
  36119. var ptSet = new TreeSet();
  36120. var pts = g.getCoordinates();
  36121. for (var i = 0; i < pts.length; i++) {
  36122. ptSet.add(pts[i]);
  36123. }
  36124. return ptSet.toArray(new Array(0).fill(null))
  36125. };
  36126. GeometrySnapper.prototype.computeMinimumSegmentLength = function computeMinimumSegmentLength (pts) {
  36127. var minSegLen = Double.MAX_VALUE;
  36128. for (var i = 0; i < pts.length - 1; i++) {
  36129. var segLen = pts[i].distance(pts[i + 1]);
  36130. if (segLen < minSegLen) { minSegLen = segLen; }
  36131. }
  36132. return minSegLen
  36133. };
  36134. GeometrySnapper.prototype.interfaces_ = function interfaces_ () {
  36135. return []
  36136. };
  36137. GeometrySnapper.prototype.getClass = function getClass () {
  36138. return GeometrySnapper
  36139. };
  36140. GeometrySnapper.snap = function snap (g0, g1, snapTolerance) {
  36141. var snapGeom = new Array(2).fill(null);
  36142. var snapper0 = new GeometrySnapper(g0);
  36143. snapGeom[0] = snapper0.snapTo(g1, snapTolerance);
  36144. var snapper1 = new GeometrySnapper(g1);
  36145. snapGeom[1] = snapper1.snapTo(snapGeom[0], snapTolerance);
  36146. return snapGeom
  36147. };
  36148. GeometrySnapper.computeOverlaySnapTolerance = function computeOverlaySnapTolerance () {
  36149. if (arguments.length === 1) {
  36150. var g = arguments[0];
  36151. var snapTolerance = GeometrySnapper.computeSizeBasedSnapTolerance(g);
  36152. var pm = g.getPrecisionModel();
  36153. if (pm.getType() === PrecisionModel.FIXED) {
  36154. var fixedSnapTol = 1 / pm.getScale() * 2 / 1.415;
  36155. if (fixedSnapTol > snapTolerance) { snapTolerance = fixedSnapTol; }
  36156. }
  36157. return snapTolerance
  36158. } else if (arguments.length === 2) {
  36159. var g0 = arguments[0];
  36160. var g1 = arguments[1];
  36161. return Math.min(GeometrySnapper.computeOverlaySnapTolerance(g0), GeometrySnapper.computeOverlaySnapTolerance(g1))
  36162. }
  36163. };
  36164. GeometrySnapper.computeSizeBasedSnapTolerance = function computeSizeBasedSnapTolerance (g) {
  36165. var env = g.getEnvelopeInternal();
  36166. var minDimension = Math.min(env.getHeight(), env.getWidth());
  36167. var snapTol = minDimension * GeometrySnapper.SNAP_PRECISION_FACTOR;
  36168. return snapTol
  36169. };
  36170. GeometrySnapper.snapToSelf = function snapToSelf (geom, snapTolerance, cleanResult) {
  36171. var snapper0 = new GeometrySnapper(geom);
  36172. return snapper0.snapToSelf(snapTolerance, cleanResult)
  36173. };
  36174. staticAccessors$41.SNAP_PRECISION_FACTOR.get = function () { return 1e-9 };
  36175. Object.defineProperties( GeometrySnapper, staticAccessors$41 );
  36176. var SnapTransformer = (function (GeometryTransformer$$1) {
  36177. function SnapTransformer (snapTolerance, snapPts, isSelfSnap) {
  36178. GeometryTransformer$$1.call(this);
  36179. this._snapTolerance = snapTolerance || null;
  36180. this._snapPts = snapPts || null;
  36181. this._isSelfSnap = (isSelfSnap !== undefined) ? isSelfSnap : false;
  36182. }
  36183. if ( GeometryTransformer$$1 ) SnapTransformer.__proto__ = GeometryTransformer$$1;
  36184. SnapTransformer.prototype = Object.create( GeometryTransformer$$1 && GeometryTransformer$$1.prototype );
  36185. SnapTransformer.prototype.constructor = SnapTransformer;
  36186. SnapTransformer.prototype.snapLine = function snapLine (srcPts, snapPts) {
  36187. var snapper = new LineStringSnapper(srcPts, this._snapTolerance);
  36188. snapper.setAllowSnappingToSourceVertices(this._isSelfSnap);
  36189. return snapper.snapTo(snapPts)
  36190. };
  36191. SnapTransformer.prototype.transformCoordinates = function transformCoordinates (coords, parent) {
  36192. var srcPts = coords.toCoordinateArray();
  36193. var newPts = this.snapLine(srcPts, this._snapPts);
  36194. return this._factory.getCoordinateSequenceFactory().create(newPts)
  36195. };
  36196. SnapTransformer.prototype.interfaces_ = function interfaces_ () {
  36197. return []
  36198. };
  36199. SnapTransformer.prototype.getClass = function getClass () {
  36200. return SnapTransformer
  36201. };
  36202. return SnapTransformer;
  36203. }(GeometryTransformer));
  36204. var CommonBits = function CommonBits () {
  36205. this._isFirst = true;
  36206. this._commonMantissaBitsCount = 53;
  36207. this._commonBits = 0;
  36208. this._commonSignExp = null;
  36209. };
  36210. CommonBits.prototype.getCommon = function getCommon () {
  36211. return Double.longBitsToDouble(this._commonBits)
  36212. };
  36213. CommonBits.prototype.add = function add (num) {
  36214. var numBits = Double.doubleToLongBits(num);
  36215. if (this._isFirst) {
  36216. this._commonBits = numBits;
  36217. this._commonSignExp = CommonBits.signExpBits(this._commonBits);
  36218. this._isFirst = false;
  36219. return null
  36220. }
  36221. var numSignExp = CommonBits.signExpBits(numBits);
  36222. if (numSignExp !== this._commonSignExp) {
  36223. this._commonBits = 0;
  36224. return null
  36225. }
  36226. this._commonMantissaBitsCount = CommonBits.numCommonMostSigMantissaBits(this._commonBits, numBits);
  36227. this._commonBits = CommonBits.zeroLowerBits(this._commonBits, 64 - (12 + this._commonMantissaBitsCount));
  36228. };
  36229. CommonBits.prototype.toString = function toString () {
  36230. if (arguments.length === 1) {
  36231. var bits = arguments[0];
  36232. var x = Double.longBitsToDouble(bits);
  36233. var numStr = Double.toBinaryString(bits);
  36234. var padStr = '0000000000000000000000000000000000000000000000000000000000000000' + numStr;
  36235. var bitStr = padStr.substring(padStr.length - 64);
  36236. var str = bitStr.substring(0, 1) + ' ' + bitStr.substring(1, 12) + '(exp) ' + bitStr.substring(12) + ' [ ' + x + ' ]';
  36237. return str
  36238. }
  36239. };
  36240. CommonBits.prototype.interfaces_ = function interfaces_ () {
  36241. return []
  36242. };
  36243. CommonBits.prototype.getClass = function getClass () {
  36244. return CommonBits
  36245. };
  36246. CommonBits.getBit = function getBit (bits, i) {
  36247. var mask = 1 << i;
  36248. return (bits & mask) !== 0 ? 1 : 0
  36249. };
  36250. CommonBits.signExpBits = function signExpBits (num) {
  36251. return num >> 52
  36252. };
  36253. CommonBits.zeroLowerBits = function zeroLowerBits (bits, nBits) {
  36254. var invMask = (1 << nBits) - 1;
  36255. var mask = ~invMask;
  36256. var zeroed = bits & mask;
  36257. return zeroed
  36258. };
  36259. CommonBits.numCommonMostSigMantissaBits = function numCommonMostSigMantissaBits (num1, num2) {
  36260. var count = 0;
  36261. for (var i = 52; i >= 0; i--) {
  36262. if (CommonBits.getBit(num1, i) !== CommonBits.getBit(num2, i)) { return count }
  36263. count++;
  36264. }
  36265. return 52
  36266. };
  36267. var CommonBitsRemover = function CommonBitsRemover () {
  36268. this._commonCoord = null;
  36269. this._ccFilter = new CommonCoordinateFilter();
  36270. };
  36271. var staticAccessors$42 = { CommonCoordinateFilter: { configurable: true },Translater: { configurable: true } };
  36272. CommonBitsRemover.prototype.addCommonBits = function addCommonBits (geom) {
  36273. var trans = new Translater(this._commonCoord);
  36274. geom.apply(trans);
  36275. geom.geometryChanged();
  36276. };
  36277. CommonBitsRemover.prototype.removeCommonBits = function removeCommonBits (geom) {
  36278. if (this._commonCoord.x === 0.0 && this._commonCoord.y === 0.0) { return geom }
  36279. var invCoord = new Coordinate(this._commonCoord);
  36280. invCoord.x = -invCoord.x;
  36281. invCoord.y = -invCoord.y;
  36282. var trans = new Translater(invCoord);
  36283. geom.apply(trans);
  36284. geom.geometryChanged();
  36285. return geom
  36286. };
  36287. CommonBitsRemover.prototype.getCommonCoordinate = function getCommonCoordinate () {
  36288. return this._commonCoord
  36289. };
  36290. CommonBitsRemover.prototype.add = function add (geom) {
  36291. geom.apply(this._ccFilter);
  36292. this._commonCoord = this._ccFilter.getCommonCoordinate();
  36293. };
  36294. CommonBitsRemover.prototype.interfaces_ = function interfaces_ () {
  36295. return []
  36296. };
  36297. CommonBitsRemover.prototype.getClass = function getClass () {
  36298. return CommonBitsRemover
  36299. };
  36300. staticAccessors$42.CommonCoordinateFilter.get = function () { return CommonCoordinateFilter };
  36301. staticAccessors$42.Translater.get = function () { return Translater };
  36302. Object.defineProperties( CommonBitsRemover, staticAccessors$42 );
  36303. var CommonCoordinateFilter = function CommonCoordinateFilter () {
  36304. this._commonBitsX = new CommonBits();
  36305. this._commonBitsY = new CommonBits();
  36306. };
  36307. CommonCoordinateFilter.prototype.filter = function filter (coord) {
  36308. this._commonBitsX.add(coord.x);
  36309. this._commonBitsY.add(coord.y);
  36310. };
  36311. CommonCoordinateFilter.prototype.getCommonCoordinate = function getCommonCoordinate () {
  36312. return new Coordinate(this._commonBitsX.getCommon(), this._commonBitsY.getCommon())
  36313. };
  36314. CommonCoordinateFilter.prototype.interfaces_ = function interfaces_ () {
  36315. return [CoordinateFilter]
  36316. };
  36317. CommonCoordinateFilter.prototype.getClass = function getClass () {
  36318. return CommonCoordinateFilter
  36319. };
  36320. var Translater = function Translater () {
  36321. this.trans = null;
  36322. var trans = arguments[0];
  36323. this.trans = trans;
  36324. };
  36325. Translater.prototype.filter = function filter (seq, i) {
  36326. var xp = seq.getOrdinate(i, 0) + this.trans.x;
  36327. var yp = seq.getOrdinate(i, 1) + this.trans.y;
  36328. seq.setOrdinate(i, 0, xp);
  36329. seq.setOrdinate(i, 1, yp);
  36330. };
  36331. Translater.prototype.isDone = function isDone () {
  36332. return false
  36333. };
  36334. Translater.prototype.isGeometryChanged = function isGeometryChanged () {
  36335. return true
  36336. };
  36337. Translater.prototype.interfaces_ = function interfaces_ () {
  36338. return [CoordinateSequenceFilter]
  36339. };
  36340. Translater.prototype.getClass = function getClass () {
  36341. return Translater
  36342. };
  36343. var SnapOverlayOp = function SnapOverlayOp (g1, g2) {
  36344. this._geom = new Array(2).fill(null);
  36345. this._snapTolerance = null;
  36346. this._cbr = null;
  36347. this._geom[0] = g1;
  36348. this._geom[1] = g2;
  36349. this.computeSnapTolerance();
  36350. };
  36351. SnapOverlayOp.prototype.selfSnap = function selfSnap (geom) {
  36352. var snapper0 = new GeometrySnapper(geom);
  36353. var snapGeom = snapper0.snapTo(geom, this._snapTolerance);
  36354. return snapGeom
  36355. };
  36356. SnapOverlayOp.prototype.removeCommonBits = function removeCommonBits (geom) {
  36357. this._cbr = new CommonBitsRemover();
  36358. this._cbr.add(geom[0]);
  36359. this._cbr.add(geom[1]);
  36360. var remGeom = new Array(2).fill(null);
  36361. remGeom[0] = this._cbr.removeCommonBits(geom[0].copy());
  36362. remGeom[1] = this._cbr.removeCommonBits(geom[1].copy());
  36363. return remGeom
  36364. };
  36365. SnapOverlayOp.prototype.prepareResult = function prepareResult (geom) {
  36366. this._cbr.addCommonBits(geom);
  36367. return geom
  36368. };
  36369. SnapOverlayOp.prototype.getResultGeometry = function getResultGeometry (opCode) {
  36370. var prepGeom = this.snap(this._geom);
  36371. var result = OverlayOp.overlayOp(prepGeom[0], prepGeom[1], opCode);
  36372. return this.prepareResult(result)
  36373. };
  36374. SnapOverlayOp.prototype.checkValid = function checkValid (g) {
  36375. if (!g.isValid()) {
  36376. System.out.println('Snapped geometry is invalid');
  36377. }
  36378. };
  36379. SnapOverlayOp.prototype.computeSnapTolerance = function computeSnapTolerance () {
  36380. this._snapTolerance = GeometrySnapper.computeOverlaySnapTolerance(this._geom[0], this._geom[1]);
  36381. };
  36382. SnapOverlayOp.prototype.snap = function snap (geom) {
  36383. var remGeom = this.removeCommonBits(geom);
  36384. var snapGeom = GeometrySnapper.snap(remGeom[0], remGeom[1], this._snapTolerance);
  36385. return snapGeom
  36386. };
  36387. SnapOverlayOp.prototype.interfaces_ = function interfaces_ () {
  36388. return []
  36389. };
  36390. SnapOverlayOp.prototype.getClass = function getClass () {
  36391. return SnapOverlayOp
  36392. };
  36393. SnapOverlayOp.overlayOp = function overlayOp (g0, g1, opCode) {
  36394. var op = new SnapOverlayOp(g0, g1);
  36395. return op.getResultGeometry(opCode)
  36396. };
  36397. SnapOverlayOp.union = function union (g0, g1) {
  36398. return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.UNION)
  36399. };
  36400. SnapOverlayOp.intersection = function intersection (g0, g1) {
  36401. return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.INTERSECTION)
  36402. };
  36403. SnapOverlayOp.symDifference = function symDifference (g0, g1) {
  36404. return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.SYMDIFFERENCE)
  36405. };
  36406. SnapOverlayOp.difference = function difference (g0, g1) {
  36407. return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.DIFFERENCE)
  36408. };
  36409. var SnapIfNeededOverlayOp = function SnapIfNeededOverlayOp (g1, g2) {
  36410. this._geom = new Array(2).fill(null);
  36411. this._geom[0] = g1;
  36412. this._geom[1] = g2;
  36413. };
  36414. SnapIfNeededOverlayOp.prototype.getResultGeometry = function getResultGeometry (opCode) {
  36415. var result = null;
  36416. var isSuccess = false;
  36417. var savedException = null;
  36418. try {
  36419. result = OverlayOp.overlayOp(this._geom[0], this._geom[1], opCode);
  36420. var isValid = true;
  36421. if (isValid) { isSuccess = true; }
  36422. } catch (ex) {
  36423. if (ex instanceof RuntimeException) {
  36424. savedException = ex;
  36425. } else { throw ex }
  36426. } finally {}
  36427. if (!isSuccess) {
  36428. try {
  36429. result = SnapOverlayOp.overlayOp(this._geom[0], this._geom[1], opCode);
  36430. } catch (ex) {
  36431. if (ex instanceof RuntimeException) {
  36432. throw savedException
  36433. } else { throw ex }
  36434. } finally {}
  36435. }
  36436. return result
  36437. };
  36438. SnapIfNeededOverlayOp.prototype.interfaces_ = function interfaces_ () {
  36439. return []
  36440. };
  36441. SnapIfNeededOverlayOp.prototype.getClass = function getClass () {
  36442. return SnapIfNeededOverlayOp
  36443. };
  36444. SnapIfNeededOverlayOp.overlayOp = function overlayOp (g0, g1, opCode) {
  36445. var op = new SnapIfNeededOverlayOp(g0, g1);
  36446. return op.getResultGeometry(opCode)
  36447. };
  36448. SnapIfNeededOverlayOp.union = function union (g0, g1) {
  36449. return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.UNION)
  36450. };
  36451. SnapIfNeededOverlayOp.intersection = function intersection (g0, g1) {
  36452. return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.INTERSECTION)
  36453. };
  36454. SnapIfNeededOverlayOp.symDifference = function symDifference (g0, g1) {
  36455. return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.SYMDIFFERENCE)
  36456. };
  36457. SnapIfNeededOverlayOp.difference = function difference (g0, g1) {
  36458. return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.DIFFERENCE)
  36459. };
  36460. var MonotoneChain$2 = function MonotoneChain () {
  36461. this.mce = null;
  36462. this.chainIndex = null;
  36463. var mce = arguments[0];
  36464. var chainIndex = arguments[1];
  36465. this.mce = mce;
  36466. this.chainIndex = chainIndex;
  36467. };
  36468. MonotoneChain$2.prototype.computeIntersections = function computeIntersections (mc, si) {
  36469. this.mce.computeIntersectsForChain(this.chainIndex, mc.mce, mc.chainIndex, si);
  36470. };
  36471. MonotoneChain$2.prototype.interfaces_ = function interfaces_ () {
  36472. return []
  36473. };
  36474. MonotoneChain$2.prototype.getClass = function getClass () {
  36475. return MonotoneChain$2
  36476. };
  36477. var SweepLineEvent = function SweepLineEvent () {
  36478. this._label = null;
  36479. this._xValue = null;
  36480. this._eventType = null;
  36481. this._insertEvent = null;
  36482. this._deleteEventIndex = null;
  36483. this._obj = null;
  36484. if (arguments.length === 2) {
  36485. var x = arguments[0];
  36486. var insertEvent = arguments[1];
  36487. this._eventType = SweepLineEvent.DELETE;
  36488. this._xValue = x;
  36489. this._insertEvent = insertEvent;
  36490. } else if (arguments.length === 3) {
  36491. var label = arguments[0];
  36492. var x$1 = arguments[1];
  36493. var obj = arguments[2];
  36494. this._eventType = SweepLineEvent.INSERT;
  36495. this._label = label;
  36496. this._xValue = x$1;
  36497. this._obj = obj;
  36498. }
  36499. };
  36500. var staticAccessors$43 = { INSERT: { configurable: true },DELETE: { configurable: true } };
  36501. SweepLineEvent.prototype.isDelete = function isDelete () {
  36502. return this._eventType === SweepLineEvent.DELETE
  36503. };
  36504. SweepLineEvent.prototype.setDeleteEventIndex = function setDeleteEventIndex (deleteEventIndex) {
  36505. this._deleteEventIndex = deleteEventIndex;
  36506. };
  36507. SweepLineEvent.prototype.getObject = function getObject () {
  36508. return this._obj
  36509. };
  36510. SweepLineEvent.prototype.compareTo = function compareTo (o) {
  36511. var pe = o;
  36512. if (this._xValue < pe._xValue) { return -1 }
  36513. if (this._xValue > pe._xValue) { return 1 }
  36514. if (this._eventType < pe._eventType) { return -1 }
  36515. if (this._eventType > pe._eventType) { return 1 }
  36516. return 0
  36517. };
  36518. SweepLineEvent.prototype.getInsertEvent = function getInsertEvent () {
  36519. return this._insertEvent
  36520. };
  36521. SweepLineEvent.prototype.isInsert = function isInsert () {
  36522. return this._eventType === SweepLineEvent.INSERT
  36523. };
  36524. SweepLineEvent.prototype.isSameLabel = function isSameLabel (ev) {
  36525. if (this._label === null) { return false }
  36526. return this._label === ev._label
  36527. };
  36528. SweepLineEvent.prototype.getDeleteEventIndex = function getDeleteEventIndex () {
  36529. return this._deleteEventIndex
  36530. };
  36531. SweepLineEvent.prototype.interfaces_ = function interfaces_ () {
  36532. return [Comparable]
  36533. };
  36534. SweepLineEvent.prototype.getClass = function getClass () {
  36535. return SweepLineEvent
  36536. };
  36537. staticAccessors$43.INSERT.get = function () { return 1 };
  36538. staticAccessors$43.DELETE.get = function () { return 2 };
  36539. Object.defineProperties( SweepLineEvent, staticAccessors$43 );
  36540. var EdgeSetIntersector = function EdgeSetIntersector () {};
  36541. EdgeSetIntersector.prototype.interfaces_ = function interfaces_ () {
  36542. return []
  36543. };
  36544. EdgeSetIntersector.prototype.getClass = function getClass () {
  36545. return EdgeSetIntersector
  36546. };
  36547. var SegmentIntersector$2 = function SegmentIntersector () {
  36548. this._hasIntersection = false;
  36549. this._hasProper = false;
  36550. this._hasProperInterior = false;
  36551. this._properIntersectionPoint = null;
  36552. this._li = null;
  36553. this._includeProper = null;
  36554. this._recordIsolated = null;
  36555. this._isSelfIntersection = null;
  36556. this._numIntersections = 0;
  36557. this.numTests = 0;
  36558. this._bdyNodes = null;
  36559. this._isDone = false;
  36560. this._isDoneWhenProperInt = false;
  36561. var li = arguments[0];
  36562. var includeProper = arguments[1];
  36563. var recordIsolated = arguments[2];
  36564. this._li = li;
  36565. this._includeProper = includeProper;
  36566. this._recordIsolated = recordIsolated;
  36567. };
  36568. SegmentIntersector$2.prototype.isTrivialIntersection = function isTrivialIntersection (e0, segIndex0, e1, segIndex1) {
  36569. if (e0 === e1) {
  36570. if (this._li.getIntersectionNum() === 1) {
  36571. if (SegmentIntersector$2.isAdjacentSegments(segIndex0, segIndex1)) { return true }
  36572. if (e0.isClosed()) {
  36573. var maxSegIndex = e0.getNumPoints() - 1;
  36574. if ((segIndex0 === 0 && segIndex1 === maxSegIndex) ||
  36575. (segIndex1 === 0 && segIndex0 === maxSegIndex)) {
  36576. return true
  36577. }
  36578. }
  36579. }
  36580. }
  36581. return false
  36582. };
  36583. SegmentIntersector$2.prototype.getProperIntersectionPoint = function getProperIntersectionPoint () {
  36584. return this._properIntersectionPoint
  36585. };
  36586. SegmentIntersector$2.prototype.setIsDoneIfProperInt = function setIsDoneIfProperInt (isDoneWhenProperInt) {
  36587. this._isDoneWhenProperInt = isDoneWhenProperInt;
  36588. };
  36589. SegmentIntersector$2.prototype.hasProperInteriorIntersection = function hasProperInteriorIntersection () {
  36590. return this._hasProperInterior
  36591. };
  36592. SegmentIntersector$2.prototype.isBoundaryPointInternal = function isBoundaryPointInternal (li, bdyNodes) {
  36593. for (var i = bdyNodes.iterator(); i.hasNext();) {
  36594. var node = i.next();
  36595. var pt = node.getCoordinate();
  36596. if (li.isIntersection(pt)) { return true }
  36597. }
  36598. return false
  36599. };
  36600. SegmentIntersector$2.prototype.hasProperIntersection = function hasProperIntersection () {
  36601. return this._hasProper
  36602. };
  36603. SegmentIntersector$2.prototype.hasIntersection = function hasIntersection () {
  36604. return this._hasIntersection
  36605. };
  36606. SegmentIntersector$2.prototype.isDone = function isDone () {
  36607. return this._isDone
  36608. };
  36609. SegmentIntersector$2.prototype.isBoundaryPoint = function isBoundaryPoint (li, bdyNodes) {
  36610. if (bdyNodes === null) { return false }
  36611. if (this.isBoundaryPointInternal(li, bdyNodes[0])) { return true }
  36612. if (this.isBoundaryPointInternal(li, bdyNodes[1])) { return true }
  36613. return false
  36614. };
  36615. SegmentIntersector$2.prototype.setBoundaryNodes = function setBoundaryNodes (bdyNodes0, bdyNodes1) {
  36616. this._bdyNodes = new Array(2).fill(null);
  36617. this._bdyNodes[0] = bdyNodes0;
  36618. this._bdyNodes[1] = bdyNodes1;
  36619. };
  36620. SegmentIntersector$2.prototype.addIntersections = function addIntersections (e0, segIndex0, e1, segIndex1) {
  36621. if (e0 === e1 && segIndex0 === segIndex1) { return null }
  36622. this.numTests++;
  36623. var p00 = e0.getCoordinates()[segIndex0];
  36624. var p01 = e0.getCoordinates()[segIndex0 + 1];
  36625. var p10 = e1.getCoordinates()[segIndex1];
  36626. var p11 = e1.getCoordinates()[segIndex1 + 1];
  36627. this._li.computeIntersection(p00, p01, p10, p11);
  36628. if (this._li.hasIntersection()) {
  36629. if (this._recordIsolated) {
  36630. e0.setIsolated(false);
  36631. e1.setIsolated(false);
  36632. }
  36633. this._numIntersections++;
  36634. if (!this.isTrivialIntersection(e0, segIndex0, e1, segIndex1)) {
  36635. this._hasIntersection = true;
  36636. if (this._includeProper || !this._li.isProper()) {
  36637. e0.addIntersections(this._li, segIndex0, 0);
  36638. e1.addIntersections(this._li, segIndex1, 1);
  36639. }
  36640. if (this._li.isProper()) {
  36641. this._properIntersectionPoint = this._li.getIntersection(0).copy();
  36642. this._hasProper = true;
  36643. if (this._isDoneWhenProperInt) {
  36644. this._isDone = true;
  36645. }
  36646. if (!this.isBoundaryPoint(this._li, this._bdyNodes)) { this._hasProperInterior = true; }
  36647. }
  36648. }
  36649. }
  36650. };
  36651. SegmentIntersector$2.prototype.interfaces_ = function interfaces_ () {
  36652. return []
  36653. };
  36654. SegmentIntersector$2.prototype.getClass = function getClass () {
  36655. return SegmentIntersector$2
  36656. };
  36657. SegmentIntersector$2.isAdjacentSegments = function isAdjacentSegments (i1, i2) {
  36658. return Math.abs(i1 - i2) === 1
  36659. };
  36660. var SimpleMCSweepLineIntersector = (function (EdgeSetIntersector$$1) {
  36661. function SimpleMCSweepLineIntersector () {
  36662. EdgeSetIntersector$$1.call(this);
  36663. this.events = new ArrayList();
  36664. this.nOverlaps = null;
  36665. }
  36666. if ( EdgeSetIntersector$$1 ) SimpleMCSweepLineIntersector.__proto__ = EdgeSetIntersector$$1;
  36667. SimpleMCSweepLineIntersector.prototype = Object.create( EdgeSetIntersector$$1 && EdgeSetIntersector$$1.prototype );
  36668. SimpleMCSweepLineIntersector.prototype.constructor = SimpleMCSweepLineIntersector;
  36669. SimpleMCSweepLineIntersector.prototype.prepareEvents = function prepareEvents () {
  36670. var this$1 = this;
  36671. Collections.sort(this.events);
  36672. for (var i = 0; i < this.events.size(); i++) {
  36673. var ev = this$1.events.get(i);
  36674. if (ev.isDelete()) {
  36675. ev.getInsertEvent().setDeleteEventIndex(i);
  36676. }
  36677. }
  36678. };
  36679. SimpleMCSweepLineIntersector.prototype.computeIntersections = function computeIntersections () {
  36680. var this$1 = this;
  36681. if (arguments.length === 1) {
  36682. var si = arguments[0];
  36683. this.nOverlaps = 0;
  36684. this.prepareEvents();
  36685. for (var i = 0; i < this.events.size(); i++) {
  36686. var ev = this$1.events.get(i);
  36687. if (ev.isInsert()) {
  36688. this$1.processOverlaps(i, ev.getDeleteEventIndex(), ev, si);
  36689. }
  36690. if (si.isDone()) {
  36691. break
  36692. }
  36693. }
  36694. } else if (arguments.length === 3) {
  36695. if (arguments[2] instanceof SegmentIntersector$2 && (hasInterface(arguments[0], List) && hasInterface(arguments[1], List))) {
  36696. var edges0 = arguments[0];
  36697. var edges1 = arguments[1];
  36698. var si$1 = arguments[2];
  36699. this.addEdges(edges0, edges0);
  36700. this.addEdges(edges1, edges1);
  36701. this.computeIntersections(si$1);
  36702. } else if (typeof arguments[2] === 'boolean' && (hasInterface(arguments[0], List) && arguments[1] instanceof SegmentIntersector$2)) {
  36703. var edges = arguments[0];
  36704. var si$2 = arguments[1];
  36705. var testAllSegments = arguments[2];
  36706. if (testAllSegments) { this.addEdges(edges, null); } else { this.addEdges(edges); }
  36707. this.computeIntersections(si$2);
  36708. }
  36709. }
  36710. };
  36711. SimpleMCSweepLineIntersector.prototype.addEdge = function addEdge (edge, edgeSet) {
  36712. var this$1 = this;
  36713. var mce = edge.getMonotoneChainEdge();
  36714. var startIndex = mce.getStartIndexes();
  36715. for (var i = 0; i < startIndex.length - 1; i++) {
  36716. var mc = new MonotoneChain$2(mce, i);
  36717. var insertEvent = new SweepLineEvent(edgeSet, mce.getMinX(i), mc);
  36718. this$1.events.add(insertEvent);
  36719. this$1.events.add(new SweepLineEvent(mce.getMaxX(i), insertEvent));
  36720. }
  36721. };
  36722. SimpleMCSweepLineIntersector.prototype.processOverlaps = function processOverlaps (start, end, ev0, si) {
  36723. var this$1 = this;
  36724. var mc0 = ev0.getObject();
  36725. for (var i = start; i < end; i++) {
  36726. var ev1 = this$1.events.get(i);
  36727. if (ev1.isInsert()) {
  36728. var mc1 = ev1.getObject();
  36729. if (!ev0.isSameLabel(ev1)) {
  36730. mc0.computeIntersections(mc1, si);
  36731. this$1.nOverlaps++;
  36732. }
  36733. }
  36734. }
  36735. };
  36736. SimpleMCSweepLineIntersector.prototype.addEdges = function addEdges () {
  36737. var this$1 = this;
  36738. if (arguments.length === 1) {
  36739. var edges = arguments[0];
  36740. for (var i = edges.iterator(); i.hasNext();) {
  36741. var edge = i.next();
  36742. this$1.addEdge(edge, edge);
  36743. }
  36744. } else if (arguments.length === 2) {
  36745. var edges$1 = arguments[0];
  36746. var edgeSet = arguments[1];
  36747. for (var i$1 = edges$1.iterator(); i$1.hasNext();) {
  36748. var edge$1 = i$1.next();
  36749. this$1.addEdge(edge$1, edgeSet);
  36750. }
  36751. }
  36752. };
  36753. SimpleMCSweepLineIntersector.prototype.interfaces_ = function interfaces_ () {
  36754. return []
  36755. };
  36756. SimpleMCSweepLineIntersector.prototype.getClass = function getClass () {
  36757. return SimpleMCSweepLineIntersector
  36758. };
  36759. return SimpleMCSweepLineIntersector;
  36760. }(EdgeSetIntersector));
  36761. var IntervalRTreeNode = function IntervalRTreeNode () {
  36762. this._min = Double.POSITIVE_INFINITY;
  36763. this._max = Double.NEGATIVE_INFINITY;
  36764. };
  36765. var staticAccessors$45 = { NodeComparator: { configurable: true } };
  36766. IntervalRTreeNode.prototype.getMin = function getMin () {
  36767. return this._min
  36768. };
  36769. IntervalRTreeNode.prototype.intersects = function intersects (queryMin, queryMax) {
  36770. if (this._min > queryMax || this._max < queryMin) { return false }
  36771. return true
  36772. };
  36773. IntervalRTreeNode.prototype.getMax = function getMax () {
  36774. return this._max
  36775. };
  36776. IntervalRTreeNode.prototype.toString = function toString () {
  36777. return WKTWriter.toLineString(new Coordinate(this._min, 0), new Coordinate(this._max, 0))
  36778. };
  36779. IntervalRTreeNode.prototype.interfaces_ = function interfaces_ () {
  36780. return []
  36781. };
  36782. IntervalRTreeNode.prototype.getClass = function getClass () {
  36783. return IntervalRTreeNode
  36784. };
  36785. staticAccessors$45.NodeComparator.get = function () { return NodeComparator };
  36786. Object.defineProperties( IntervalRTreeNode, staticAccessors$45 );
  36787. var NodeComparator = function NodeComparator () {};
  36788. NodeComparator.prototype.compare = function compare (o1, o2) {
  36789. var n1 = o1;
  36790. var n2 = o2;
  36791. var mid1 = (n1._min + n1._max) / 2;
  36792. var mid2 = (n2._min + n2._max) / 2;
  36793. if (mid1 < mid2) { return -1 }
  36794. if (mid1 > mid2) { return 1 }
  36795. return 0
  36796. };
  36797. NodeComparator.prototype.interfaces_ = function interfaces_ () {
  36798. return [Comparator]
  36799. };
  36800. NodeComparator.prototype.getClass = function getClass () {
  36801. return NodeComparator
  36802. };
  36803. var IntervalRTreeLeafNode = (function (IntervalRTreeNode$$1) {
  36804. function IntervalRTreeLeafNode () {
  36805. IntervalRTreeNode$$1.call(this);
  36806. this._item = null;
  36807. var min = arguments[0];
  36808. var max = arguments[1];
  36809. var item = arguments[2];
  36810. this._min = min;
  36811. this._max = max;
  36812. this._item = item;
  36813. }
  36814. if ( IntervalRTreeNode$$1 ) IntervalRTreeLeafNode.__proto__ = IntervalRTreeNode$$1;
  36815. IntervalRTreeLeafNode.prototype = Object.create( IntervalRTreeNode$$1 && IntervalRTreeNode$$1.prototype );
  36816. IntervalRTreeLeafNode.prototype.constructor = IntervalRTreeLeafNode;
  36817. IntervalRTreeLeafNode.prototype.query = function query (queryMin, queryMax, visitor) {
  36818. if (!this.intersects(queryMin, queryMax)) { return null }
  36819. visitor.visitItem(this._item);
  36820. };
  36821. IntervalRTreeLeafNode.prototype.interfaces_ = function interfaces_ () {
  36822. return []
  36823. };
  36824. IntervalRTreeLeafNode.prototype.getClass = function getClass () {
  36825. return IntervalRTreeLeafNode
  36826. };
  36827. return IntervalRTreeLeafNode;
  36828. }(IntervalRTreeNode));
  36829. var IntervalRTreeBranchNode = (function (IntervalRTreeNode$$1) {
  36830. function IntervalRTreeBranchNode () {
  36831. IntervalRTreeNode$$1.call(this);
  36832. this._node1 = null;
  36833. this._node2 = null;
  36834. var n1 = arguments[0];
  36835. var n2 = arguments[1];
  36836. this._node1 = n1;
  36837. this._node2 = n2;
  36838. this.buildExtent(this._node1, this._node2);
  36839. }
  36840. if ( IntervalRTreeNode$$1 ) IntervalRTreeBranchNode.__proto__ = IntervalRTreeNode$$1;
  36841. IntervalRTreeBranchNode.prototype = Object.create( IntervalRTreeNode$$1 && IntervalRTreeNode$$1.prototype );
  36842. IntervalRTreeBranchNode.prototype.constructor = IntervalRTreeBranchNode;
  36843. IntervalRTreeBranchNode.prototype.buildExtent = function buildExtent (n1, n2) {
  36844. this._min = Math.min(n1._min, n2._min);
  36845. this._max = Math.max(n1._max, n2._max);
  36846. };
  36847. IntervalRTreeBranchNode.prototype.query = function query (queryMin, queryMax, visitor) {
  36848. if (!this.intersects(queryMin, queryMax)) {
  36849. return null
  36850. }
  36851. if (this._node1 !== null) { this._node1.query(queryMin, queryMax, visitor); }
  36852. if (this._node2 !== null) { this._node2.query(queryMin, queryMax, visitor); }
  36853. };
  36854. IntervalRTreeBranchNode.prototype.interfaces_ = function interfaces_ () {
  36855. return []
  36856. };
  36857. IntervalRTreeBranchNode.prototype.getClass = function getClass () {
  36858. return IntervalRTreeBranchNode
  36859. };
  36860. return IntervalRTreeBranchNode;
  36861. }(IntervalRTreeNode));
  36862. var SortedPackedIntervalRTree = function SortedPackedIntervalRTree () {
  36863. this._leaves = new ArrayList();
  36864. this._root = null;
  36865. this._level = 0;
  36866. };
  36867. SortedPackedIntervalRTree.prototype.buildTree = function buildTree () {
  36868. var this$1 = this;
  36869. Collections.sort(this._leaves, new IntervalRTreeNode.NodeComparator());
  36870. var src = this._leaves;
  36871. var temp = null;
  36872. var dest = new ArrayList();
  36873. while (true) {
  36874. this$1.buildLevel(src, dest);
  36875. if (dest.size() === 1) { return dest.get(0) }
  36876. temp = src;
  36877. src = dest;
  36878. dest = temp;
  36879. }
  36880. };
  36881. SortedPackedIntervalRTree.prototype.insert = function insert (min, max, item) {
  36882. if (this._root !== null) { throw new Error('Index cannot be added to once it has been queried') }
  36883. this._leaves.add(new IntervalRTreeLeafNode(min, max, item));
  36884. };
  36885. SortedPackedIntervalRTree.prototype.query = function query (min, max, visitor) {
  36886. this.init();
  36887. this._root.query(min, max, visitor);
  36888. };
  36889. SortedPackedIntervalRTree.prototype.buildRoot = function buildRoot () {
  36890. if (this._root !== null) { return null }
  36891. this._root = this.buildTree();
  36892. };
  36893. SortedPackedIntervalRTree.prototype.printNode = function printNode (node) {
  36894. System.out.println(WKTWriter.toLineString(new Coordinate(node._min, this._level), new Coordinate(node._max, this._level)));
  36895. };
  36896. SortedPackedIntervalRTree.prototype.init = function init () {
  36897. if (this._root !== null) { return null }
  36898. this.buildRoot();
  36899. };
  36900. SortedPackedIntervalRTree.prototype.buildLevel = function buildLevel (src, dest) {
  36901. this._level++;
  36902. dest.clear();
  36903. for (var i = 0; i < src.size(); i += 2) {
  36904. var n1 = src.get(i);
  36905. var n2 = i + 1 < src.size() ? src.get(i) : null;
  36906. if (n2 === null) {
  36907. dest.add(n1);
  36908. } else {
  36909. var node = new IntervalRTreeBranchNode(src.get(i), src.get(i + 1));
  36910. dest.add(node);
  36911. }
  36912. }
  36913. };
  36914. SortedPackedIntervalRTree.prototype.interfaces_ = function interfaces_ () {
  36915. return []
  36916. };
  36917. SortedPackedIntervalRTree.prototype.getClass = function getClass () {
  36918. return SortedPackedIntervalRTree
  36919. };
  36920. var ArrayListVisitor = function ArrayListVisitor () {
  36921. this._items = new ArrayList();
  36922. };
  36923. ArrayListVisitor.prototype.visitItem = function visitItem (item) {
  36924. this._items.add(item);
  36925. };
  36926. ArrayListVisitor.prototype.getItems = function getItems () {
  36927. return this._items
  36928. };
  36929. ArrayListVisitor.prototype.interfaces_ = function interfaces_ () {
  36930. return [ItemVisitor]
  36931. };
  36932. ArrayListVisitor.prototype.getClass = function getClass () {
  36933. return ArrayListVisitor
  36934. };
  36935. var IndexedPointInAreaLocator = function IndexedPointInAreaLocator () {
  36936. this._index = null;
  36937. var g = arguments[0];
  36938. if (!hasInterface(g, Polygonal)) { throw new IllegalArgumentException('Argument must be Polygonal') }
  36939. this._index = new IntervalIndexedGeometry(g);
  36940. };
  36941. var staticAccessors$44 = { SegmentVisitor: { configurable: true },IntervalIndexedGeometry: { configurable: true } };
  36942. IndexedPointInAreaLocator.prototype.locate = function locate (p) {
  36943. var rcc = new RayCrossingCounter(p);
  36944. var visitor = new SegmentVisitor(rcc);
  36945. this._index.query(p.y, p.y, visitor);
  36946. return rcc.getLocation()
  36947. };
  36948. IndexedPointInAreaLocator.prototype.interfaces_ = function interfaces_ () {
  36949. return [PointOnGeometryLocator]
  36950. };
  36951. IndexedPointInAreaLocator.prototype.getClass = function getClass () {
  36952. return IndexedPointInAreaLocator
  36953. };
  36954. staticAccessors$44.SegmentVisitor.get = function () { return SegmentVisitor };
  36955. staticAccessors$44.IntervalIndexedGeometry.get = function () { return IntervalIndexedGeometry };
  36956. Object.defineProperties( IndexedPointInAreaLocator, staticAccessors$44 );
  36957. var SegmentVisitor = function SegmentVisitor () {
  36958. this._counter = null;
  36959. var counter = arguments[0];
  36960. this._counter = counter;
  36961. };
  36962. SegmentVisitor.prototype.visitItem = function visitItem (item) {
  36963. var seg = item;
  36964. this._counter.countSegment(seg.getCoordinate(0), seg.getCoordinate(1));
  36965. };
  36966. SegmentVisitor.prototype.interfaces_ = function interfaces_ () {
  36967. return [ItemVisitor]
  36968. };
  36969. SegmentVisitor.prototype.getClass = function getClass () {
  36970. return SegmentVisitor
  36971. };
  36972. var IntervalIndexedGeometry = function IntervalIndexedGeometry () {
  36973. this._index = new SortedPackedIntervalRTree();
  36974. var geom = arguments[0];
  36975. this.init(geom);
  36976. };
  36977. IntervalIndexedGeometry.prototype.init = function init (geom) {
  36978. var this$1 = this;
  36979. var lines = LinearComponentExtracter.getLines(geom);
  36980. for (var i = lines.iterator(); i.hasNext();) {
  36981. var line = i.next();
  36982. var pts = line.getCoordinates();
  36983. this$1.addLine(pts);
  36984. }
  36985. };
  36986. IntervalIndexedGeometry.prototype.addLine = function addLine (pts) {
  36987. var this$1 = this;
  36988. for (var i = 1; i < pts.length; i++) {
  36989. var seg = new LineSegment(pts[i - 1], pts[i]);
  36990. var min = Math.min(seg.p0.y, seg.p1.y);
  36991. var max = Math.max(seg.p0.y, seg.p1.y);
  36992. this$1._index.insert(min, max, seg);
  36993. }
  36994. };
  36995. IntervalIndexedGeometry.prototype.query = function query () {
  36996. if (arguments.length === 2) {
  36997. var min = arguments[0];
  36998. var max = arguments[1];
  36999. var visitor = new ArrayListVisitor();
  37000. this._index.query(min, max, visitor);
  37001. return visitor.getItems()
  37002. } else if (arguments.length === 3) {
  37003. var min$1 = arguments[0];
  37004. var max$1 = arguments[1];
  37005. var visitor$1 = arguments[2];
  37006. this._index.query(min$1, max$1, visitor$1);
  37007. }
  37008. };
  37009. IntervalIndexedGeometry.prototype.interfaces_ = function interfaces_ () {
  37010. return []
  37011. };
  37012. IntervalIndexedGeometry.prototype.getClass = function getClass () {
  37013. return IntervalIndexedGeometry
  37014. };
  37015. var GeometryGraph = (function (PlanarGraph$$1) {
  37016. function GeometryGraph () {
  37017. PlanarGraph$$1.call(this);
  37018. this._parentGeom = null;
  37019. this._lineEdgeMap = new HashMap();
  37020. this._boundaryNodeRule = null;
  37021. this._useBoundaryDeterminationRule = true;
  37022. this._argIndex = null;
  37023. this._boundaryNodes = null;
  37024. this._hasTooFewPoints = false;
  37025. this._invalidPoint = null;
  37026. this._areaPtLocator = null;
  37027. this._ptLocator = new PointLocator();
  37028. if (arguments.length === 2) {
  37029. var argIndex = arguments[0];
  37030. var parentGeom = arguments[1];
  37031. var boundaryNodeRule = BoundaryNodeRule.OGC_SFS_BOUNDARY_RULE;
  37032. this._argIndex = argIndex;
  37033. this._parentGeom = parentGeom;
  37034. this._boundaryNodeRule = boundaryNodeRule;
  37035. if (parentGeom !== null) {
  37036. this.add(parentGeom);
  37037. }
  37038. } else if (arguments.length === 3) {
  37039. var argIndex$1 = arguments[0];
  37040. var parentGeom$1 = arguments[1];
  37041. var boundaryNodeRule$1 = arguments[2];
  37042. this._argIndex = argIndex$1;
  37043. this._parentGeom = parentGeom$1;
  37044. this._boundaryNodeRule = boundaryNodeRule$1;
  37045. if (parentGeom$1 !== null) {
  37046. this.add(parentGeom$1);
  37047. }
  37048. }
  37049. }
  37050. if ( PlanarGraph$$1 ) GeometryGraph.__proto__ = PlanarGraph$$1;
  37051. GeometryGraph.prototype = Object.create( PlanarGraph$$1 && PlanarGraph$$1.prototype );
  37052. GeometryGraph.prototype.constructor = GeometryGraph;
  37053. GeometryGraph.prototype.insertBoundaryPoint = function insertBoundaryPoint (argIndex, coord) {
  37054. var n = this._nodes.addNode(coord);
  37055. var lbl = n.getLabel();
  37056. var boundaryCount = 1;
  37057. var loc = Location.NONE;
  37058. loc = lbl.getLocation(argIndex, Position.ON);
  37059. if (loc === Location.BOUNDARY) { boundaryCount++; }
  37060. var newLoc = GeometryGraph.determineBoundary(this._boundaryNodeRule, boundaryCount);
  37061. lbl.setLocation(argIndex, newLoc);
  37062. };
  37063. GeometryGraph.prototype.computeSelfNodes = function computeSelfNodes () {
  37064. if (arguments.length === 2) {
  37065. var li = arguments[0];
  37066. var computeRingSelfNodes = arguments[1];
  37067. return this.computeSelfNodes(li, computeRingSelfNodes, false)
  37068. } else if (arguments.length === 3) {
  37069. var li$1 = arguments[0];
  37070. var computeRingSelfNodes$1 = arguments[1];
  37071. var isDoneIfProperInt = arguments[2];
  37072. var si = new SegmentIntersector$2(li$1, true, false);
  37073. si.setIsDoneIfProperInt(isDoneIfProperInt);
  37074. var esi = this.createEdgeSetIntersector();
  37075. var isRings = this._parentGeom instanceof LinearRing || this._parentGeom instanceof Polygon || this._parentGeom instanceof MultiPolygon;
  37076. var computeAllSegments = computeRingSelfNodes$1 || !isRings;
  37077. esi.computeIntersections(this._edges, si, computeAllSegments);
  37078. this.addSelfIntersectionNodes(this._argIndex);
  37079. return si
  37080. }
  37081. };
  37082. GeometryGraph.prototype.computeSplitEdges = function computeSplitEdges (edgelist) {
  37083. for (var i = this._edges.iterator(); i.hasNext();) {
  37084. var e = i.next();
  37085. e.eiList.addSplitEdges(edgelist);
  37086. }
  37087. };
  37088. GeometryGraph.prototype.computeEdgeIntersections = function computeEdgeIntersections (g, li, includeProper) {
  37089. var si = new SegmentIntersector$2(li, includeProper, true);
  37090. si.setBoundaryNodes(this.getBoundaryNodes(), g.getBoundaryNodes());
  37091. var esi = this.createEdgeSetIntersector();
  37092. esi.computeIntersections(this._edges, g._edges, si);
  37093. return si
  37094. };
  37095. GeometryGraph.prototype.getGeometry = function getGeometry () {
  37096. return this._parentGeom
  37097. };
  37098. GeometryGraph.prototype.getBoundaryNodeRule = function getBoundaryNodeRule () {
  37099. return this._boundaryNodeRule
  37100. };
  37101. GeometryGraph.prototype.hasTooFewPoints = function hasTooFewPoints () {
  37102. return this._hasTooFewPoints
  37103. };
  37104. GeometryGraph.prototype.addPoint = function addPoint () {
  37105. if (arguments[0] instanceof Point) {
  37106. var p = arguments[0];
  37107. var coord = p.getCoordinate();
  37108. this.insertPoint(this._argIndex, coord, Location.INTERIOR);
  37109. } else if (arguments[0] instanceof Coordinate) {
  37110. var pt = arguments[0];
  37111. this.insertPoint(this._argIndex, pt, Location.INTERIOR);
  37112. }
  37113. };
  37114. GeometryGraph.prototype.addPolygon = function addPolygon (p) {
  37115. var this$1 = this;
  37116. this.addPolygonRing(p.getExteriorRing(), Location.EXTERIOR, Location.INTERIOR);
  37117. for (var i = 0; i < p.getNumInteriorRing(); i++) {
  37118. var hole = p.getInteriorRingN(i);
  37119. this$1.addPolygonRing(hole, Location.INTERIOR, Location.EXTERIOR);
  37120. }
  37121. };
  37122. GeometryGraph.prototype.addEdge = function addEdge (e) {
  37123. this.insertEdge(e);
  37124. var coord = e.getCoordinates();
  37125. this.insertPoint(this._argIndex, coord[0], Location.BOUNDARY);
  37126. this.insertPoint(this._argIndex, coord[coord.length - 1], Location.BOUNDARY);
  37127. };
  37128. GeometryGraph.prototype.addLineString = function addLineString (line) {
  37129. var coord = CoordinateArrays.removeRepeatedPoints(line.getCoordinates());
  37130. if (coord.length < 2) {
  37131. this._hasTooFewPoints = true;
  37132. this._invalidPoint = coord[0];
  37133. return null
  37134. }
  37135. var e = new Edge$1(coord, new Label(this._argIndex, Location.INTERIOR));
  37136. this._lineEdgeMap.put(line, e);
  37137. this.insertEdge(e);
  37138. Assert.isTrue(coord.length >= 2, 'found LineString with single point');
  37139. this.insertBoundaryPoint(this._argIndex, coord[0]);
  37140. this.insertBoundaryPoint(this._argIndex, coord[coord.length - 1]);
  37141. };
  37142. GeometryGraph.prototype.getInvalidPoint = function getInvalidPoint () {
  37143. return this._invalidPoint
  37144. };
  37145. GeometryGraph.prototype.getBoundaryPoints = function getBoundaryPoints () {
  37146. var coll = this.getBoundaryNodes();
  37147. var pts = new Array(coll.size()).fill(null);
  37148. var i = 0;
  37149. for (var it = coll.iterator(); it.hasNext();) {
  37150. var node = it.next();
  37151. pts[i++] = node.getCoordinate().copy();
  37152. }
  37153. return pts
  37154. };
  37155. GeometryGraph.prototype.getBoundaryNodes = function getBoundaryNodes () {
  37156. if (this._boundaryNodes === null) { this._boundaryNodes = this._nodes.getBoundaryNodes(this._argIndex); }
  37157. return this._boundaryNodes
  37158. };
  37159. GeometryGraph.prototype.addSelfIntersectionNode = function addSelfIntersectionNode (argIndex, coord, loc) {
  37160. if (this.isBoundaryNode(argIndex, coord)) { return null }
  37161. if (loc === Location.BOUNDARY && this._useBoundaryDeterminationRule) { this.insertBoundaryPoint(argIndex, coord); } else { this.insertPoint(argIndex, coord, loc); }
  37162. };
  37163. GeometryGraph.prototype.addPolygonRing = function addPolygonRing (lr, cwLeft, cwRight) {
  37164. if (lr.isEmpty()) { return null }
  37165. var coord = CoordinateArrays.removeRepeatedPoints(lr.getCoordinates());
  37166. if (coord.length < 4) {
  37167. this._hasTooFewPoints = true;
  37168. this._invalidPoint = coord[0];
  37169. return null
  37170. }
  37171. var left = cwLeft;
  37172. var right = cwRight;
  37173. if (CGAlgorithms.isCCW(coord)) {
  37174. left = cwRight;
  37175. right = cwLeft;
  37176. }
  37177. var e = new Edge$1(coord, new Label(this._argIndex, Location.BOUNDARY, left, right));
  37178. this._lineEdgeMap.put(lr, e);
  37179. this.insertEdge(e);
  37180. this.insertPoint(this._argIndex, coord[0], Location.BOUNDARY);
  37181. };
  37182. GeometryGraph.prototype.insertPoint = function insertPoint (argIndex, coord, onLocation) {
  37183. var n = this._nodes.addNode(coord);
  37184. var lbl = n.getLabel();
  37185. if (lbl === null) {
  37186. n._label = new Label(argIndex, onLocation);
  37187. } else { lbl.setLocation(argIndex, onLocation); }
  37188. };
  37189. GeometryGraph.prototype.createEdgeSetIntersector = function createEdgeSetIntersector () {
  37190. return new SimpleMCSweepLineIntersector()
  37191. };
  37192. GeometryGraph.prototype.addSelfIntersectionNodes = function addSelfIntersectionNodes (argIndex) {
  37193. var this$1 = this;
  37194. for (var i = this._edges.iterator(); i.hasNext();) {
  37195. var e = i.next();
  37196. var eLoc = e.getLabel().getLocation(argIndex);
  37197. for (var eiIt = e.eiList.iterator(); eiIt.hasNext();) {
  37198. var ei = eiIt.next();
  37199. this$1.addSelfIntersectionNode(argIndex, ei.coord, eLoc);
  37200. }
  37201. }
  37202. };
  37203. GeometryGraph.prototype.add = function add () {
  37204. if (arguments.length === 1) {
  37205. var g = arguments[0];
  37206. if (g.isEmpty()) { return null }
  37207. if (g instanceof MultiPolygon) { this._useBoundaryDeterminationRule = false; }
  37208. if (g instanceof Polygon) { this.addPolygon(g); }
  37209. else if (g instanceof LineString$1) { this.addLineString(g); }
  37210. else if (g instanceof Point) { this.addPoint(g); }
  37211. else if (g instanceof MultiPoint) { this.addCollection(g); }
  37212. else if (g instanceof MultiLineString) { this.addCollection(g); }
  37213. else if (g instanceof MultiPolygon) { this.addCollection(g); }
  37214. else if (g instanceof GeometryCollection) { this.addCollection(g); }
  37215. else { throw new Error(g.getClass().getName()) }
  37216. } else { return PlanarGraph$$1.prototype.add.apply(this, arguments) }
  37217. };
  37218. GeometryGraph.prototype.addCollection = function addCollection (gc) {
  37219. var this$1 = this;
  37220. for (var i = 0; i < gc.getNumGeometries(); i++) {
  37221. var g = gc.getGeometryN(i);
  37222. this$1.add(g);
  37223. }
  37224. };
  37225. GeometryGraph.prototype.locate = function locate (pt) {
  37226. if (hasInterface(this._parentGeom, Polygonal) && this._parentGeom.getNumGeometries() > 50) {
  37227. if (this._areaPtLocator === null) {
  37228. this._areaPtLocator = new IndexedPointInAreaLocator(this._parentGeom);
  37229. }
  37230. return this._areaPtLocator.locate(pt)
  37231. }
  37232. return this._ptLocator.locate(pt, this._parentGeom)
  37233. };
  37234. GeometryGraph.prototype.findEdge = function findEdge () {
  37235. if (arguments.length === 1) {
  37236. var line = arguments[0];
  37237. return this._lineEdgeMap.get(line)
  37238. } else { return PlanarGraph$$1.prototype.findEdge.apply(this, arguments) }
  37239. };
  37240. GeometryGraph.prototype.interfaces_ = function interfaces_ () {
  37241. return []
  37242. };
  37243. GeometryGraph.prototype.getClass = function getClass () {
  37244. return GeometryGraph
  37245. };
  37246. GeometryGraph.determineBoundary = function determineBoundary (boundaryNodeRule, boundaryCount) {
  37247. return boundaryNodeRule.isInBoundary(boundaryCount) ? Location.BOUNDARY : Location.INTERIOR
  37248. };
  37249. return GeometryGraph;
  37250. }(PlanarGraph));
  37251. var GeometryGraphOp = function GeometryGraphOp () {
  37252. this._li = new RobustLineIntersector();
  37253. this._resultPrecisionModel = null;
  37254. this._arg = null;
  37255. if (arguments.length === 1) {
  37256. var g0 = arguments[0];
  37257. this.setComputationPrecision(g0.getPrecisionModel());
  37258. this._arg = new Array(1).fill(null);
  37259. this._arg[0] = new GeometryGraph(0, g0);
  37260. } else if (arguments.length === 2) {
  37261. var g0$1 = arguments[0];
  37262. var g1 = arguments[1];
  37263. var boundaryNodeRule = BoundaryNodeRule.OGC_SFS_BOUNDARY_RULE;
  37264. if (g0$1.getPrecisionModel().compareTo(g1.getPrecisionModel()) >= 0) { this.setComputationPrecision(g0$1.getPrecisionModel()); } else { this.setComputationPrecision(g1.getPrecisionModel()); }
  37265. this._arg = new Array(2).fill(null);
  37266. this._arg[0] = new GeometryGraph(0, g0$1, boundaryNodeRule);
  37267. this._arg[1] = new GeometryGraph(1, g1, boundaryNodeRule);
  37268. } else if (arguments.length === 3) {
  37269. var g0$2 = arguments[0];
  37270. var g1$1 = arguments[1];
  37271. var boundaryNodeRule$1 = arguments[2];
  37272. if (g0$2.getPrecisionModel().compareTo(g1$1.getPrecisionModel()) >= 0) { this.setComputationPrecision(g0$2.getPrecisionModel()); } else { this.setComputationPrecision(g1$1.getPrecisionModel()); }
  37273. this._arg = new Array(2).fill(null);
  37274. this._arg[0] = new GeometryGraph(0, g0$2, boundaryNodeRule$1);
  37275. this._arg[1] = new GeometryGraph(1, g1$1, boundaryNodeRule$1);
  37276. }
  37277. };
  37278. GeometryGraphOp.prototype.getArgGeometry = function getArgGeometry (i) {
  37279. return this._arg[i].getGeometry()
  37280. };
  37281. GeometryGraphOp.prototype.setComputationPrecision = function setComputationPrecision (pm) {
  37282. this._resultPrecisionModel = pm;
  37283. this._li.setPrecisionModel(this._resultPrecisionModel);
  37284. };
  37285. GeometryGraphOp.prototype.interfaces_ = function interfaces_ () {
  37286. return []
  37287. };
  37288. GeometryGraphOp.prototype.getClass = function getClass () {
  37289. return GeometryGraphOp
  37290. };
  37291. // operation.geometrygraph
  37292. var GeometryMapper = function GeometryMapper () {};
  37293. GeometryMapper.prototype.interfaces_ = function interfaces_ () {
  37294. return []
  37295. };
  37296. GeometryMapper.prototype.getClass = function getClass () {
  37297. return GeometryMapper
  37298. };
  37299. GeometryMapper.map = function map () {
  37300. if (arguments[0] instanceof Geometry && hasInterface(arguments[1], GeometryMapper.MapOp)) {
  37301. var geom = arguments[0];
  37302. var op = arguments[1];
  37303. var mapped = new ArrayList();
  37304. for (var i = 0; i < geom.getNumGeometries(); i++) {
  37305. var g = op.map(geom.getGeometryN(i));
  37306. if (g !== null) { mapped.add(g); }
  37307. }
  37308. return geom.getFactory().buildGeometry(mapped)
  37309. } else if (hasInterface(arguments[0], Collection) && hasInterface(arguments[1], GeometryMapper.MapOp)) {
  37310. var geoms = arguments[0];
  37311. var op$1 = arguments[1];
  37312. var mapped$1 = new ArrayList();
  37313. for (var i$1 = geoms.iterator(); i$1.hasNext();) {
  37314. var g$1 = i$1.next();
  37315. var gr = op$1.map(g$1);
  37316. if (gr !== null) { mapped$1.add(gr); }
  37317. }
  37318. return mapped$1
  37319. }
  37320. };
  37321. GeometryMapper.MapOp = function MapOp () {};
  37322. var OverlayOp = (function (GeometryGraphOp) {
  37323. function OverlayOp () {
  37324. var g0 = arguments[0];
  37325. var g1 = arguments[1];
  37326. GeometryGraphOp.call(this, g0, g1);
  37327. this._ptLocator = new PointLocator();
  37328. this._geomFact = null;
  37329. this._resultGeom = null;
  37330. this._graph = null;
  37331. this._edgeList = new EdgeList();
  37332. this._resultPolyList = new ArrayList();
  37333. this._resultLineList = new ArrayList();
  37334. this._resultPointList = new ArrayList();
  37335. this._graph = new PlanarGraph(new OverlayNodeFactory());
  37336. this._geomFact = g0.getFactory();
  37337. }
  37338. if ( GeometryGraphOp ) OverlayOp.__proto__ = GeometryGraphOp;
  37339. OverlayOp.prototype = Object.create( GeometryGraphOp && GeometryGraphOp.prototype );
  37340. OverlayOp.prototype.constructor = OverlayOp;
  37341. OverlayOp.prototype.insertUniqueEdge = function insertUniqueEdge (e) {
  37342. var existingEdge = this._edgeList.findEqualEdge(e);
  37343. if (existingEdge !== null) {
  37344. var existingLabel = existingEdge.getLabel();
  37345. var labelToMerge = e.getLabel();
  37346. if (!existingEdge.isPointwiseEqual(e)) {
  37347. labelToMerge = new Label(e.getLabel());
  37348. labelToMerge.flip();
  37349. }
  37350. var depth = existingEdge.getDepth();
  37351. if (depth.isNull()) {
  37352. depth.add(existingLabel);
  37353. }
  37354. depth.add(labelToMerge);
  37355. existingLabel.merge(labelToMerge);
  37356. } else {
  37357. this._edgeList.add(e);
  37358. }
  37359. };
  37360. OverlayOp.prototype.getGraph = function getGraph () {
  37361. return this._graph
  37362. };
  37363. OverlayOp.prototype.cancelDuplicateResultEdges = function cancelDuplicateResultEdges () {
  37364. for (var it = this._graph.getEdgeEnds().iterator(); it.hasNext();) {
  37365. var de = it.next();
  37366. var sym = de.getSym();
  37367. if (de.isInResult() && sym.isInResult()) {
  37368. de.setInResult(false);
  37369. sym.setInResult(false);
  37370. }
  37371. }
  37372. };
  37373. OverlayOp.prototype.isCoveredByLA = function isCoveredByLA (coord) {
  37374. if (this.isCovered(coord, this._resultLineList)) { return true }
  37375. if (this.isCovered(coord, this._resultPolyList)) { return true }
  37376. return false
  37377. };
  37378. OverlayOp.prototype.computeGeometry = function computeGeometry (resultPointList, resultLineList, resultPolyList, opcode) {
  37379. var geomList = new ArrayList();
  37380. geomList.addAll(resultPointList);
  37381. geomList.addAll(resultLineList);
  37382. geomList.addAll(resultPolyList);
  37383. if (geomList.isEmpty()) { return OverlayOp.createEmptyResult(opcode, this._arg[0].getGeometry(), this._arg[1].getGeometry(), this._geomFact) }
  37384. return this._geomFact.buildGeometry(geomList)
  37385. };
  37386. OverlayOp.prototype.mergeSymLabels = function mergeSymLabels () {
  37387. for (var nodeit = this._graph.getNodes().iterator(); nodeit.hasNext();) {
  37388. var node = nodeit.next();
  37389. node.getEdges().mergeSymLabels();
  37390. }
  37391. };
  37392. OverlayOp.prototype.isCovered = function isCovered (coord, geomList) {
  37393. var this$1 = this;
  37394. for (var it = geomList.iterator(); it.hasNext();) {
  37395. var geom = it.next();
  37396. var loc = this$1._ptLocator.locate(coord, geom);
  37397. if (loc !== Location.EXTERIOR) { return true }
  37398. }
  37399. return false
  37400. };
  37401. OverlayOp.prototype.replaceCollapsedEdges = function replaceCollapsedEdges () {
  37402. var newEdges = new ArrayList();
  37403. for (var it = this._edgeList.iterator(); it.hasNext();) {
  37404. var e = it.next();
  37405. if (e.isCollapsed()) {
  37406. it.remove();
  37407. newEdges.add(e.getCollapsedEdge());
  37408. }
  37409. }
  37410. this._edgeList.addAll(newEdges);
  37411. };
  37412. OverlayOp.prototype.updateNodeLabelling = function updateNodeLabelling () {
  37413. for (var nodeit = this._graph.getNodes().iterator(); nodeit.hasNext();) {
  37414. var node = nodeit.next();
  37415. var lbl = node.getEdges().getLabel();
  37416. node.getLabel().merge(lbl);
  37417. }
  37418. };
  37419. OverlayOp.prototype.getResultGeometry = function getResultGeometry (overlayOpCode) {
  37420. this.computeOverlay(overlayOpCode);
  37421. return this._resultGeom
  37422. };
  37423. OverlayOp.prototype.insertUniqueEdges = function insertUniqueEdges (edges) {
  37424. var this$1 = this;
  37425. for (var i = edges.iterator(); i.hasNext();) {
  37426. var e = i.next();
  37427. this$1.insertUniqueEdge(e);
  37428. }
  37429. };
  37430. OverlayOp.prototype.computeOverlay = function computeOverlay (opCode) {
  37431. this.copyPoints(0);
  37432. this.copyPoints(1);
  37433. this._arg[0].computeSelfNodes(this._li, false);
  37434. this._arg[1].computeSelfNodes(this._li, false);
  37435. this._arg[0].computeEdgeIntersections(this._arg[1], this._li, true);
  37436. var baseSplitEdges = new ArrayList();
  37437. this._arg[0].computeSplitEdges(baseSplitEdges);
  37438. this._arg[1].computeSplitEdges(baseSplitEdges);
  37439. // const splitEdges = baseSplitEdges
  37440. this.insertUniqueEdges(baseSplitEdges);
  37441. this.computeLabelsFromDepths();
  37442. this.replaceCollapsedEdges();
  37443. EdgeNodingValidator.checkValid(this._edgeList.getEdges());
  37444. this._graph.addEdges(this._edgeList.getEdges());
  37445. this.computeLabelling();
  37446. this.labelIncompleteNodes();
  37447. this.findResultAreaEdges(opCode);
  37448. this.cancelDuplicateResultEdges();
  37449. var polyBuilder = new PolygonBuilder(this._geomFact);
  37450. polyBuilder.add(this._graph);
  37451. this._resultPolyList = polyBuilder.getPolygons();
  37452. var lineBuilder = new LineBuilder(this, this._geomFact, this._ptLocator);
  37453. this._resultLineList = lineBuilder.build(opCode);
  37454. var pointBuilder = new PointBuilder(this, this._geomFact, this._ptLocator);
  37455. this._resultPointList = pointBuilder.build(opCode);
  37456. this._resultGeom = this.computeGeometry(this._resultPointList, this._resultLineList, this._resultPolyList, opCode);
  37457. };
  37458. OverlayOp.prototype.labelIncompleteNode = function labelIncompleteNode (n, targetIndex) {
  37459. var loc = this._ptLocator.locate(n.getCoordinate(), this._arg[targetIndex].getGeometry());
  37460. n.getLabel().setLocation(targetIndex, loc);
  37461. };
  37462. OverlayOp.prototype.copyPoints = function copyPoints (argIndex) {
  37463. var this$1 = this;
  37464. for (var i = this._arg[argIndex].getNodeIterator(); i.hasNext();) {
  37465. var graphNode = i.next();
  37466. var newNode = this$1._graph.addNode(graphNode.getCoordinate());
  37467. newNode.setLabel(argIndex, graphNode.getLabel().getLocation(argIndex));
  37468. }
  37469. };
  37470. OverlayOp.prototype.findResultAreaEdges = function findResultAreaEdges (opCode) {
  37471. for (var it = this._graph.getEdgeEnds().iterator(); it.hasNext();) {
  37472. var de = it.next();
  37473. var label = de.getLabel();
  37474. if (label.isArea() && !de.isInteriorAreaEdge() && OverlayOp.isResultOfOp(label.getLocation(0, Position.RIGHT), label.getLocation(1, Position.RIGHT), opCode)) {
  37475. de.setInResult(true);
  37476. }
  37477. }
  37478. };
  37479. OverlayOp.prototype.computeLabelsFromDepths = function computeLabelsFromDepths () {
  37480. for (var it = this._edgeList.iterator(); it.hasNext();) {
  37481. var e = it.next();
  37482. var lbl = e.getLabel();
  37483. var depth = e.getDepth();
  37484. if (!depth.isNull()) {
  37485. depth.normalize();
  37486. for (var i = 0; i < 2; i++) {
  37487. if (!lbl.isNull(i) && lbl.isArea() && !depth.isNull(i)) {
  37488. if (depth.getDelta(i) === 0) {
  37489. lbl.toLine(i);
  37490. } else {
  37491. Assert.isTrue(!depth.isNull(i, Position.LEFT), 'depth of LEFT side has not been initialized');
  37492. lbl.setLocation(i, Position.LEFT, depth.getLocation(i, Position.LEFT));
  37493. Assert.isTrue(!depth.isNull(i, Position.RIGHT), 'depth of RIGHT side has not been initialized');
  37494. lbl.setLocation(i, Position.RIGHT, depth.getLocation(i, Position.RIGHT));
  37495. }
  37496. }
  37497. }
  37498. }
  37499. }
  37500. };
  37501. OverlayOp.prototype.computeLabelling = function computeLabelling () {
  37502. var this$1 = this;
  37503. for (var nodeit = this._graph.getNodes().iterator(); nodeit.hasNext();) {
  37504. var node = nodeit.next();
  37505. node.getEdges().computeLabelling(this$1._arg);
  37506. }
  37507. this.mergeSymLabels();
  37508. this.updateNodeLabelling();
  37509. };
  37510. OverlayOp.prototype.labelIncompleteNodes = function labelIncompleteNodes () {
  37511. var this$1 = this;
  37512. // let nodeCount = 0
  37513. for (var ni = this._graph.getNodes().iterator(); ni.hasNext();) {
  37514. var n = ni.next();
  37515. var label = n.getLabel();
  37516. if (n.isIsolated()) {
  37517. // nodeCount++
  37518. if (label.isNull(0)) { this$1.labelIncompleteNode(n, 0); } else { this$1.labelIncompleteNode(n, 1); }
  37519. }
  37520. n.getEdges().updateLabelling(label);
  37521. }
  37522. };
  37523. OverlayOp.prototype.isCoveredByA = function isCoveredByA (coord) {
  37524. if (this.isCovered(coord, this._resultPolyList)) { return true }
  37525. return false
  37526. };
  37527. OverlayOp.prototype.interfaces_ = function interfaces_ () {
  37528. return []
  37529. };
  37530. OverlayOp.prototype.getClass = function getClass () {
  37531. return OverlayOp
  37532. };
  37533. return OverlayOp;
  37534. }(GeometryGraphOp));
  37535. OverlayOp.overlayOp = function (geom0, geom1, opCode) {
  37536. var gov = new OverlayOp(geom0, geom1);
  37537. var geomOv = gov.getResultGeometry(opCode);
  37538. return geomOv
  37539. };
  37540. OverlayOp.intersection = function (g, other) {
  37541. if (g.isEmpty() || other.isEmpty()) { return OverlayOp.createEmptyResult(OverlayOp.INTERSECTION, g, other, g.getFactory()) }
  37542. if (g.isGeometryCollection()) {
  37543. var g2 = other;
  37544. return GeometryCollectionMapper.map(g, {
  37545. interfaces_: function () {
  37546. return [GeometryMapper.MapOp]
  37547. },
  37548. map: function (g) {
  37549. return g.intersection(g2)
  37550. }
  37551. })
  37552. }
  37553. g.checkNotGeometryCollection(g);
  37554. g.checkNotGeometryCollection(other);
  37555. return SnapIfNeededOverlayOp.overlayOp(g, other, OverlayOp.INTERSECTION)
  37556. };
  37557. OverlayOp.symDifference = function (g, other) {
  37558. if (g.isEmpty() || other.isEmpty()) {
  37559. if (g.isEmpty() && other.isEmpty()) { return OverlayOp.createEmptyResult(OverlayOp.SYMDIFFERENCE, g, other, g.getFactory()) }
  37560. if (g.isEmpty()) { return other.copy() }
  37561. if (other.isEmpty()) { return g.copy() }
  37562. }
  37563. g.checkNotGeometryCollection(g);
  37564. g.checkNotGeometryCollection(other);
  37565. return SnapIfNeededOverlayOp.overlayOp(g, other, OverlayOp.SYMDIFFERENCE)
  37566. };
  37567. OverlayOp.resultDimension = function (opCode, g0, g1) {
  37568. var dim0 = g0.getDimension();
  37569. var dim1 = g1.getDimension();
  37570. var resultDimension = -1;
  37571. switch (opCode) {
  37572. case OverlayOp.INTERSECTION:
  37573. resultDimension = Math.min(dim0, dim1);
  37574. break
  37575. case OverlayOp.UNION:
  37576. resultDimension = Math.max(dim0, dim1);
  37577. break
  37578. case OverlayOp.DIFFERENCE:
  37579. resultDimension = dim0;
  37580. break
  37581. case OverlayOp.SYMDIFFERENCE:
  37582. resultDimension = Math.max(dim0, dim1);
  37583. break
  37584. default:
  37585. }
  37586. return resultDimension
  37587. };
  37588. OverlayOp.createEmptyResult = function (overlayOpCode, a, b, geomFact) {
  37589. var result = null;
  37590. switch (OverlayOp.resultDimension(overlayOpCode, a, b)) {
  37591. case -1:
  37592. result = geomFact.createGeometryCollection(new Array(0).fill(null));
  37593. break
  37594. case 0:
  37595. result = geomFact.createPoint();
  37596. break
  37597. case 1:
  37598. result = geomFact.createLineString();
  37599. break
  37600. case 2:
  37601. result = geomFact.createPolygon();
  37602. break
  37603. default:
  37604. }
  37605. return result
  37606. };
  37607. OverlayOp.difference = function (g, other) {
  37608. if (g.isEmpty()) { return OverlayOp.createEmptyResult(OverlayOp.DIFFERENCE, g, other, g.getFactory()) }
  37609. if (other.isEmpty()) { return g.copy() }
  37610. g.checkNotGeometryCollection(g);
  37611. g.checkNotGeometryCollection(other);
  37612. return SnapIfNeededOverlayOp.overlayOp(g, other, OverlayOp.DIFFERENCE)
  37613. };
  37614. OverlayOp.isResultOfOp = function () {
  37615. if (arguments.length === 2) {
  37616. var label = arguments[0];
  37617. var opCode = arguments[1];
  37618. var loc0 = label.getLocation(0);
  37619. var loc1 = label.getLocation(1);
  37620. return OverlayOp.isResultOfOp(loc0, loc1, opCode)
  37621. } else if (arguments.length === 3) {
  37622. var loc0$1 = arguments[0];
  37623. var loc1$1 = arguments[1];
  37624. var overlayOpCode = arguments[2];
  37625. if (loc0$1 === Location.BOUNDARY) { loc0$1 = Location.INTERIOR; }
  37626. if (loc1$1 === Location.BOUNDARY) { loc1$1 = Location.INTERIOR; }
  37627. switch (overlayOpCode) {
  37628. case OverlayOp.INTERSECTION:
  37629. return loc0$1 === Location.INTERIOR && loc1$1 === Location.INTERIOR
  37630. case OverlayOp.UNION:
  37631. return loc0$1 === Location.INTERIOR || loc1$1 === Location.INTERIOR
  37632. case OverlayOp.DIFFERENCE:
  37633. return loc0$1 === Location.INTERIOR && loc1$1 !== Location.INTERIOR
  37634. case OverlayOp.SYMDIFFERENCE:
  37635. return (loc0$1 === Location.INTERIOR && loc1$1 !== Location.INTERIOR) || (loc0$1 !== Location.INTERIOR && loc1$1 === Location.INTERIOR)
  37636. default:
  37637. }
  37638. return false
  37639. }
  37640. };
  37641. OverlayOp.INTERSECTION = 1;
  37642. OverlayOp.UNION = 2;
  37643. OverlayOp.DIFFERENCE = 3;
  37644. OverlayOp.SYMDIFFERENCE = 4;
  37645. var FuzzyPointLocator = function FuzzyPointLocator () {
  37646. this._g = null;
  37647. this._boundaryDistanceTolerance = null;
  37648. this._linework = null;
  37649. this._ptLocator = new PointLocator();
  37650. this._seg = new LineSegment();
  37651. var g = arguments[0];
  37652. var boundaryDistanceTolerance = arguments[1];
  37653. this._g = g;
  37654. this._boundaryDistanceTolerance = boundaryDistanceTolerance;
  37655. this._linework = this.extractLinework(g);
  37656. };
  37657. FuzzyPointLocator.prototype.isWithinToleranceOfBoundary = function isWithinToleranceOfBoundary (pt) {
  37658. var this$1 = this;
  37659. for (var i = 0; i < this._linework.getNumGeometries(); i++) {
  37660. var line = this$1._linework.getGeometryN(i);
  37661. var seq = line.getCoordinateSequence();
  37662. for (var j = 0; j < seq.size() - 1; j++) {
  37663. seq.getCoordinate(j, this$1._seg.p0);
  37664. seq.getCoordinate(j + 1, this$1._seg.p1);
  37665. var dist = this$1._seg.distance(pt);
  37666. if (dist <= this$1._boundaryDistanceTolerance) { return true }
  37667. }
  37668. }
  37669. return false
  37670. };
  37671. FuzzyPointLocator.prototype.getLocation = function getLocation (pt) {
  37672. if (this.isWithinToleranceOfBoundary(pt)) { return Location.BOUNDARY }
  37673. return this._ptLocator.locate(pt, this._g)
  37674. };
  37675. FuzzyPointLocator.prototype.extractLinework = function extractLinework (g) {
  37676. var extracter = new PolygonalLineworkExtracter();
  37677. g.apply(extracter);
  37678. var linework = extracter.getLinework();
  37679. var lines = GeometryFactory.toLineStringArray(linework);
  37680. return g.getFactory().createMultiLineString(lines)
  37681. };
  37682. FuzzyPointLocator.prototype.interfaces_ = function interfaces_ () {
  37683. return []
  37684. };
  37685. FuzzyPointLocator.prototype.getClass = function getClass () {
  37686. return FuzzyPointLocator
  37687. };
  37688. var PolygonalLineworkExtracter = function PolygonalLineworkExtracter () {
  37689. this._linework = null;
  37690. this._linework = new ArrayList();
  37691. };
  37692. PolygonalLineworkExtracter.prototype.getLinework = function getLinework () {
  37693. return this._linework
  37694. };
  37695. PolygonalLineworkExtracter.prototype.filter = function filter (g) {
  37696. var this$1 = this;
  37697. if (g instanceof Polygon) {
  37698. var poly = g;
  37699. this._linework.add(poly.getExteriorRing());
  37700. for (var i = 0; i < poly.getNumInteriorRing(); i++) {
  37701. this$1._linework.add(poly.getInteriorRingN(i));
  37702. }
  37703. }
  37704. };
  37705. PolygonalLineworkExtracter.prototype.interfaces_ = function interfaces_ () {
  37706. return [GeometryFilter]
  37707. };
  37708. PolygonalLineworkExtracter.prototype.getClass = function getClass () {
  37709. return PolygonalLineworkExtracter
  37710. };
  37711. var OffsetPointGenerator = function OffsetPointGenerator () {
  37712. this._g = null;
  37713. this._doLeft = true;
  37714. this._doRight = true;
  37715. var g = arguments[0];
  37716. this._g = g;
  37717. };
  37718. OffsetPointGenerator.prototype.extractPoints = function extractPoints (line, offsetDistance, offsetPts) {
  37719. var this$1 = this;
  37720. var pts = line.getCoordinates();
  37721. for (var i = 0; i < pts.length - 1; i++) {
  37722. this$1.computeOffsetPoints(pts[i], pts[i + 1], offsetDistance, offsetPts);
  37723. }
  37724. };
  37725. OffsetPointGenerator.prototype.setSidesToGenerate = function setSidesToGenerate (doLeft, doRight) {
  37726. this._doLeft = doLeft;
  37727. this._doRight = doRight;
  37728. };
  37729. OffsetPointGenerator.prototype.getPoints = function getPoints (offsetDistance) {
  37730. var this$1 = this;
  37731. var offsetPts = new ArrayList();
  37732. var lines = LinearComponentExtracter.getLines(this._g);
  37733. for (var i = lines.iterator(); i.hasNext();) {
  37734. var line = i.next();
  37735. this$1.extractPoints(line, offsetDistance, offsetPts);
  37736. }
  37737. return offsetPts
  37738. };
  37739. OffsetPointGenerator.prototype.computeOffsetPoints = function computeOffsetPoints (p0, p1, offsetDistance, offsetPts) {
  37740. var dx = p1.x - p0.x;
  37741. var dy = p1.y - p0.y;
  37742. var len = Math.sqrt(dx * dx + dy * dy);
  37743. var ux = offsetDistance * dx / len;
  37744. var uy = offsetDistance * dy / len;
  37745. var midX = (p1.x + p0.x) / 2;
  37746. var midY = (p1.y + p0.y) / 2;
  37747. if (this._doLeft) {
  37748. var offsetLeft = new Coordinate(midX - uy, midY + ux);
  37749. offsetPts.add(offsetLeft);
  37750. }
  37751. if (this._doRight) {
  37752. var offsetRight = new Coordinate(midX + uy, midY - ux);
  37753. offsetPts.add(offsetRight);
  37754. }
  37755. };
  37756. OffsetPointGenerator.prototype.interfaces_ = function interfaces_ () {
  37757. return []
  37758. };
  37759. OffsetPointGenerator.prototype.getClass = function getClass () {
  37760. return OffsetPointGenerator
  37761. };
  37762. var OverlayResultValidator = function OverlayResultValidator () {
  37763. this._geom = null;
  37764. this._locFinder = null;
  37765. this._location = new Array(3).fill(null);
  37766. this._invalidLocation = null;
  37767. this._boundaryDistanceTolerance = OverlayResultValidator.TOLERANCE;
  37768. this._testCoords = new ArrayList();
  37769. var a = arguments[0];
  37770. var b = arguments[1];
  37771. var result = arguments[2];
  37772. this._boundaryDistanceTolerance = OverlayResultValidator.computeBoundaryDistanceTolerance(a, b);
  37773. this._geom = [a, b, result];
  37774. this._locFinder = [new FuzzyPointLocator(this._geom[0], this._boundaryDistanceTolerance), new FuzzyPointLocator(this._geom[1], this._boundaryDistanceTolerance), new FuzzyPointLocator(this._geom[2], this._boundaryDistanceTolerance)];
  37775. };
  37776. var staticAccessors$46 = { TOLERANCE: { configurable: true } };
  37777. OverlayResultValidator.prototype.reportResult = function reportResult (overlayOp, location, expectedInterior) {
  37778. System.out.println('Overlay result invalid - A:' + Location.toLocationSymbol(location[0]) + ' B:' + Location.toLocationSymbol(location[1]) + ' expected:' + (expectedInterior ? 'i' : 'e') + ' actual:' + Location.toLocationSymbol(location[2]));
  37779. };
  37780. OverlayResultValidator.prototype.isValid = function isValid (overlayOp) {
  37781. this.addTestPts(this._geom[0]);
  37782. this.addTestPts(this._geom[1]);
  37783. var isValid = this.checkValid(overlayOp);
  37784. return isValid
  37785. };
  37786. OverlayResultValidator.prototype.checkValid = function checkValid () {
  37787. var this$1 = this;
  37788. if (arguments.length === 1) {
  37789. var overlayOp = arguments[0];
  37790. for (var i = 0; i < this._testCoords.size(); i++) {
  37791. var pt = this$1._testCoords.get(i);
  37792. if (!this$1.checkValid(overlayOp, pt)) {
  37793. this$1._invalidLocation = pt;
  37794. return false
  37795. }
  37796. }
  37797. return true
  37798. } else if (arguments.length === 2) {
  37799. var overlayOp$1 = arguments[0];
  37800. var pt$1 = arguments[1];
  37801. this._location[0] = this._locFinder[0].getLocation(pt$1);
  37802. this._location[1] = this._locFinder[1].getLocation(pt$1);
  37803. this._location[2] = this._locFinder[2].getLocation(pt$1);
  37804. if (OverlayResultValidator.hasLocation(this._location, Location.BOUNDARY)) { return true }
  37805. return this.isValidResult(overlayOp$1, this._location)
  37806. }
  37807. };
  37808. OverlayResultValidator.prototype.addTestPts = function addTestPts (g) {
  37809. var ptGen = new OffsetPointGenerator(g);
  37810. this._testCoords.addAll(ptGen.getPoints(5 * this._boundaryDistanceTolerance));
  37811. };
  37812. OverlayResultValidator.prototype.isValidResult = function isValidResult (overlayOp, location) {
  37813. var expectedInterior = OverlayOp.isResultOfOp(location[0], location[1], overlayOp);
  37814. var resultInInterior = location[2] === Location.INTERIOR;
  37815. var isValid = !(expectedInterior ^ resultInInterior);
  37816. if (!isValid) { this.reportResult(overlayOp, location, expectedInterior); }
  37817. return isValid
  37818. };
  37819. OverlayResultValidator.prototype.getInvalidLocation = function getInvalidLocation () {
  37820. return this._invalidLocation
  37821. };
  37822. OverlayResultValidator.prototype.interfaces_ = function interfaces_ () {
  37823. return []
  37824. };
  37825. OverlayResultValidator.prototype.getClass = function getClass () {
  37826. return OverlayResultValidator
  37827. };
  37828. OverlayResultValidator.hasLocation = function hasLocation (location, loc) {
  37829. for (var i = 0; i < 3; i++) {
  37830. if (location[i] === loc) { return true }
  37831. }
  37832. return false
  37833. };
  37834. OverlayResultValidator.computeBoundaryDistanceTolerance = function computeBoundaryDistanceTolerance (g0, g1) {
  37835. return Math.min(GeometrySnapper.computeSizeBasedSnapTolerance(g0), GeometrySnapper.computeSizeBasedSnapTolerance(g1))
  37836. };
  37837. OverlayResultValidator.isValid = function isValid (a, b, overlayOp, result) {
  37838. var validator = new OverlayResultValidator(a, b, result);
  37839. return validator.isValid(overlayOp)
  37840. };
  37841. staticAccessors$46.TOLERANCE.get = function () { return 0.000001 };
  37842. Object.defineProperties( OverlayResultValidator, staticAccessors$46 );
  37843. // operation.overlay
  37844. var GeometryCombiner = function GeometryCombiner (geoms) {
  37845. this._geomFactory = null;
  37846. this._skipEmpty = false;
  37847. this._inputGeoms = null;
  37848. this._geomFactory = GeometryCombiner.extractFactory(geoms);
  37849. this._inputGeoms = geoms;
  37850. };
  37851. GeometryCombiner.prototype.extractElements = function extractElements (geom, elems) {
  37852. var this$1 = this;
  37853. if (geom === null) { return null }
  37854. for (var i = 0; i < geom.getNumGeometries(); i++) {
  37855. var elemGeom = geom.getGeometryN(i);
  37856. if (this$1._skipEmpty && elemGeom.isEmpty()) { continue }
  37857. elems.add(elemGeom);
  37858. }
  37859. };
  37860. GeometryCombiner.prototype.combine = function combine () {
  37861. var this$1 = this;
  37862. var elems = new ArrayList();
  37863. for (var i = this._inputGeoms.iterator(); i.hasNext();) {
  37864. var g = i.next();
  37865. this$1.extractElements(g, elems);
  37866. }
  37867. if (elems.size() === 0) {
  37868. if (this._geomFactory !== null) {
  37869. return this._geomFactory.createGeometryCollection(null)
  37870. }
  37871. return null
  37872. }
  37873. return this._geomFactory.buildGeometry(elems)
  37874. };
  37875. GeometryCombiner.prototype.interfaces_ = function interfaces_ () {
  37876. return []
  37877. };
  37878. GeometryCombiner.prototype.getClass = function getClass () {
  37879. return GeometryCombiner
  37880. };
  37881. GeometryCombiner.combine = function combine () {
  37882. if (arguments.length === 1) {
  37883. var geoms = arguments[0];
  37884. var combiner = new GeometryCombiner(geoms);
  37885. return combiner.combine()
  37886. } else if (arguments.length === 2) {
  37887. var g0 = arguments[0];
  37888. var g1 = arguments[1];
  37889. var combiner$1 = new GeometryCombiner(GeometryCombiner.createList(g0, g1));
  37890. return combiner$1.combine()
  37891. } else if (arguments.length === 3) {
  37892. var g0$1 = arguments[0];
  37893. var g1$1 = arguments[1];
  37894. var g2 = arguments[2];
  37895. var combiner$2 = new GeometryCombiner(GeometryCombiner.createList(g0$1, g1$1, g2));
  37896. return combiner$2.combine()
  37897. }
  37898. };
  37899. GeometryCombiner.extractFactory = function extractFactory (geoms) {
  37900. if (geoms.isEmpty()) { return null }
  37901. return geoms.iterator().next().getFactory()
  37902. };
  37903. GeometryCombiner.createList = function createList () {
  37904. if (arguments.length === 2) {
  37905. var obj0 = arguments[0];
  37906. var obj1 = arguments[1];
  37907. var list = new ArrayList();
  37908. list.add(obj0);
  37909. list.add(obj1);
  37910. return list
  37911. } else if (arguments.length === 3) {
  37912. var obj0$1 = arguments[0];
  37913. var obj1$1 = arguments[1];
  37914. var obj2 = arguments[2];
  37915. var list$1 = new ArrayList();
  37916. list$1.add(obj0$1);
  37917. list$1.add(obj1$1);
  37918. list$1.add(obj2);
  37919. return list$1
  37920. }
  37921. };
  37922. var CascadedPolygonUnion = function CascadedPolygonUnion () {
  37923. this._inputPolys = null;
  37924. this._geomFactory = null;
  37925. var polys = arguments[0];
  37926. this._inputPolys = polys;
  37927. if (this._inputPolys === null) { this._inputPolys = new ArrayList(); }
  37928. };
  37929. var staticAccessors$47 = { STRTREE_NODE_CAPACITY: { configurable: true } };
  37930. CascadedPolygonUnion.prototype.reduceToGeometries = function reduceToGeometries (geomTree) {
  37931. var this$1 = this;
  37932. var geoms = new ArrayList();
  37933. for (var i = geomTree.iterator(); i.hasNext();) {
  37934. var o = i.next();
  37935. var geom = null;
  37936. if (hasInterface(o, List)) {
  37937. geom = this$1.unionTree(o);
  37938. } else if (o instanceof Geometry) {
  37939. geom = o;
  37940. }
  37941. geoms.add(geom);
  37942. }
  37943. return geoms
  37944. };
  37945. CascadedPolygonUnion.prototype.extractByEnvelope = function extractByEnvelope (env, geom, disjointGeoms) {
  37946. var intersectingGeoms = new ArrayList();
  37947. for (var i = 0; i < geom.getNumGeometries(); i++) {
  37948. var elem = geom.getGeometryN(i);
  37949. if (elem.getEnvelopeInternal().intersects(env)) { intersectingGeoms.add(elem); } else { disjointGeoms.add(elem); }
  37950. }
  37951. return this._geomFactory.buildGeometry(intersectingGeoms)
  37952. };
  37953. CascadedPolygonUnion.prototype.unionOptimized = function unionOptimized (g0, g1) {
  37954. var g0Env = g0.getEnvelopeInternal();
  37955. var g1Env = g1.getEnvelopeInternal();
  37956. if (!g0Env.intersects(g1Env)) {
  37957. var combo = GeometryCombiner.combine(g0, g1);
  37958. return combo
  37959. }
  37960. if (g0.getNumGeometries() <= 1 && g1.getNumGeometries() <= 1) { return this.unionActual(g0, g1) }
  37961. var commonEnv = g0Env.intersection(g1Env);
  37962. return this.unionUsingEnvelopeIntersection(g0, g1, commonEnv)
  37963. };
  37964. CascadedPolygonUnion.prototype.union = function union () {
  37965. if (this._inputPolys === null) { throw new Error('union() method cannot be called twice') }
  37966. if (this._inputPolys.isEmpty()) { return null }
  37967. this._geomFactory = this._inputPolys.iterator().next().getFactory();
  37968. var index = new STRtree(CascadedPolygonUnion.STRTREE_NODE_CAPACITY);
  37969. for (var i = this._inputPolys.iterator(); i.hasNext();) {
  37970. var item = i.next();
  37971. index.insert(item.getEnvelopeInternal(), item);
  37972. }
  37973. this._inputPolys = null;
  37974. var itemTree = index.itemsTree();
  37975. var unionAll = this.unionTree(itemTree);
  37976. return unionAll
  37977. };
  37978. CascadedPolygonUnion.prototype.binaryUnion = function binaryUnion () {
  37979. if (arguments.length === 1) {
  37980. var geoms = arguments[0];
  37981. return this.binaryUnion(geoms, 0, geoms.size())
  37982. } else if (arguments.length === 3) {
  37983. var geoms$1 = arguments[0];
  37984. var start = arguments[1];
  37985. var end = arguments[2];
  37986. if (end - start <= 1) {
  37987. var g0 = CascadedPolygonUnion.getGeometry(geoms$1, start);
  37988. return this.unionSafe(g0, null)
  37989. } else if (end - start === 2) {
  37990. return this.unionSafe(CascadedPolygonUnion.getGeometry(geoms$1, start), CascadedPolygonUnion.getGeometry(geoms$1, start + 1))
  37991. } else {
  37992. var mid = Math.trunc((end + start) / 2);
  37993. var g0$1 = this.binaryUnion(geoms$1, start, mid);
  37994. var g1 = this.binaryUnion(geoms$1, mid, end);
  37995. return this.unionSafe(g0$1, g1)
  37996. }
  37997. }
  37998. };
  37999. CascadedPolygonUnion.prototype.repeatedUnion = function repeatedUnion (geoms) {
  38000. var union = null;
  38001. for (var i = geoms.iterator(); i.hasNext();) {
  38002. var g = i.next();
  38003. if (union === null) { union = g.copy(); } else { union = union.union(g); }
  38004. }
  38005. return union
  38006. };
  38007. CascadedPolygonUnion.prototype.unionSafe = function unionSafe (g0, g1) {
  38008. if (g0 === null && g1 === null) { return null }
  38009. if (g0 === null) { return g1.copy() }
  38010. if (g1 === null) { return g0.copy() }
  38011. return this.unionOptimized(g0, g1)
  38012. };
  38013. CascadedPolygonUnion.prototype.unionActual = function unionActual (g0, g1) {
  38014. return CascadedPolygonUnion.restrictToPolygons(g0.union(g1))
  38015. };
  38016. CascadedPolygonUnion.prototype.unionTree = function unionTree (geomTree) {
  38017. var geoms = this.reduceToGeometries(geomTree);
  38018. var union = this.binaryUnion(geoms);
  38019. return union
  38020. };
  38021. CascadedPolygonUnion.prototype.unionUsingEnvelopeIntersection = function unionUsingEnvelopeIntersection (g0, g1, common) {
  38022. var disjointPolys = new ArrayList();
  38023. var g0Int = this.extractByEnvelope(common, g0, disjointPolys);
  38024. var g1Int = this.extractByEnvelope(common, g1, disjointPolys);
  38025. var union = this.unionActual(g0Int, g1Int);
  38026. disjointPolys.add(union);
  38027. var overallUnion = GeometryCombiner.combine(disjointPolys);
  38028. return overallUnion
  38029. };
  38030. CascadedPolygonUnion.prototype.bufferUnion = function bufferUnion () {
  38031. if (arguments.length === 1) {
  38032. var geoms = arguments[0];
  38033. var factory = geoms.get(0).getFactory();
  38034. var gColl = factory.buildGeometry(geoms);
  38035. var unionAll = gColl.buffer(0.0);
  38036. return unionAll
  38037. } else if (arguments.length === 2) {
  38038. var g0 = arguments[0];
  38039. var g1 = arguments[1];
  38040. var factory$1 = g0.getFactory();
  38041. var gColl$1 = factory$1.createGeometryCollection([g0, g1]);
  38042. var unionAll$1 = gColl$1.buffer(0.0);
  38043. return unionAll$1
  38044. }
  38045. };
  38046. CascadedPolygonUnion.prototype.interfaces_ = function interfaces_ () {
  38047. return []
  38048. };
  38049. CascadedPolygonUnion.prototype.getClass = function getClass () {
  38050. return CascadedPolygonUnion
  38051. };
  38052. CascadedPolygonUnion.restrictToPolygons = function restrictToPolygons (g) {
  38053. if (hasInterface(g, Polygonal)) {
  38054. return g
  38055. }
  38056. var polygons = PolygonExtracter.getPolygons(g);
  38057. if (polygons.size() === 1) { return polygons.get(0) }
  38058. return g.getFactory().createMultiPolygon(GeometryFactory.toPolygonArray(polygons))
  38059. };
  38060. CascadedPolygonUnion.getGeometry = function getGeometry (list, index) {
  38061. if (index >= list.size()) { return null }
  38062. return list.get(index)
  38063. };
  38064. CascadedPolygonUnion.union = function union (polys) {
  38065. var op = new CascadedPolygonUnion(polys);
  38066. return op.union()
  38067. };
  38068. staticAccessors$47.STRTREE_NODE_CAPACITY.get = function () { return 4 };
  38069. Object.defineProperties( CascadedPolygonUnion, staticAccessors$47 );
  38070. var UnionOp = function UnionOp () {};
  38071. UnionOp.prototype.interfaces_ = function interfaces_ () {
  38072. return []
  38073. };
  38074. UnionOp.prototype.getClass = function getClass () {
  38075. return UnionOp
  38076. };
  38077. UnionOp.union = function union (g, other) {
  38078. if (g.isEmpty() || other.isEmpty()) {
  38079. if (g.isEmpty() && other.isEmpty()) { return OverlayOp.createEmptyResult(OverlayOp.UNION, g, other, g.getFactory()) }
  38080. if (g.isEmpty()) { return other.copy() }
  38081. if (other.isEmpty()) { return g.copy() }
  38082. }
  38083. g.checkNotGeometryCollection(g);
  38084. g.checkNotGeometryCollection(other);
  38085. return SnapIfNeededOverlayOp.overlayOp(g, other, OverlayOp.UNION)
  38086. };
  38087. /**
  38088. * Finds the difference between two {@link Polygon|polygons} by clipping the second polygon from the first.
  38089. *
  38090. * @name difference
  38091. * @param {Feature<Polygon|MultiPolygon>} polygon1 input Polygon feature
  38092. * @param {Feature<Polygon|MultiPolygon>} polygon2 Polygon feature to difference from polygon1
  38093. * @returns {Feature<Polygon|MultiPolygon>|null} a Polygon or MultiPolygon feature showing the area of `polygon1` excluding the area of `polygon2` (if empty returns `null`)
  38094. * @example
  38095. * var polygon1 = turf.polygon([[
  38096. * [128, -26],
  38097. * [141, -26],
  38098. * [141, -21],
  38099. * [128, -21],
  38100. * [128, -26]
  38101. * ]], {
  38102. * "fill": "#F00",
  38103. * "fill-opacity": 0.1
  38104. * });
  38105. * var polygon2 = turf.polygon([[
  38106. * [126, -28],
  38107. * [140, -28],
  38108. * [140, -20],
  38109. * [126, -20],
  38110. * [126, -28]
  38111. * ]], {
  38112. * "fill": "#00F",
  38113. * "fill-opacity": 0.1
  38114. * });
  38115. *
  38116. * var difference = turf.difference(polygon1, polygon2);
  38117. *
  38118. * //addToMap
  38119. * var addToMap = [polygon1, polygon2, difference];
  38120. */
  38121. function difference(polygon1, polygon2) {
  38122. var geom1 = getGeom(polygon1);
  38123. var geom2 = getGeom(polygon2);
  38124. var properties = polygon1.properties || {};
  38125. // Issue #721 - JSTS can't handle empty polygons
  38126. geom1 = removeEmptyPolygon(geom1);
  38127. geom2 = removeEmptyPolygon(geom2);
  38128. if (!geom1) return null;
  38129. if (!geom2) return feature(geom1, properties);
  38130. // JSTS difference operation
  38131. var reader = new GeoJSONReader();
  38132. var a = reader.read(geom1);
  38133. var b = reader.read(geom2);
  38134. var differenced = OverlayOp.difference(a, b);
  38135. if (differenced.isEmpty()) return null;
  38136. var writer = new GeoJSONWriter();
  38137. var geom = writer.write(differenced);
  38138. return feature(geom, properties);
  38139. }
  38140. /**
  38141. * Detect Empty Polygon
  38142. *
  38143. * @private
  38144. * @param {Geometry<Polygon|MultiPolygon>} geom Geometry Object
  38145. * @returns {Geometry<Polygon|MultiPolygon>|null} removed any polygons with no areas
  38146. */
  38147. function removeEmptyPolygon(geom) {
  38148. switch (geom.type) {
  38149. case 'Polygon':
  38150. if (area$1(geom) > 1) return geom;
  38151. return null;
  38152. case 'MultiPolygon':
  38153. var coordinates = [];
  38154. flattenEach(geom, function (feature$$1) {
  38155. if (area$1(feature$$1) > 1) coordinates.push(feature$$1.geometry.coordinates);
  38156. });
  38157. if (coordinates.length) return {type: 'MultiPolygon', coordinates: coordinates};
  38158. }
  38159. }
  38160. // Adds floating point numbers with twice the normal precision.
  38161. // Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and
  38162. // Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3)
  38163. // 305–363 (1997).
  38164. // Code adapted from GeographicLib by Charles F. F. Karney,
  38165. // http://geographiclib.sourceforge.net/
  38166. var adder = function() {
  38167. return new Adder;
  38168. };
  38169. function Adder() {
  38170. this.reset();
  38171. }
  38172. Adder.prototype = {
  38173. constructor: Adder,
  38174. reset: function() {
  38175. this.s = // rounded value
  38176. this.t = 0; // exact error
  38177. },
  38178. add: function(y) {
  38179. add$1(temp, y, this.t);
  38180. add$1(this, temp.s, this.s);
  38181. if (this.s) this.t += temp.t;
  38182. else this.s = temp.t;
  38183. },
  38184. valueOf: function() {
  38185. return this.s;
  38186. }
  38187. };
  38188. var temp = new Adder;
  38189. function add$1(adder, a, b) {
  38190. var x = adder.s = a + b,
  38191. bv = x - a,
  38192. av = x - bv;
  38193. adder.t = (a - av) + (b - bv);
  38194. }
  38195. var epsilon$1 = 1e-6;
  38196. var pi = Math.PI;
  38197. var halfPi = pi / 2;
  38198. var quarterPi = pi / 4;
  38199. var tau = pi * 2;
  38200. var degrees = 180 / pi;
  38201. var radians = pi / 180;
  38202. var abs = Math.abs;
  38203. var atan = Math.atan;
  38204. var atan2 = Math.atan2;
  38205. var cos = Math.cos;
  38206. var exp = Math.exp;
  38207. var log = Math.log;
  38208. var sin = Math.sin;
  38209. var sqrt = Math.sqrt;
  38210. var tan = Math.tan;
  38211. function acos(x) {
  38212. return x > 1 ? 0 : x < -1 ? pi : Math.acos(x);
  38213. }
  38214. function asin(x) {
  38215. return x > 1 ? halfPi : x < -1 ? -halfPi : Math.asin(x);
  38216. }
  38217. function noop() {}
  38218. function streamGeometry(geometry, stream) {
  38219. if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {
  38220. streamGeometryType[geometry.type](geometry, stream);
  38221. }
  38222. }
  38223. var streamObjectType = {
  38224. Feature: function(object, stream) {
  38225. streamGeometry(object.geometry, stream);
  38226. },
  38227. FeatureCollection: function(object, stream) {
  38228. var features = object.features, i = -1, n = features.length;
  38229. while (++i < n) streamGeometry(features[i].geometry, stream);
  38230. }
  38231. };
  38232. var streamGeometryType = {
  38233. Sphere: function(object, stream) {
  38234. stream.sphere();
  38235. },
  38236. Point: function(object, stream) {
  38237. object = object.coordinates;
  38238. stream.point(object[0], object[1], object[2]);
  38239. },
  38240. MultiPoint: function(object, stream) {
  38241. var coordinates = object.coordinates, i = -1, n = coordinates.length;
  38242. while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]);
  38243. },
  38244. LineString: function(object, stream) {
  38245. streamLine(object.coordinates, stream, 0);
  38246. },
  38247. MultiLineString: function(object, stream) {
  38248. var coordinates = object.coordinates, i = -1, n = coordinates.length;
  38249. while (++i < n) streamLine(coordinates[i], stream, 0);
  38250. },
  38251. Polygon: function(object, stream) {
  38252. streamPolygon(object.coordinates, stream);
  38253. },
  38254. MultiPolygon: function(object, stream) {
  38255. var coordinates = object.coordinates, i = -1, n = coordinates.length;
  38256. while (++i < n) streamPolygon(coordinates[i], stream);
  38257. },
  38258. GeometryCollection: function(object, stream) {
  38259. var geometries = object.geometries, i = -1, n = geometries.length;
  38260. while (++i < n) streamGeometry(geometries[i], stream);
  38261. }
  38262. };
  38263. function streamLine(coordinates, stream, closed) {
  38264. var i = -1, n = coordinates.length - closed, coordinate;
  38265. stream.lineStart();
  38266. while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);
  38267. stream.lineEnd();
  38268. }
  38269. function streamPolygon(coordinates, stream) {
  38270. var i = -1, n = coordinates.length;
  38271. stream.polygonStart();
  38272. while (++i < n) streamLine(coordinates[i], stream, 1);
  38273. stream.polygonEnd();
  38274. }
  38275. var geoStream = function(object, stream) {
  38276. if (object && streamObjectType.hasOwnProperty(object.type)) {
  38277. streamObjectType[object.type](object, stream);
  38278. } else {
  38279. streamGeometry(object, stream);
  38280. }
  38281. };
  38282. var areaRingSum = adder();
  38283. var areaSum = adder();
  38284. function spherical(cartesian) {
  38285. return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])];
  38286. }
  38287. function cartesian(spherical) {
  38288. var lambda = spherical[0], phi = spherical[1], cosPhi = cos(phi);
  38289. return [cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi)];
  38290. }
  38291. function cartesianDot(a, b) {
  38292. return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
  38293. }
  38294. function cartesianCross(a, b) {
  38295. return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
  38296. }
  38297. // TODO return a
  38298. function cartesianAddInPlace(a, b) {
  38299. a[0] += b[0], a[1] += b[1], a[2] += b[2];
  38300. }
  38301. function cartesianScale(vector, k) {
  38302. return [vector[0] * k, vector[1] * k, vector[2] * k];
  38303. }
  38304. // TODO return d
  38305. function cartesianNormalizeInPlace(d) {
  38306. var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
  38307. d[0] /= l, d[1] /= l, d[2] /= l;
  38308. }
  38309. var deltaSum = adder();
  38310. var compose = function(a, b) {
  38311. function compose(x, y) {
  38312. return x = a(x, y), b(x[0], x[1]);
  38313. }
  38314. if (a.invert && b.invert) compose.invert = function(x, y) {
  38315. return x = b.invert(x, y), x && a.invert(x[0], x[1]);
  38316. };
  38317. return compose;
  38318. };
  38319. function rotationIdentity(lambda, phi) {
  38320. return [lambda > pi ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi];
  38321. }
  38322. rotationIdentity.invert = rotationIdentity;
  38323. function rotateRadians(deltaLambda, deltaPhi, deltaGamma) {
  38324. return (deltaLambda %= tau) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma))
  38325. : rotationLambda(deltaLambda))
  38326. : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma)
  38327. : rotationIdentity);
  38328. }
  38329. function forwardRotationLambda(deltaLambda) {
  38330. return function(lambda, phi) {
  38331. return lambda += deltaLambda, [lambda > pi ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi];
  38332. };
  38333. }
  38334. function rotationLambda(deltaLambda) {
  38335. var rotation = forwardRotationLambda(deltaLambda);
  38336. rotation.invert = forwardRotationLambda(-deltaLambda);
  38337. return rotation;
  38338. }
  38339. function rotationPhiGamma(deltaPhi, deltaGamma) {
  38340. var cosDeltaPhi = cos(deltaPhi),
  38341. sinDeltaPhi = sin(deltaPhi),
  38342. cosDeltaGamma = cos(deltaGamma),
  38343. sinDeltaGamma = sin(deltaGamma);
  38344. function rotation(lambda, phi) {
  38345. var cosPhi = cos(phi),
  38346. x = cos(lambda) * cosPhi,
  38347. y = sin(lambda) * cosPhi,
  38348. z = sin(phi),
  38349. k = z * cosDeltaPhi + x * sinDeltaPhi;
  38350. return [
  38351. atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi),
  38352. asin(k * cosDeltaGamma + y * sinDeltaGamma)
  38353. ];
  38354. }
  38355. rotation.invert = function(lambda, phi) {
  38356. var cosPhi = cos(phi),
  38357. x = cos(lambda) * cosPhi,
  38358. y = sin(lambda) * cosPhi,
  38359. z = sin(phi),
  38360. k = z * cosDeltaGamma - y * sinDeltaGamma;
  38361. return [
  38362. atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi),
  38363. asin(k * cosDeltaPhi - x * sinDeltaPhi)
  38364. ];
  38365. };
  38366. return rotation;
  38367. }
  38368. var rotation = function(rotate) {
  38369. rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0);
  38370. function forward(coordinates) {
  38371. coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians);
  38372. return coordinates[0] *= degrees, coordinates[1] *= degrees, coordinates;
  38373. }
  38374. forward.invert = function(coordinates) {
  38375. coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians);
  38376. return coordinates[0] *= degrees, coordinates[1] *= degrees, coordinates;
  38377. };
  38378. return forward;
  38379. };
  38380. // Generates a circle centered at [0°, 0°], with a given radius and precision.
  38381. function circleStream(stream, radius, delta, direction, t0, t1) {
  38382. if (!delta) return;
  38383. var cosRadius = cos(radius),
  38384. sinRadius = sin(radius),
  38385. step = direction * delta;
  38386. if (t0 == null) {
  38387. t0 = radius + direction * tau;
  38388. t1 = radius - step / 2;
  38389. } else {
  38390. t0 = circleRadius(cosRadius, t0);
  38391. t1 = circleRadius(cosRadius, t1);
  38392. if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau;
  38393. }
  38394. for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) {
  38395. point = spherical([cosRadius, -sinRadius * cos(t), -sinRadius * sin(t)]);
  38396. stream.point(point[0], point[1]);
  38397. }
  38398. }
  38399. // Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0].
  38400. function circleRadius(cosRadius, point) {
  38401. point = cartesian(point), point[0] -= cosRadius;
  38402. cartesianNormalizeInPlace(point);
  38403. var radius = acos(-point[1]);
  38404. return ((-point[2] < 0 ? -radius : radius) + tau - epsilon$1) % tau;
  38405. }
  38406. var clipBuffer = function() {
  38407. var lines = [],
  38408. line;
  38409. return {
  38410. point: function(x, y) {
  38411. line.push([x, y]);
  38412. },
  38413. lineStart: function() {
  38414. lines.push(line = []);
  38415. },
  38416. lineEnd: noop,
  38417. rejoin: function() {
  38418. if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
  38419. },
  38420. result: function() {
  38421. var result = lines;
  38422. lines = [];
  38423. line = null;
  38424. return result;
  38425. }
  38426. };
  38427. };
  38428. var clipLine = function(a, b, x0, y0, x1, y1) {
  38429. var ax = a[0],
  38430. ay = a[1],
  38431. bx = b[0],
  38432. by = b[1],
  38433. t0 = 0,
  38434. t1 = 1,
  38435. dx = bx - ax,
  38436. dy = by - ay,
  38437. r;
  38438. r = x0 - ax;
  38439. if (!dx && r > 0) return;
  38440. r /= dx;
  38441. if (dx < 0) {
  38442. if (r < t0) return;
  38443. if (r < t1) t1 = r;
  38444. } else if (dx > 0) {
  38445. if (r > t1) return;
  38446. if (r > t0) t0 = r;
  38447. }
  38448. r = x1 - ax;
  38449. if (!dx && r < 0) return;
  38450. r /= dx;
  38451. if (dx < 0) {
  38452. if (r > t1) return;
  38453. if (r > t0) t0 = r;
  38454. } else if (dx > 0) {
  38455. if (r < t0) return;
  38456. if (r < t1) t1 = r;
  38457. }
  38458. r = y0 - ay;
  38459. if (!dy && r > 0) return;
  38460. r /= dy;
  38461. if (dy < 0) {
  38462. if (r < t0) return;
  38463. if (r < t1) t1 = r;
  38464. } else if (dy > 0) {
  38465. if (r > t1) return;
  38466. if (r > t0) t0 = r;
  38467. }
  38468. r = y1 - ay;
  38469. if (!dy && r < 0) return;
  38470. r /= dy;
  38471. if (dy < 0) {
  38472. if (r > t1) return;
  38473. if (r > t0) t0 = r;
  38474. } else if (dy > 0) {
  38475. if (r < t0) return;
  38476. if (r < t1) t1 = r;
  38477. }
  38478. if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy;
  38479. if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy;
  38480. return true;
  38481. };
  38482. var pointEqual = function(a, b) {
  38483. return abs(a[0] - b[0]) < epsilon$1 && abs(a[1] - b[1]) < epsilon$1;
  38484. };
  38485. function Intersection(point, points, other, entry) {
  38486. this.x = point;
  38487. this.z = points;
  38488. this.o = other; // another intersection
  38489. this.e = entry; // is an entry?
  38490. this.v = false; // visited
  38491. this.n = this.p = null; // next & previous
  38492. }
  38493. // A generalized polygon clipping algorithm: given a polygon that has been cut
  38494. // into its visible line segments, and rejoins the segments by interpolating
  38495. // along the clip edge.
  38496. var clipPolygon$1 = function(segments, compareIntersection, startInside, interpolate, stream) {
  38497. var subject = [],
  38498. clip = [],
  38499. i,
  38500. n;
  38501. segments.forEach(function(segment) {
  38502. if ((n = segment.length - 1) <= 0) return;
  38503. var n, p0 = segment[0], p1 = segment[n], x;
  38504. // If the first and last points of a segment are coincident, then treat as a
  38505. // closed ring. TODO if all rings are closed, then the winding order of the
  38506. // exterior ring should be checked.
  38507. if (pointEqual(p0, p1)) {
  38508. stream.lineStart();
  38509. for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]);
  38510. stream.lineEnd();
  38511. return;
  38512. }
  38513. subject.push(x = new Intersection(p0, segment, null, true));
  38514. clip.push(x.o = new Intersection(p0, null, x, false));
  38515. subject.push(x = new Intersection(p1, segment, null, false));
  38516. clip.push(x.o = new Intersection(p1, null, x, true));
  38517. });
  38518. if (!subject.length) return;
  38519. clip.sort(compareIntersection);
  38520. link(subject);
  38521. link(clip);
  38522. for (i = 0, n = clip.length; i < n; ++i) {
  38523. clip[i].e = startInside = !startInside;
  38524. }
  38525. var start = subject[0],
  38526. points,
  38527. point;
  38528. while (1) {
  38529. // Find first unvisited intersection.
  38530. var current = start,
  38531. isSubject = true;
  38532. while (current.v) if ((current = current.n) === start) return;
  38533. points = current.z;
  38534. stream.lineStart();
  38535. do {
  38536. current.v = current.o.v = true;
  38537. if (current.e) {
  38538. if (isSubject) {
  38539. for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]);
  38540. } else {
  38541. interpolate(current.x, current.n.x, 1, stream);
  38542. }
  38543. current = current.n;
  38544. } else {
  38545. if (isSubject) {
  38546. points = current.p.z;
  38547. for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]);
  38548. } else {
  38549. interpolate(current.x, current.p.x, -1, stream);
  38550. }
  38551. current = current.p;
  38552. }
  38553. current = current.o;
  38554. points = current.z;
  38555. isSubject = !isSubject;
  38556. } while (!current.v);
  38557. stream.lineEnd();
  38558. }
  38559. };
  38560. function link(array) {
  38561. if (!(n = array.length)) return;
  38562. var n,
  38563. i = 0,
  38564. a = array[0],
  38565. b;
  38566. while (++i < n) {
  38567. a.n = b = array[i];
  38568. b.p = a;
  38569. a = b;
  38570. }
  38571. a.n = b = array[0];
  38572. b.p = a;
  38573. }
  38574. var ascending = function(a, b) {
  38575. return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
  38576. };
  38577. var bisector = function(compare) {
  38578. if (compare.length === 1) compare = ascendingComparator(compare);
  38579. return {
  38580. left: function(a, x, lo, hi) {
  38581. if (lo == null) lo = 0;
  38582. if (hi == null) hi = a.length;
  38583. while (lo < hi) {
  38584. var mid = lo + hi >>> 1;
  38585. if (compare(a[mid], x) < 0) lo = mid + 1;
  38586. else hi = mid;
  38587. }
  38588. return lo;
  38589. },
  38590. right: function(a, x, lo, hi) {
  38591. if (lo == null) lo = 0;
  38592. if (hi == null) hi = a.length;
  38593. while (lo < hi) {
  38594. var mid = lo + hi >>> 1;
  38595. if (compare(a[mid], x) > 0) hi = mid;
  38596. else lo = mid + 1;
  38597. }
  38598. return lo;
  38599. }
  38600. };
  38601. };
  38602. function ascendingComparator(f) {
  38603. return function(d, x) {
  38604. return ascending(f(d), x);
  38605. };
  38606. }
  38607. var ascendingBisect = bisector(ascending);
  38608. var merge$1 = function(arrays) {
  38609. var n = arrays.length,
  38610. m,
  38611. i = -1,
  38612. j = 0,
  38613. merged,
  38614. array;
  38615. while (++i < n) j += arrays[i].length;
  38616. merged = new Array(j);
  38617. while (--n >= 0) {
  38618. array = arrays[n];
  38619. m = array.length;
  38620. while (--m >= 0) {
  38621. merged[--j] = array[m];
  38622. }
  38623. }
  38624. return merged;
  38625. };
  38626. var clipMax = 1e9;
  38627. var clipMin = -clipMax;
  38628. // TODO Use d3-polygon’s polygonContains here for the ring check?
  38629. // TODO Eliminate duplicate buffering in clipBuffer and polygon.push?
  38630. function clipExtent(x0, y0, x1, y1) {
  38631. function visible(x, y) {
  38632. return x0 <= x && x <= x1 && y0 <= y && y <= y1;
  38633. }
  38634. function interpolate(from, to, direction, stream) {
  38635. var a = 0, a1 = 0;
  38636. if (from == null
  38637. || (a = corner(from, direction)) !== (a1 = corner(to, direction))
  38638. || comparePoint(from, to) < 0 ^ direction > 0) {
  38639. do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
  38640. while ((a = (a + direction + 4) % 4) !== a1);
  38641. } else {
  38642. stream.point(to[0], to[1]);
  38643. }
  38644. }
  38645. function corner(p, direction) {
  38646. return abs(p[0] - x0) < epsilon$1 ? direction > 0 ? 0 : 3
  38647. : abs(p[0] - x1) < epsilon$1 ? direction > 0 ? 2 : 1
  38648. : abs(p[1] - y0) < epsilon$1 ? direction > 0 ? 1 : 0
  38649. : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon
  38650. }
  38651. function compareIntersection(a, b) {
  38652. return comparePoint(a.x, b.x);
  38653. }
  38654. function comparePoint(a, b) {
  38655. var ca = corner(a, 1),
  38656. cb = corner(b, 1);
  38657. return ca !== cb ? ca - cb
  38658. : ca === 0 ? b[1] - a[1]
  38659. : ca === 1 ? a[0] - b[0]
  38660. : ca === 2 ? a[1] - b[1]
  38661. : b[0] - a[0];
  38662. }
  38663. return function(stream) {
  38664. var activeStream = stream,
  38665. bufferStream = clipBuffer(),
  38666. segments,
  38667. polygon,
  38668. ring,
  38669. x__, y__, v__, // first point
  38670. x_, y_, v_, // previous point
  38671. first,
  38672. clean;
  38673. var clipStream = {
  38674. point: point,
  38675. lineStart: lineStart,
  38676. lineEnd: lineEnd,
  38677. polygonStart: polygonStart,
  38678. polygonEnd: polygonEnd
  38679. };
  38680. function point(x, y) {
  38681. if (visible(x, y)) activeStream.point(x, y);
  38682. }
  38683. function polygonInside() {
  38684. var winding = 0;
  38685. for (var i = 0, n = polygon.length; i < n; ++i) {
  38686. for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) {
  38687. a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1];
  38688. if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; }
  38689. else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; }
  38690. }
  38691. }
  38692. return winding;
  38693. }
  38694. // Buffer geometry within a polygon and then clip it en masse.
  38695. function polygonStart() {
  38696. activeStream = bufferStream, segments = [], polygon = [], clean = true;
  38697. }
  38698. function polygonEnd() {
  38699. var startInside = polygonInside(),
  38700. cleanInside = clean && startInside,
  38701. visible = (segments = merge$1(segments)).length;
  38702. if (cleanInside || visible) {
  38703. stream.polygonStart();
  38704. if (cleanInside) {
  38705. stream.lineStart();
  38706. interpolate(null, null, 1, stream);
  38707. stream.lineEnd();
  38708. }
  38709. if (visible) {
  38710. clipPolygon$1(segments, compareIntersection, startInside, interpolate, stream);
  38711. }
  38712. stream.polygonEnd();
  38713. }
  38714. activeStream = stream, segments = polygon = ring = null;
  38715. }
  38716. function lineStart() {
  38717. clipStream.point = linePoint;
  38718. if (polygon) polygon.push(ring = []);
  38719. first = true;
  38720. v_ = false;
  38721. x_ = y_ = NaN;
  38722. }
  38723. // TODO rather than special-case polygons, simply handle them separately.
  38724. // Ideally, coincident intersection points should be jittered to avoid
  38725. // clipping issues.
  38726. function lineEnd() {
  38727. if (segments) {
  38728. linePoint(x__, y__);
  38729. if (v__ && v_) bufferStream.rejoin();
  38730. segments.push(bufferStream.result());
  38731. }
  38732. clipStream.point = point;
  38733. if (v_) activeStream.lineEnd();
  38734. }
  38735. function linePoint(x, y) {
  38736. var v = visible(x, y);
  38737. if (polygon) ring.push([x, y]);
  38738. if (first) {
  38739. x__ = x, y__ = y, v__ = v;
  38740. first = false;
  38741. if (v) {
  38742. activeStream.lineStart();
  38743. activeStream.point(x, y);
  38744. }
  38745. } else {
  38746. if (v && v_) activeStream.point(x, y);
  38747. else {
  38748. var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))],
  38749. b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))];
  38750. if (clipLine(a, b, x0, y0, x1, y1)) {
  38751. if (!v_) {
  38752. activeStream.lineStart();
  38753. activeStream.point(a[0], a[1]);
  38754. }
  38755. activeStream.point(b[0], b[1]);
  38756. if (!v) activeStream.lineEnd();
  38757. clean = false;
  38758. } else if (v) {
  38759. activeStream.lineStart();
  38760. activeStream.point(x, y);
  38761. clean = false;
  38762. }
  38763. }
  38764. }
  38765. x_ = x, y_ = y, v_ = v;
  38766. }
  38767. return clipStream;
  38768. };
  38769. }
  38770. var sum$1 = adder();
  38771. var polygonContains = function(polygon, point) {
  38772. var lambda = point[0],
  38773. phi = point[1],
  38774. normal = [sin(lambda), -cos(lambda), 0],
  38775. angle = 0,
  38776. winding = 0;
  38777. sum$1.reset();
  38778. for (var i = 0, n = polygon.length; i < n; ++i) {
  38779. if (!(m = (ring = polygon[i]).length)) continue;
  38780. var ring,
  38781. m,
  38782. point0 = ring[m - 1],
  38783. lambda0 = point0[0],
  38784. phi0 = point0[1] / 2 + quarterPi,
  38785. sinPhi0 = sin(phi0),
  38786. cosPhi0 = cos(phi0);
  38787. for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
  38788. var point1 = ring[j],
  38789. lambda1 = point1[0],
  38790. phi1 = point1[1] / 2 + quarterPi,
  38791. sinPhi1 = sin(phi1),
  38792. cosPhi1 = cos(phi1),
  38793. delta = lambda1 - lambda0,
  38794. sign = delta >= 0 ? 1 : -1,
  38795. absDelta = sign * delta,
  38796. antimeridian = absDelta > pi,
  38797. k = sinPhi0 * sinPhi1;
  38798. sum$1.add(atan2(k * sign * sin(absDelta), cosPhi0 * cosPhi1 + k * cos(absDelta)));
  38799. angle += antimeridian ? delta + sign * tau : delta;
  38800. // Are the longitudes either side of the point’s meridian (lambda),
  38801. // and are the latitudes smaller than the parallel (phi)?
  38802. if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
  38803. var arc = cartesianCross(cartesian(point0), cartesian(point1));
  38804. cartesianNormalizeInPlace(arc);
  38805. var intersection = cartesianCross(normal, arc);
  38806. cartesianNormalizeInPlace(intersection);
  38807. var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]);
  38808. if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
  38809. winding += antimeridian ^ delta >= 0 ? 1 : -1;
  38810. }
  38811. }
  38812. }
  38813. }
  38814. // First, determine whether the South pole is inside or outside:
  38815. //
  38816. // It is inside if:
  38817. // * the polygon winds around it in a clockwise direction.
  38818. // * the polygon does not (cumulatively) wind around it, but has a negative
  38819. // (counter-clockwise) area.
  38820. //
  38821. // Second, count the (signed) number of times a segment crosses a lambda
  38822. // from the point to the South pole. If it is zero, then the point is the
  38823. // same side as the South pole.
  38824. return (angle < -epsilon$1 || angle < epsilon$1 && sum$1 < -epsilon$1) ^ (winding & 1);
  38825. };
  38826. var lengthSum = adder();
  38827. var identity$2 = function(x) {
  38828. return x;
  38829. };
  38830. var areaSum$1 = adder();
  38831. var areaRingSum$1 = adder();
  38832. var x0$2 = Infinity;
  38833. var y0$2 = x0$2;
  38834. var x1 = -x0$2;
  38835. var y1 = x1;
  38836. var boundsStream$1 = {
  38837. point: boundsPoint$1,
  38838. lineStart: noop,
  38839. lineEnd: noop,
  38840. polygonStart: noop,
  38841. polygonEnd: noop,
  38842. result: function() {
  38843. var bounds = [[x0$2, y0$2], [x1, y1]];
  38844. x1 = y1 = -(y0$2 = x0$2 = Infinity);
  38845. return bounds;
  38846. }
  38847. };
  38848. function boundsPoint$1(x, y) {
  38849. if (x < x0$2) x0$2 = x;
  38850. if (x > x1) x1 = x;
  38851. if (y < y0$2) y0$2 = y;
  38852. if (y > y1) y1 = y;
  38853. }
  38854. var lengthSum$1 = adder();
  38855. var clip = function(pointVisible, clipLine, interpolate, start) {
  38856. return function(rotate, sink) {
  38857. var line = clipLine(sink),
  38858. rotatedStart = rotate.invert(start[0], start[1]),
  38859. ringBuffer = clipBuffer(),
  38860. ringSink = clipLine(ringBuffer),
  38861. polygonStarted = false,
  38862. polygon,
  38863. segments,
  38864. ring;
  38865. var clip = {
  38866. point: point,
  38867. lineStart: lineStart,
  38868. lineEnd: lineEnd,
  38869. polygonStart: function() {
  38870. clip.point = pointRing;
  38871. clip.lineStart = ringStart;
  38872. clip.lineEnd = ringEnd;
  38873. segments = [];
  38874. polygon = [];
  38875. },
  38876. polygonEnd: function() {
  38877. clip.point = point;
  38878. clip.lineStart = lineStart;
  38879. clip.lineEnd = lineEnd;
  38880. segments = merge$1(segments);
  38881. var startInside = polygonContains(polygon, rotatedStart);
  38882. if (segments.length) {
  38883. if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
  38884. clipPolygon$1(segments, compareIntersection, startInside, interpolate, sink);
  38885. } else if (startInside) {
  38886. if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
  38887. sink.lineStart();
  38888. interpolate(null, null, 1, sink);
  38889. sink.lineEnd();
  38890. }
  38891. if (polygonStarted) sink.polygonEnd(), polygonStarted = false;
  38892. segments = polygon = null;
  38893. },
  38894. sphere: function() {
  38895. sink.polygonStart();
  38896. sink.lineStart();
  38897. interpolate(null, null, 1, sink);
  38898. sink.lineEnd();
  38899. sink.polygonEnd();
  38900. }
  38901. };
  38902. function point(lambda, phi) {
  38903. var point = rotate(lambda, phi);
  38904. if (pointVisible(lambda = point[0], phi = point[1])) sink.point(lambda, phi);
  38905. }
  38906. function pointLine(lambda, phi) {
  38907. var point = rotate(lambda, phi);
  38908. line.point(point[0], point[1]);
  38909. }
  38910. function lineStart() {
  38911. clip.point = pointLine;
  38912. line.lineStart();
  38913. }
  38914. function lineEnd() {
  38915. clip.point = point;
  38916. line.lineEnd();
  38917. }
  38918. function pointRing(lambda, phi) {
  38919. ring.push([lambda, phi]);
  38920. var point = rotate(lambda, phi);
  38921. ringSink.point(point[0], point[1]);
  38922. }
  38923. function ringStart() {
  38924. ringSink.lineStart();
  38925. ring = [];
  38926. }
  38927. function ringEnd() {
  38928. pointRing(ring[0][0], ring[0][1]);
  38929. ringSink.lineEnd();
  38930. var clean = ringSink.clean(),
  38931. ringSegments = ringBuffer.result(),
  38932. i, n = ringSegments.length, m,
  38933. segment,
  38934. point;
  38935. ring.pop();
  38936. polygon.push(ring);
  38937. ring = null;
  38938. if (!n) return;
  38939. // No intersections.
  38940. if (clean & 1) {
  38941. segment = ringSegments[0];
  38942. if ((m = segment.length - 1) > 0) {
  38943. if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
  38944. sink.lineStart();
  38945. for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]);
  38946. sink.lineEnd();
  38947. }
  38948. return;
  38949. }
  38950. // Rejoin connected segments.
  38951. // TODO reuse ringBuffer.rejoin()?
  38952. if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
  38953. segments.push(ringSegments.filter(validSegment));
  38954. }
  38955. return clip;
  38956. };
  38957. };
  38958. function validSegment(segment) {
  38959. return segment.length > 1;
  38960. }
  38961. // Intersections are sorted along the clip edge. For both antimeridian cutting
  38962. // and circle clipping, the same comparison is used.
  38963. function compareIntersection(a, b) {
  38964. return ((a = a.x)[0] < 0 ? a[1] - halfPi - epsilon$1 : halfPi - a[1])
  38965. - ((b = b.x)[0] < 0 ? b[1] - halfPi - epsilon$1 : halfPi - b[1]);
  38966. }
  38967. var clipAntimeridian = clip(
  38968. function() { return true; },
  38969. clipAntimeridianLine,
  38970. clipAntimeridianInterpolate,
  38971. [-pi, -halfPi]
  38972. );
  38973. // Takes a line and cuts into visible segments. Return values: 0 - there were
  38974. // intersections or the line was empty; 1 - no intersections; 2 - there were
  38975. // intersections, and the first and last segments should be rejoined.
  38976. function clipAntimeridianLine(stream) {
  38977. var lambda0 = NaN,
  38978. phi0 = NaN,
  38979. sign0 = NaN,
  38980. clean; // no intersections
  38981. return {
  38982. lineStart: function() {
  38983. stream.lineStart();
  38984. clean = 1;
  38985. },
  38986. point: function(lambda1, phi1) {
  38987. var sign1 = lambda1 > 0 ? pi : -pi,
  38988. delta = abs(lambda1 - lambda0);
  38989. if (abs(delta - pi) < epsilon$1) { // line crosses a pole
  38990. stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi : -halfPi);
  38991. stream.point(sign0, phi0);
  38992. stream.lineEnd();
  38993. stream.lineStart();
  38994. stream.point(sign1, phi0);
  38995. stream.point(lambda1, phi0);
  38996. clean = 0;
  38997. } else if (sign0 !== sign1 && delta >= pi) { // line crosses antimeridian
  38998. if (abs(lambda0 - sign0) < epsilon$1) lambda0 -= sign0 * epsilon$1; // handle degeneracies
  38999. if (abs(lambda1 - sign1) < epsilon$1) lambda1 -= sign1 * epsilon$1;
  39000. phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);
  39001. stream.point(sign0, phi0);
  39002. stream.lineEnd();
  39003. stream.lineStart();
  39004. stream.point(sign1, phi0);
  39005. clean = 0;
  39006. }
  39007. stream.point(lambda0 = lambda1, phi0 = phi1);
  39008. sign0 = sign1;
  39009. },
  39010. lineEnd: function() {
  39011. stream.lineEnd();
  39012. lambda0 = phi0 = NaN;
  39013. },
  39014. clean: function() {
  39015. return 2 - clean; // if intersections, rejoin first and last segments
  39016. }
  39017. };
  39018. }
  39019. function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {
  39020. var cosPhi0,
  39021. cosPhi1,
  39022. sinLambda0Lambda1 = sin(lambda0 - lambda1);
  39023. return abs(sinLambda0Lambda1) > epsilon$1
  39024. ? atan((sin(phi0) * (cosPhi1 = cos(phi1)) * sin(lambda1)
  39025. - sin(phi1) * (cosPhi0 = cos(phi0)) * sin(lambda0))
  39026. / (cosPhi0 * cosPhi1 * sinLambda0Lambda1))
  39027. : (phi0 + phi1) / 2;
  39028. }
  39029. function clipAntimeridianInterpolate(from, to, direction, stream) {
  39030. var phi;
  39031. if (from == null) {
  39032. phi = direction * halfPi;
  39033. stream.point(-pi, phi);
  39034. stream.point(0, phi);
  39035. stream.point(pi, phi);
  39036. stream.point(pi, 0);
  39037. stream.point(pi, -phi);
  39038. stream.point(0, -phi);
  39039. stream.point(-pi, -phi);
  39040. stream.point(-pi, 0);
  39041. stream.point(-pi, phi);
  39042. } else if (abs(from[0] - to[0]) > epsilon$1) {
  39043. var lambda = from[0] < to[0] ? pi : -pi;
  39044. phi = direction * lambda / 2;
  39045. stream.point(-lambda, phi);
  39046. stream.point(0, phi);
  39047. stream.point(lambda, phi);
  39048. } else {
  39049. stream.point(to[0], to[1]);
  39050. }
  39051. }
  39052. var clipCircle = function(radius, delta) {
  39053. var cr = cos(radius),
  39054. smallRadius = cr > 0,
  39055. notHemisphere = abs(cr) > epsilon$1; // TODO optimise for this common case
  39056. function interpolate(from, to, direction, stream) {
  39057. circleStream(stream, radius, delta, direction, from, to);
  39058. }
  39059. function visible(lambda, phi) {
  39060. return cos(lambda) * cos(phi) > cr;
  39061. }
  39062. // Takes a line and cuts into visible segments. Return values used for polygon
  39063. // clipping: 0 - there were intersections or the line was empty; 1 - no
  39064. // intersections 2 - there were intersections, and the first and last segments
  39065. // should be rejoined.
  39066. function clipLine(stream) {
  39067. var point0, // previous point
  39068. c0, // code for previous point
  39069. v0, // visibility of previous point
  39070. v00, // visibility of first point
  39071. clean; // no intersections
  39072. return {
  39073. lineStart: function() {
  39074. v00 = v0 = false;
  39075. clean = 1;
  39076. },
  39077. point: function(lambda, phi) {
  39078. var point1 = [lambda, phi],
  39079. point2,
  39080. v = visible(lambda, phi),
  39081. c = smallRadius
  39082. ? v ? 0 : code(lambda, phi)
  39083. : v ? code(lambda + (lambda < 0 ? pi : -pi), phi) : 0;
  39084. if (!point0 && (v00 = v0 = v)) stream.lineStart();
  39085. // Handle degeneracies.
  39086. // TODO ignore if not clipping polygons.
  39087. if (v !== v0) {
  39088. point2 = intersect(point0, point1);
  39089. if (!point2 || pointEqual(point0, point2) || pointEqual(point1, point2)) {
  39090. point1[0] += epsilon$1;
  39091. point1[1] += epsilon$1;
  39092. v = visible(point1[0], point1[1]);
  39093. }
  39094. }
  39095. if (v !== v0) {
  39096. clean = 0;
  39097. if (v) {
  39098. // outside going in
  39099. stream.lineStart();
  39100. point2 = intersect(point1, point0);
  39101. stream.point(point2[0], point2[1]);
  39102. } else {
  39103. // inside going out
  39104. point2 = intersect(point0, point1);
  39105. stream.point(point2[0], point2[1]);
  39106. stream.lineEnd();
  39107. }
  39108. point0 = point2;
  39109. } else if (notHemisphere && point0 && smallRadius ^ v) {
  39110. var t;
  39111. // If the codes for two points are different, or are both zero,
  39112. // and there this segment intersects with the small circle.
  39113. if (!(c & c0) && (t = intersect(point1, point0, true))) {
  39114. clean = 0;
  39115. if (smallRadius) {
  39116. stream.lineStart();
  39117. stream.point(t[0][0], t[0][1]);
  39118. stream.point(t[1][0], t[1][1]);
  39119. stream.lineEnd();
  39120. } else {
  39121. stream.point(t[1][0], t[1][1]);
  39122. stream.lineEnd();
  39123. stream.lineStart();
  39124. stream.point(t[0][0], t[0][1]);
  39125. }
  39126. }
  39127. }
  39128. if (v && (!point0 || !pointEqual(point0, point1))) {
  39129. stream.point(point1[0], point1[1]);
  39130. }
  39131. point0 = point1, v0 = v, c0 = c;
  39132. },
  39133. lineEnd: function() {
  39134. if (v0) stream.lineEnd();
  39135. point0 = null;
  39136. },
  39137. // Rejoin first and last segments if there were intersections and the first
  39138. // and last points were visible.
  39139. clean: function() {
  39140. return clean | ((v00 && v0) << 1);
  39141. }
  39142. };
  39143. }
  39144. // Intersects the great circle between a and b with the clip circle.
  39145. function intersect(a, b, two) {
  39146. var pa = cartesian(a),
  39147. pb = cartesian(b);
  39148. // We have two planes, n1.p = d1 and n2.p = d2.
  39149. // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
  39150. var n1 = [1, 0, 0], // normal
  39151. n2 = cartesianCross(pa, pb),
  39152. n2n2 = cartesianDot(n2, n2),
  39153. n1n2 = n2[0], // cartesianDot(n1, n2),
  39154. determinant = n2n2 - n1n2 * n1n2;
  39155. // Two polar points.
  39156. if (!determinant) return !two && a;
  39157. var c1 = cr * n2n2 / determinant,
  39158. c2 = -cr * n1n2 / determinant,
  39159. n1xn2 = cartesianCross(n1, n2),
  39160. A = cartesianScale(n1, c1),
  39161. B = cartesianScale(n2, c2);
  39162. cartesianAddInPlace(A, B);
  39163. // Solve |p(t)|^2 = 1.
  39164. var u = n1xn2,
  39165. w = cartesianDot(A, u),
  39166. uu = cartesianDot(u, u),
  39167. t2 = w * w - uu * (cartesianDot(A, A) - 1);
  39168. if (t2 < 0) return;
  39169. var t = sqrt(t2),
  39170. q = cartesianScale(u, (-w - t) / uu);
  39171. cartesianAddInPlace(q, A);
  39172. q = spherical(q);
  39173. if (!two) return q;
  39174. // Two intersection points.
  39175. var lambda0 = a[0],
  39176. lambda1 = b[0],
  39177. phi0 = a[1],
  39178. phi1 = b[1],
  39179. z;
  39180. if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;
  39181. var delta = lambda1 - lambda0,
  39182. polar = abs(delta - pi) < epsilon$1,
  39183. meridian = polar || delta < epsilon$1;
  39184. if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z;
  39185. // Check that the first point is between a and b.
  39186. if (meridian
  39187. ? polar
  39188. ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon$1 ? phi0 : phi1)
  39189. : phi0 <= q[1] && q[1] <= phi1
  39190. : delta > pi ^ (lambda0 <= q[0] && q[0] <= lambda1)) {
  39191. var q1 = cartesianScale(u, (-w + t) / uu);
  39192. cartesianAddInPlace(q1, A);
  39193. return [q, spherical(q1)];
  39194. }
  39195. }
  39196. // Generates a 4-bit vector representing the location of a point relative to
  39197. // the small circle's bounding box.
  39198. function code(lambda, phi) {
  39199. var r = smallRadius ? radius : pi - radius,
  39200. code = 0;
  39201. if (lambda < -r) code |= 1; // left
  39202. else if (lambda > r) code |= 2; // right
  39203. if (phi < -r) code |= 4; // below
  39204. else if (phi > r) code |= 8; // above
  39205. return code;
  39206. }
  39207. return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi, radius - pi]);
  39208. };
  39209. function transformer(methods) {
  39210. return function(stream) {
  39211. var s = new TransformStream;
  39212. for (var key in methods) s[key] = methods[key];
  39213. s.stream = stream;
  39214. return s;
  39215. };
  39216. }
  39217. function TransformStream() {}
  39218. TransformStream.prototype = {
  39219. constructor: TransformStream,
  39220. point: function(x, y) { this.stream.point(x, y); },
  39221. sphere: function() { this.stream.sphere(); },
  39222. lineStart: function() { this.stream.lineStart(); },
  39223. lineEnd: function() { this.stream.lineEnd(); },
  39224. polygonStart: function() { this.stream.polygonStart(); },
  39225. polygonEnd: function() { this.stream.polygonEnd(); }
  39226. };
  39227. function fitExtent(projection, extent, object) {
  39228. var w = extent[1][0] - extent[0][0],
  39229. h = extent[1][1] - extent[0][1],
  39230. clip = projection.clipExtent && projection.clipExtent();
  39231. projection
  39232. .scale(150)
  39233. .translate([0, 0]);
  39234. if (clip != null) projection.clipExtent(null);
  39235. geoStream(object, projection.stream(boundsStream$1));
  39236. var b = boundsStream$1.result(),
  39237. k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])),
  39238. x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2,
  39239. y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2;
  39240. if (clip != null) projection.clipExtent(clip);
  39241. return projection
  39242. .scale(k * 150)
  39243. .translate([x, y]);
  39244. }
  39245. function fitSize(projection, size, object) {
  39246. return fitExtent(projection, [[0, 0], size], object);
  39247. }
  39248. var maxDepth = 16;
  39249. var cosMinDistance = cos(30 * radians); // cos(minimum angular distance)
  39250. var resample = function(project, delta2) {
  39251. return +delta2 ? resample$1(project, delta2) : resampleNone(project);
  39252. };
  39253. function resampleNone(project) {
  39254. return transformer({
  39255. point: function(x, y) {
  39256. x = project(x, y);
  39257. this.stream.point(x[0], x[1]);
  39258. }
  39259. });
  39260. }
  39261. function resample$1(project, delta2) {
  39262. function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) {
  39263. var dx = x1 - x0,
  39264. dy = y1 - y0,
  39265. d2 = dx * dx + dy * dy;
  39266. if (d2 > 4 * delta2 && depth--) {
  39267. var a = a0 + a1,
  39268. b = b0 + b1,
  39269. c = c0 + c1,
  39270. m = sqrt(a * a + b * b + c * c),
  39271. phi2 = asin(c /= m),
  39272. lambda2 = abs(abs(c) - 1) < epsilon$1 || abs(lambda0 - lambda1) < epsilon$1 ? (lambda0 + lambda1) / 2 : atan2(b, a),
  39273. p = project(lambda2, phi2),
  39274. x2 = p[0],
  39275. y2 = p[1],
  39276. dx2 = x2 - x0,
  39277. dy2 = y2 - y0,
  39278. dz = dy * dx2 - dx * dy2;
  39279. if (dz * dz / d2 > delta2 // perpendicular projected distance
  39280. || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end
  39281. || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance
  39282. resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream);
  39283. stream.point(x2, y2);
  39284. resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream);
  39285. }
  39286. }
  39287. }
  39288. return function(stream) {
  39289. var lambda00, x00, y00, a00, b00, c00, // first point
  39290. lambda0, x0, y0, a0, b0, c0; // previous point
  39291. var resampleStream = {
  39292. point: point,
  39293. lineStart: lineStart,
  39294. lineEnd: lineEnd,
  39295. polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; },
  39296. polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; }
  39297. };
  39298. function point(x, y) {
  39299. x = project(x, y);
  39300. stream.point(x[0], x[1]);
  39301. }
  39302. function lineStart() {
  39303. x0 = NaN;
  39304. resampleStream.point = linePoint;
  39305. stream.lineStart();
  39306. }
  39307. function linePoint(lambda, phi) {
  39308. var c = cartesian([lambda, phi]), p = project(lambda, phi);
  39309. resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
  39310. stream.point(x0, y0);
  39311. }
  39312. function lineEnd() {
  39313. resampleStream.point = point;
  39314. stream.lineEnd();
  39315. }
  39316. function ringStart() {
  39317. lineStart();
  39318. resampleStream.point = ringPoint;
  39319. resampleStream.lineEnd = ringEnd;
  39320. }
  39321. function ringPoint(lambda, phi) {
  39322. linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
  39323. resampleStream.point = linePoint;
  39324. }
  39325. function ringEnd() {
  39326. resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream);
  39327. resampleStream.lineEnd = lineEnd;
  39328. lineEnd();
  39329. }
  39330. return resampleStream;
  39331. };
  39332. }
  39333. var transformRadians = transformer({
  39334. point: function(x, y) {
  39335. this.stream.point(x * radians, y * radians);
  39336. }
  39337. });
  39338. function projection(project) {
  39339. return projectionMutator(function() { return project; })();
  39340. }
  39341. function projectionMutator(projectAt) {
  39342. var project,
  39343. k = 150, // scale
  39344. x = 480, y = 250, // translate
  39345. dx, dy, lambda = 0, phi = 0, // center
  39346. deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate
  39347. theta = null, preclip = clipAntimeridian, // clip angle
  39348. x0 = null, y0, x1, y1, postclip = identity$2, // clip extent
  39349. delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision
  39350. cache,
  39351. cacheStream;
  39352. function projection(point) {
  39353. point = projectRotate(point[0] * radians, point[1] * radians);
  39354. return [point[0] * k + dx, dy - point[1] * k];
  39355. }
  39356. function invert(point) {
  39357. point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k);
  39358. return point && [point[0] * degrees, point[1] * degrees];
  39359. }
  39360. function projectTransform(x, y) {
  39361. return x = project(x, y), [x[0] * k + dx, dy - x[1] * k];
  39362. }
  39363. projection.stream = function(stream) {
  39364. return cache && cacheStream === stream ? cache : cache = transformRadians(preclip(rotate, projectResample(postclip(cacheStream = stream))));
  39365. };
  39366. projection.clipAngle = function(_) {
  39367. return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians, 6 * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees;
  39368. };
  39369. projection.clipExtent = function(_) {
  39370. return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$2) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]];
  39371. };
  39372. projection.scale = function(_) {
  39373. return arguments.length ? (k = +_, recenter()) : k;
  39374. };
  39375. projection.translate = function(_) {
  39376. return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y];
  39377. };
  39378. projection.center = function(_) {
  39379. return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees, phi * degrees];
  39380. };
  39381. projection.rotate = function(_) {
  39382. return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees, deltaPhi * degrees, deltaGamma * degrees];
  39383. };
  39384. projection.precision = function(_) {
  39385. return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2);
  39386. };
  39387. projection.fitExtent = function(extent$$1, object) {
  39388. return fitExtent(projection, extent$$1, object);
  39389. };
  39390. projection.fitSize = function(size, object) {
  39391. return fitSize(projection, size, object);
  39392. };
  39393. function recenter() {
  39394. projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project);
  39395. var center = project(lambda, phi);
  39396. dx = x - center[0] * k;
  39397. dy = y + center[1] * k;
  39398. return reset();
  39399. }
  39400. function reset() {
  39401. cache = cacheStream = null;
  39402. return projection;
  39403. }
  39404. return function() {
  39405. project = projectAt.apply(this, arguments);
  39406. projection.invert = project.invert && invert;
  39407. return recenter();
  39408. };
  39409. }
  39410. function mercatorRaw(lambda, phi) {
  39411. return [lambda, log(tan((halfPi + phi) / 2))];
  39412. }
  39413. mercatorRaw.invert = function(x, y) {
  39414. return [x, 2 * atan(exp(y)) - halfPi];
  39415. };
  39416. function mercatorProjection(project) {
  39417. var m = projection(project),
  39418. center = m.center,
  39419. scale = m.scale,
  39420. translate = m.translate,
  39421. clipExtent = m.clipExtent,
  39422. x0 = null, y0, x1, y1; // clip extent
  39423. m.scale = function(_) {
  39424. return arguments.length ? (scale(_), reclip()) : scale();
  39425. };
  39426. m.translate = function(_) {
  39427. return arguments.length ? (translate(_), reclip()) : translate();
  39428. };
  39429. m.center = function(_) {
  39430. return arguments.length ? (center(_), reclip()) : center();
  39431. };
  39432. m.clipExtent = function(_) {
  39433. return arguments.length ? (_ == null ? x0 = y0 = x1 = y1 = null : (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reclip()) : x0 == null ? null : [[x0, y0], [x1, y1]];
  39434. };
  39435. function reclip() {
  39436. var k = pi * scale(),
  39437. t = m(rotation(m.rotate()).invert([0, 0]));
  39438. return clipExtent(x0 == null
  39439. ? [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]] : project === mercatorRaw
  39440. ? [[Math.max(t[0] - k, x0), y0], [Math.min(t[0] + k, x1), y1]]
  39441. : [[x0, Math.max(t[1] - k, y0)], [x1, Math.min(t[1] + k, y1)]]);
  39442. }
  39443. return reclip();
  39444. }
  39445. function transverseMercatorRaw(lambda, phi) {
  39446. return [log(tan((halfPi + phi) / 2)), -lambda];
  39447. }
  39448. transverseMercatorRaw.invert = function(x, y) {
  39449. return [-y, 2 * atan(exp(x)) - halfPi];
  39450. };
  39451. var geoTransverseMercator = function() {
  39452. var m = mercatorProjection(transverseMercatorRaw),
  39453. center = m.center,
  39454. rotate = m.rotate;
  39455. m.center = function(_) {
  39456. return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]);
  39457. };
  39458. m.rotate = function(_) {
  39459. return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]);
  39460. };
  39461. return rotate([0, 0, 90])
  39462. .scale(159.155);
  39463. };
  39464. /**
  39465. * Calculates a buffer for input features for a given radius. Units supported are miles, kilometers, and degrees.
  39466. *
  39467. * When using a negative radius, the resulting geometry may be invalid if
  39468. * it's too small compared to the radius magnitude. If the input is a
  39469. * FeatureCollection, only valid members will be returned in the output
  39470. * FeatureCollection - i.e., the output collection may have fewer members than
  39471. * the input, or even be empty.
  39472. *
  39473. * @name buffer
  39474. * @param {FeatureCollection|Geometry|Feature<any>} geojson input to be buffered
  39475. * @param {number} radius distance to draw the buffer (negative values are allowed)
  39476. * @param {Object} [options={}] Optional parameters
  39477. * @param {string} [options.units="kilometers"] any of the options supported by turf units
  39478. * @param {number} [options.steps=64] number of steps
  39479. * @returns {FeatureCollection|Feature<Polygon|MultiPolygon>|undefined} buffered features
  39480. * @example
  39481. * var point = turf.point([-90.548630, 14.616599]);
  39482. * var buffered = turf.buffer(point, 500, {units: 'miles'});
  39483. *
  39484. * //addToMap
  39485. * var addToMap = [point, buffered]
  39486. */
  39487. function buffer$1(geojson, radius, options) {
  39488. // Optional params
  39489. options = options || {};
  39490. var units = options.units;
  39491. var steps = options.steps || 64;
  39492. // validation
  39493. if (!geojson) throw new Error('geojson is required');
  39494. if (typeof options !== 'object') throw new Error('options must be an object');
  39495. if (typeof steps !== 'number') throw new Error('steps must be an number');
  39496. // Allow negative buffers ("erosion") or zero-sized buffers ("repair geometry")
  39497. if (radius === undefined) throw new Error('radius is required');
  39498. if (steps <= 0) throw new Error('steps must be greater than 0');
  39499. // default params
  39500. steps = steps || 64;
  39501. units = units || 'kilometers';
  39502. var results = [];
  39503. switch (geojson.type) {
  39504. case 'GeometryCollection':
  39505. geomEach(geojson, function (geometry$$1) {
  39506. var buffered = bufferFeature(geometry$$1, radius, units, steps);
  39507. if (buffered) results.push(buffered);
  39508. });
  39509. return featureCollection(results);
  39510. case 'FeatureCollection':
  39511. featureEach(geojson, function (feature$$1) {
  39512. var multiBuffered = bufferFeature(feature$$1, radius, units, steps);
  39513. if (multiBuffered) {
  39514. featureEach(multiBuffered, function (buffered) {
  39515. if (buffered) results.push(buffered);
  39516. });
  39517. }
  39518. });
  39519. return featureCollection(results);
  39520. }
  39521. return bufferFeature(geojson, radius, units, steps);
  39522. }
  39523. /**
  39524. * Buffer single Feature/Geometry
  39525. *
  39526. * @private
  39527. * @param {Feature<any>} geojson input to be buffered
  39528. * @param {number} radius distance to draw the buffer
  39529. * @param {string} [units='kilometers'] any of the options supported by turf units
  39530. * @param {number} [steps=64] number of steps
  39531. * @returns {Feature<Polygon|MultiPolygon>} buffered feature
  39532. */
  39533. function bufferFeature(geojson, radius, units, steps) {
  39534. var properties = geojson.properties || {};
  39535. var geometry$$1 = (geojson.type === 'Feature') ? geojson.geometry : geojson;
  39536. // Geometry Types faster than jsts
  39537. if (geometry$$1.type === 'GeometryCollection') {
  39538. var results = [];
  39539. geomEach(geojson, function (geometry$$1) {
  39540. var buffered = bufferFeature(geometry$$1, radius, units, steps);
  39541. if (buffered) results.push(buffered);
  39542. });
  39543. return featureCollection(results);
  39544. }
  39545. // Project GeoJSON to Transverse Mercator projection (convert to Meters)
  39546. var projected;
  39547. var bbox$$1 = bbox(geojson);
  39548. var needsTransverseMercator = bbox$$1[1] > 50 && bbox$$1[3] > 50;
  39549. if (needsTransverseMercator) {
  39550. projected = {
  39551. type: geometry$$1.type,
  39552. coordinates: projectCoords(geometry$$1.coordinates, defineProjection(geometry$$1))
  39553. };
  39554. } else {
  39555. projected = toMercator(geometry$$1);
  39556. }
  39557. // JSTS buffer operation
  39558. var reader = new GeoJSONReader();
  39559. var geom = reader.read(projected);
  39560. var distance = radiansToLength(lengthToRadians(radius, units), 'meters');
  39561. var buffered = BufferOp.bufferOp(geom, distance);
  39562. var writer = new GeoJSONWriter();
  39563. buffered = writer.write(buffered);
  39564. // Detect if empty geometries
  39565. if (coordsIsNaN(buffered.coordinates)) return undefined;
  39566. // Unproject coordinates (convert to Degrees)
  39567. var result;
  39568. if (needsTransverseMercator) {
  39569. result = {
  39570. type: buffered.type,
  39571. coordinates: unprojectCoords(buffered.coordinates, defineProjection(geometry$$1))
  39572. };
  39573. } else {
  39574. result = toWgs84(buffered);
  39575. }
  39576. return (result.geometry) ? result : feature(result, properties);
  39577. }
  39578. /**
  39579. * Coordinates isNaN
  39580. *
  39581. * @private
  39582. * @param {Array<any>} coords GeoJSON Coordinates
  39583. * @returns {boolean} if NaN exists
  39584. */
  39585. function coordsIsNaN(coords) {
  39586. if (Array.isArray(coords[0])) return coordsIsNaN(coords[0]);
  39587. return isNaN(coords[0]);
  39588. }
  39589. /**
  39590. * Project coordinates to projection
  39591. *
  39592. * @private
  39593. * @param {Array<any>} coords to project
  39594. * @param {GeoProjection} proj D3 Geo Projection
  39595. * @returns {Array<any>} projected coordinates
  39596. */
  39597. function projectCoords(coords, proj) {
  39598. if (typeof coords[0] !== 'object') return proj(coords);
  39599. return coords.map(function (coord) {
  39600. return projectCoords(coord, proj);
  39601. });
  39602. }
  39603. /**
  39604. * Un-Project coordinates to projection
  39605. *
  39606. * @private
  39607. * @param {Array<any>} coords to un-project
  39608. * @param {GeoProjection} proj D3 Geo Projection
  39609. * @returns {Array<any>} un-projected coordinates
  39610. */
  39611. function unprojectCoords(coords, proj) {
  39612. if (typeof coords[0] !== 'object') return proj.invert(coords);
  39613. return coords.map(function (coord) {
  39614. return unprojectCoords(coord, proj);
  39615. });
  39616. }
  39617. /**
  39618. * Define Transverse Mercator projection
  39619. *
  39620. * @private
  39621. * @param {Geometry|Feature<any>} geojson Base projection on center of GeoJSON
  39622. * @returns {GeoProjection} D3 Geo Transverse Mercator Projection
  39623. */
  39624. function defineProjection(geojson) {
  39625. var coords = center(geojson).geometry.coordinates.reverse();
  39626. var rotate = coords.map(function (coord) { return -coord; });
  39627. return geoTransverseMercator()
  39628. .center(coords)
  39629. .rotate(rotate)
  39630. .scale(earthRadius);
  39631. }
  39632. /**
  39633. * Takes two or more {@link Polygon|polygons} and returns a combined polygon. If the input polygons are not contiguous, this function returns a {@link MultiPolygon} feature.
  39634. *
  39635. * @name union
  39636. * @param {...Feature<Polygon>} A polygon to combine
  39637. * @returns {Feature<(Polygon|MultiPolygon)>} a combined {@link Polygon} or {@link MultiPolygon} feature
  39638. * @example
  39639. * var poly1 = turf.polygon([[
  39640. * [-82.574787, 35.594087],
  39641. * [-82.574787, 35.615581],
  39642. * [-82.545261, 35.615581],
  39643. * [-82.545261, 35.594087],
  39644. * [-82.574787, 35.594087]
  39645. * ]], {"fill": "#0f0"});
  39646. * var poly2 = turf.polygon([[
  39647. * [-82.560024, 35.585153],
  39648. * [-82.560024, 35.602602],
  39649. * [-82.52964, 35.602602],
  39650. * [-82.52964, 35.585153],
  39651. * [-82.560024, 35.585153]
  39652. * ]], {"fill": "#00f"});
  39653. *
  39654. * var union = turf.union(poly1, poly2);
  39655. *
  39656. * //addToMap
  39657. * var addToMap = [poly1, poly2, union];
  39658. */
  39659. function union() {
  39660. var reader = new GeoJSONReader();
  39661. var result = reader.read(JSON.stringify(arguments[0].geometry));
  39662. for (var i = 1; i < arguments.length; i++) {
  39663. result = UnionOp.union(result, reader.read(JSON.stringify(arguments[i].geometry)));
  39664. }
  39665. var writer = new GeoJSONWriter();
  39666. result = writer.write(result);
  39667. return {
  39668. type: 'Feature',
  39669. geometry: result,
  39670. properties: arguments[0].properties
  39671. };
  39672. }
  39673. // depend on jsts for now http://bjornharrtell.github.io/jsts/
  39674. /**
  39675. * Takes two {@link Polygon|polygons} and finds their intersection. If they share a border, returns the border; if they don't intersect, returns undefined.
  39676. *
  39677. * @name intersect
  39678. * @param {Feature<Polygon>} poly1 the first polygon
  39679. * @param {Feature<Polygon>} poly2 the second polygon
  39680. * @returns {Feature|null} returns a feature representing the point(s) they share (in case of a {@link Point} or {@link MultiPoint}), the borders they share (in case of a {@link LineString} or a {@link MultiLineString}), the area they share (in case of {@link Polygon} or {@link MultiPolygon}). If they do not share any point, returns `null`.
  39681. * @example
  39682. * var poly1 = turf.polygon([[
  39683. * [-122.801742, 45.48565],
  39684. * [-122.801742, 45.60491],
  39685. * [-122.584762, 45.60491],
  39686. * [-122.584762, 45.48565],
  39687. * [-122.801742, 45.48565]
  39688. * ]]);
  39689. *
  39690. * var poly2 = turf.polygon([[
  39691. * [-122.520217, 45.535693],
  39692. * [-122.64038, 45.553967],
  39693. * [-122.720031, 45.526554],
  39694. * [-122.669906, 45.507309],
  39695. * [-122.723464, 45.446643],
  39696. * [-122.532577, 45.408574],
  39697. * [-122.487258, 45.477466],
  39698. * [-122.520217, 45.535693]
  39699. * ]]);
  39700. *
  39701. * var intersection = turf.intersect(poly1, poly2);
  39702. *
  39703. * //addToMap
  39704. * var addToMap = [poly1, poly2, intersection];
  39705. */
  39706. function intersect$2(poly1, poly2) {
  39707. var geom1 = getGeom(poly1);
  39708. var geom2 = getGeom(poly2);
  39709. // Return null if geometry is too narrow in coordinate precision
  39710. // fixes topology errors with JSTS
  39711. // https://github.com/Turfjs/turf/issues/463
  39712. // https://github.com/Turfjs/turf/pull/1004
  39713. if (cleanCoords(truncate(geom2, {precision: 4})).coordinates[0].length < 4) return null;
  39714. if (cleanCoords(truncate(geom1, {precision: 4})).coordinates[0].length < 4) return null;
  39715. var reader = new GeoJSONReader();
  39716. var a = reader.read(truncate(geom1));
  39717. var b = reader.read(truncate(geom2));
  39718. var intersection = OverlayOp.intersection(a, b);
  39719. // https://github.com/Turfjs/turf/issues/951
  39720. if (intersection.isEmpty()) return null;
  39721. var writer = new GeoJSONWriter();
  39722. var geom = writer.write(intersection);
  39723. return feature(geom);
  39724. }
  39725. /**
  39726. * @license get-closest https://github.com/cosmosio/get-closest
  39727. *
  39728. * The MIT License (MIT)
  39729. *
  39730. * Copyright (c) 2014-2017 Olivier Scherrer <pode.fr@gmail.com>
  39731. */
  39732. /**
  39733. * Get the closest number in an array
  39734. *
  39735. * @private
  39736. * @param {number} item the base number
  39737. * @param {Array} array the array to search into
  39738. * @param {Function} getDiff returns the difference between the base number and
  39739. * and the currently read item in the array. The item which returned the smallest difference wins.
  39740. * @returns {Object} Get Closest
  39741. */
  39742. function _getClosest(item, array, getDiff) {
  39743. var closest,
  39744. diff;
  39745. if (!Array.isArray(array)) {
  39746. throw new Error('Get closest expects an array as second argument');
  39747. }
  39748. array.forEach(function (comparedItem, comparedItemIndex) {
  39749. var thisDiff = getDiff(comparedItem, item);
  39750. if (thisDiff >= 0 && (typeof diff == 'undefined' || thisDiff < diff)) {
  39751. diff = thisDiff;
  39752. closest = comparedItemIndex;
  39753. }
  39754. });
  39755. return closest;
  39756. }
  39757. /**
  39758. * Get the closest number in an array given a base number
  39759. *
  39760. * @private
  39761. * @param {number} item the base number
  39762. * @param {Array<number>} array the array of numbers to search into
  39763. * @returns {number} the index of the closest item in the array
  39764. * @example
  39765. * closestNumber(30, [20, 0, 50, 29])
  39766. * //= will return 3 as 29 is the closest item
  39767. */
  39768. /**
  39769. * Get the closest greater number in an array given a base number
  39770. *
  39771. * @private
  39772. * @param {number} item the base number
  39773. * @param {Array<number>} array the array of numbers to search into
  39774. * @returns {number} the index of the closest item in the array
  39775. * @example
  39776. * closestGreaterNumber(30, [20, 0, 50, 29])
  39777. * //= will return 2 as 50 is the closest greater item
  39778. */
  39779. function closestGreaterNumber(item, array) {
  39780. return _getClosest(item, array, function (comparedItem, item) {
  39781. return comparedItem - item;
  39782. });
  39783. }
  39784. /**
  39785. * Get the closest lower number in an array given a base number
  39786. *
  39787. * @private
  39788. * @param {number} item the base number
  39789. * @param {Array<number>} array the array of numbers to search into
  39790. * @returns {number} the index of the closest item in the array
  39791. * @example
  39792. * closestLowerNumber(30, [20, 0, 50, 29])
  39793. * //= will return 0 as 20 is the closest lower item
  39794. */
  39795. /**
  39796. * Get the closest item in an array given a base item and a comparator function
  39797. *
  39798. * @private
  39799. * @param {*} item the base item
  39800. * @param {Array} array an array of items
  39801. * @param {Function} comparator a comparatof function to compare the items
  39802. * @returns {Object} Closest Custom
  39803. * @example
  39804. * closestCustom("lundi", ["mundi", "mardi"], getLevenshteinDistance)
  39805. * //= will return 0 for "lundi"
  39806. *
  39807. * // The function looks like:
  39808. *
  39809. * // comparedItem comes from the array
  39810. * // baseItem is the item to compare the others to
  39811. * // It returns a number
  39812. * function comparator(comparedItem, baseItem) {
  39813. * return comparedItem - baseItem;
  39814. * }
  39815. */
  39816. /**
  39817. * Dissolves a FeatureCollection of {@link polygon} features, filtered by an optional property name:value.
  39818. * Note that {@link mulitpolygon} features within the collection are not supported
  39819. *
  39820. * @name dissolve
  39821. * @param {FeatureCollection<Polygon>} featureCollection input feature collection to be dissolved
  39822. * @param {Object} [options={}] Optional parameters
  39823. * @param {string} [options.propertyName] features with equals 'propertyName' in `properties` will be merged
  39824. * @returns {FeatureCollection<Polygon>} a FeatureCollection containing the dissolved polygons
  39825. * @example
  39826. * var features = turf.featureCollection([
  39827. * turf.polygon([[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]], {combine: 'yes'}),
  39828. * turf.polygon([[[0, -1], [0, 0], [1, 0], [1, -1], [0,-1]]], {combine: 'yes'}),
  39829. * turf.polygon([[[1,-1],[1, 0], [2, 0], [2, -1], [1, -1]]], {combine: 'no'}),
  39830. * ]);
  39831. *
  39832. * var dissolved = turf.dissolve(features, {propertyName: 'combine'});
  39833. *
  39834. * //addToMap
  39835. * var addToMap = [features, dissolved]
  39836. */
  39837. function dissolve$1(featureCollection$$1, options) {
  39838. // Optional parameters
  39839. options = options || {};
  39840. if (!isObject(options)) throw new Error('options is invalid');
  39841. var propertyName = options.propertyName;
  39842. // Input validation
  39843. collectionOf(featureCollection$$1, 'Polygon', 'dissolve');
  39844. // Main
  39845. var fc = clone(featureCollection$$1);
  39846. var features = fc.features;
  39847. var originalIndexOfItemsRemoved = [];
  39848. features.forEach(function (f, i) {
  39849. f.properties.origIndexPosition = i;
  39850. });
  39851. var tree = geojsonRbush();
  39852. tree.load(fc);
  39853. for (var i in features) {
  39854. var polygon$$1 = features[i];
  39855. var featureChanged = false;
  39856. tree.search(polygon$$1).features.forEach(function (potentialMatchingFeature) {
  39857. polygon$$1 = features[i];
  39858. var matchFeaturePosition = potentialMatchingFeature.properties.origIndexPosition;
  39859. if (originalIndexOfItemsRemoved.length > 0 && matchFeaturePosition !== 0) {
  39860. if (matchFeaturePosition > originalIndexOfItemsRemoved[originalIndexOfItemsRemoved.length - 1]) {
  39861. matchFeaturePosition = matchFeaturePosition - (originalIndexOfItemsRemoved.length);
  39862. } else {
  39863. var closestNumber$$1 = closestGreaterNumber(matchFeaturePosition, originalIndexOfItemsRemoved);
  39864. if (closestNumber$$1 !== 0) {
  39865. matchFeaturePosition = matchFeaturePosition - closestNumber$$1;
  39866. }
  39867. }
  39868. }
  39869. if (matchFeaturePosition === +i) return;
  39870. var matchFeature = features[matchFeaturePosition];
  39871. if (!matchFeature || !polygon$$1) return;
  39872. if (propertyName !== undefined &&
  39873. matchFeature.properties[propertyName] !== polygon$$1.properties[propertyName]) return;
  39874. if (!booleanOverlap(polygon$$1, matchFeature) || !ringsIntersect(polygon$$1, matchFeature)) return;
  39875. features[i] = union(polygon$$1, matchFeature);
  39876. originalIndexOfItemsRemoved.push(potentialMatchingFeature.properties.origIndexPosition);
  39877. originalIndexOfItemsRemoved.sort(function (a, b) {
  39878. return a - b;
  39879. });
  39880. tree.remove(potentialMatchingFeature);
  39881. features.splice(matchFeaturePosition, 1);
  39882. polygon$$1.properties.origIndexPosition = i;
  39883. tree.remove(polygon$$1, function (a, b) {
  39884. return a.properties.origIndexPosition === b.properties.origIndexPosition;
  39885. });
  39886. featureChanged = true;
  39887. });
  39888. if (featureChanged) {
  39889. if (!polygon$$1) continue;
  39890. polygon$$1.properties.origIndexPosition = i;
  39891. tree.insert(polygon$$1);
  39892. i--;
  39893. }
  39894. }
  39895. features.forEach(function (f) {
  39896. delete f.properties.origIndexPosition;
  39897. delete f.bbox;
  39898. });
  39899. return fc;
  39900. }
  39901. function ringsIntersect(poly1, poly2) {
  39902. var line1 = lineString(coordAll(poly1));
  39903. var line2 = lineString(coordAll(poly2));
  39904. var points$$1 = lineIntersect(line1, line2).features;
  39905. return points$$1.length > 0;
  39906. }
  39907. /**
  39908. * Takes a bounding box and the diameter of the cell and returns a {@link FeatureCollection} of flat-topped
  39909. * hexagons or triangles ({@link Polygon} features) aligned in an "odd-q" vertical grid as
  39910. * described in [Hexagonal Grids](http://www.redblobgames.com/grids/hexagons/).
  39911. *
  39912. * @name hexGrid
  39913. * @param {BBox} bbox extent in [minX, minY, maxX, maxY] order
  39914. * @param {number} cellSide length of the side of the the hexagons or triangles, in units. It will also coincide with the
  39915. * radius of the circumcircle of the hexagons.
  39916. * @param {Object} [options={}] Optional parameters
  39917. * @param {string} [options.units='kilometers'] used in calculating cell size, can be degrees, radians, miles, or kilometers
  39918. * @param {Object} [options.properties={}] passed to each hexagon or triangle of the grid
  39919. * @param {Feature<Polygon|MultiPolygon>} [options.mask] if passed a Polygon or MultiPolygon, the grid Points will be created only inside it
  39920. * @param {boolean} [options.triangles=false] whether to return as triangles instead of hexagons
  39921. * @returns {FeatureCollection<Polygon>} a hexagonal grid
  39922. * @example
  39923. * var bbox = [-96,31,-84,40];
  39924. * var cellSide = 50;
  39925. * var options = {units: 'miles'};
  39926. *
  39927. * var hexgrid = turf.hexGrid(bbox, cellSide, options);
  39928. *
  39929. * //addToMap
  39930. * var addToMap = [hexgrid];
  39931. */
  39932. function hexGrid(bbox, cellSide, options) {
  39933. // Optional parameters
  39934. options = options || {};
  39935. if (!isObject(options)) throw new Error('options is invalid');
  39936. // var units = options.units;
  39937. var properties = options.properties || {};
  39938. var triangles = options.triangles;
  39939. var mask = options.mask;
  39940. // validation
  39941. if (cellSide === null || cellSide === undefined) throw new Error('cellSide is required');
  39942. if (!isNumber(cellSide)) throw new Error('cellSide is invalid');
  39943. if (!bbox) throw new Error('bbox is required');
  39944. if (!Array.isArray(bbox)) throw new Error('bbox must be array');
  39945. if (bbox.length !== 4) throw new Error('bbox must contain 4 numbers');
  39946. if (mask && ['Polygon', 'MultiPolygon'].indexOf(getType(mask)) === -1) throw new Error('options.mask must be a (Multi)Polygon');
  39947. var west = bbox[0];
  39948. var south = bbox[1];
  39949. var east = bbox[2];
  39950. var north = bbox[3];
  39951. var centerY = (south + north) / 2;
  39952. var centerX = (west + east) / 2;
  39953. // https://github.com/Turfjs/turf/issues/758
  39954. var xFraction = cellSide * 2 / (distance([west, centerY], [east, centerY], options));
  39955. var cellWidth = xFraction * (east - west);
  39956. var yFraction = cellSide * 2 / (distance([centerX, south], [centerX, north], options));
  39957. var cellHeight = yFraction * (north - south);
  39958. var radius = cellWidth / 2;
  39959. var hex_width = radius * 2;
  39960. var hex_height = Math.sqrt(3) / 2 * cellHeight;
  39961. var box_width = east - west;
  39962. var box_height = north - south;
  39963. var x_interval = 3 / 4 * hex_width;
  39964. var y_interval = hex_height;
  39965. // adjust box_width so all hexagons will be inside the bbox
  39966. var x_span = (box_width - hex_width) / (hex_width - radius / 2);
  39967. var x_count = Math.floor(x_span);
  39968. var x_adjust = ((x_count * x_interval - radius / 2) - box_width) / 2 - radius / 2 + x_interval / 2;
  39969. // adjust box_height so all hexagons will be inside the bbox
  39970. var y_count = Math.floor((box_height - hex_height) / hex_height);
  39971. var y_adjust = (box_height - y_count * hex_height) / 2;
  39972. var hasOffsetY = y_count * hex_height - box_height > hex_height / 2;
  39973. if (hasOffsetY) {
  39974. y_adjust -= hex_height / 4;
  39975. }
  39976. // Precompute cosines and sines of angles used in hexagon creation for performance gain
  39977. var cosines = [];
  39978. var sines = [];
  39979. for (var i = 0; i < 6; i++) {
  39980. var angle = 2 * Math.PI / 6 * i;
  39981. cosines.push(Math.cos(angle));
  39982. sines.push(Math.sin(angle));
  39983. }
  39984. var results = [];
  39985. for (var x = 0; x <= x_count; x++) {
  39986. for (var y = 0; y <= y_count; y++) {
  39987. var isOdd = x % 2 === 1;
  39988. if (y === 0 && isOdd) continue;
  39989. if (y === 0 && hasOffsetY) continue;
  39990. var center_x = x * x_interval + west - x_adjust;
  39991. var center_y = y * y_interval + south + y_adjust;
  39992. if (isOdd) {
  39993. center_y -= hex_height / 2;
  39994. }
  39995. if (triangles === true) {
  39996. hexTriangles(
  39997. [center_x, center_y],
  39998. cellWidth / 2,
  39999. cellHeight / 2,
  40000. properties,
  40001. cosines,
  40002. sines).forEach(function (triangle) {
  40003. if (mask) {
  40004. if (intersect$2(mask, triangle)) results.push(triangle);
  40005. } else {
  40006. results.push(triangle);
  40007. }
  40008. });
  40009. } else {
  40010. var hex = hexagon(
  40011. [center_x, center_y],
  40012. cellWidth / 2,
  40013. cellHeight / 2,
  40014. properties,
  40015. cosines,
  40016. sines
  40017. );
  40018. if (mask) {
  40019. if (intersect$2(mask, hex)) results.push(hex);
  40020. } else {
  40021. results.push(hex);
  40022. }
  40023. }
  40024. }
  40025. }
  40026. return featureCollection(results);
  40027. }
  40028. /**
  40029. * Creates hexagon
  40030. *
  40031. * @private
  40032. * @param {Array<number>} center of the hexagon
  40033. * @param {number} rx half hexagon width
  40034. * @param {number} ry half hexagon height
  40035. * @param {Object} properties passed to each hexagon
  40036. * @param {Array<number>} cosines precomputed
  40037. * @param {Array<number>} sines precomputed
  40038. * @returns {Feature<Polygon>} hexagon
  40039. */
  40040. function hexagon(center, rx, ry, properties, cosines, sines) {
  40041. var vertices = [];
  40042. for (var i = 0; i < 6; i++) {
  40043. var x = center[0] + rx * cosines[i];
  40044. var y = center[1] + ry * sines[i];
  40045. vertices.push([x, y]);
  40046. }
  40047. //first and last vertex must be the same
  40048. vertices.push(vertices[0].slice());
  40049. return polygon([vertices], properties);
  40050. }
  40051. /**
  40052. * Creates triangles composing an hexagon
  40053. *
  40054. * @private
  40055. * @param {Array<number>} center of the hexagon
  40056. * @param {number} rx half triangle width
  40057. * @param {number} ry half triangle height
  40058. * @param {Object} properties passed to each triangle
  40059. * @param {Array<number>} cosines precomputed
  40060. * @param {Array<number>} sines precomputed
  40061. * @returns {Array<Feature<Polygon>>} triangles
  40062. */
  40063. function hexTriangles(center, rx, ry, properties, cosines, sines) {
  40064. var triangles = [];
  40065. for (var i = 0; i < 6; i++) {
  40066. var vertices = [];
  40067. vertices.push(center);
  40068. vertices.push([
  40069. center[0] + rx * cosines[i],
  40070. center[1] + ry * sines[i]
  40071. ]);
  40072. vertices.push([
  40073. center[0] + rx * cosines[(i + 1) % 6],
  40074. center[1] + ry * sines[(i + 1) % 6]
  40075. ]);
  40076. vertices.push(center);
  40077. triangles.push(polygon([vertices], properties));
  40078. }
  40079. return triangles;
  40080. }
  40081. /**
  40082. * Takes any type of {@link Polygon|polygon} and an optional mask and returns a {@link Polygon|polygon} exterior ring with holes.
  40083. *
  40084. * @name mask
  40085. * @param {FeatureCollection|Feature<Polygon|MultiPolygon>} polygon GeoJSON Polygon used as interior rings or holes.
  40086. * @param {Feature<Polygon>} [mask] GeoJSON Polygon used as the exterior ring (if undefined, the world extent is used)
  40087. * @returns {Feature<Polygon>} Masked Polygon (exterior ring with holes).
  40088. * @example
  40089. * var polygon = turf.polygon([[[112, -21], [116, -36], [146, -39], [153, -24], [133, -10], [112, -21]]]);
  40090. * var mask = turf.polygon([[[90, -55], [170, -55], [170, 10], [90, 10], [90, -55]]]);
  40091. *
  40092. * var masked = turf.mask(polygon, mask);
  40093. *
  40094. * //addToMap
  40095. * var addToMap = [masked]
  40096. */
  40097. function mask(polygon$$1, mask) {
  40098. // Define mask
  40099. var maskPolygon = createMask(mask);
  40100. // Define polygon
  40101. var separated = separatePolygons(polygon$$1);
  40102. var polygonOuters = separated[0];
  40103. var polygonInners = separated[1];
  40104. // Union Outers & Inners
  40105. polygonOuters = unionPolygons(polygonOuters);
  40106. polygonInners = unionPolygons(polygonInners);
  40107. // Create masked area
  40108. var masked = buildMask(maskPolygon, polygonOuters, polygonInners);
  40109. return masked;
  40110. }
  40111. /**
  40112. * Build Mask
  40113. *
  40114. * @private
  40115. * @param {Feature<Polygon>} maskPolygon Mask Outer
  40116. * @param {FeatureCollection<Polygon>} polygonOuters Polygon Outers
  40117. * @param {FeatureCollection<Polygon>} polygonInners Polygon Inners
  40118. * @returns {Feature<Polygon>} Feature Polygon
  40119. */
  40120. function buildMask(maskPolygon, polygonOuters, polygonInners) {
  40121. var coordinates = [];
  40122. coordinates.push(maskPolygon.geometry.coordinates[0]);
  40123. flattenEach(polygonOuters, function (feature$$1) {
  40124. coordinates.push(feature$$1.geometry.coordinates[0]);
  40125. });
  40126. flattenEach(polygonInners, function (feature$$1) {
  40127. coordinates.push(feature$$1.geometry.coordinates[0]);
  40128. });
  40129. return polygon(coordinates);
  40130. }
  40131. /**
  40132. * Separate Polygons to inners & outers
  40133. *
  40134. * @private
  40135. * @param {FeatureCollection|Feature<Polygon|MultiPolygon>} poly GeoJSON Feature
  40136. * @returns {Array<FeatureCollection<Polygon>, FeatureCollection<Polygon>>} Outer & Inner lines
  40137. */
  40138. function separatePolygons(poly) {
  40139. var outers = [];
  40140. var inners = [];
  40141. flattenEach(poly, function (feature$$1) {
  40142. var coordinates = feature$$1.geometry.coordinates;
  40143. var featureOuter = coordinates[0];
  40144. var featureInner = coordinates.slice(1);
  40145. outers.push(polygon([featureOuter]));
  40146. featureInner.forEach(function (inner) {
  40147. inners.push(polygon([inner]));
  40148. });
  40149. });
  40150. return [featureCollection(outers), featureCollection(inners)];
  40151. }
  40152. /**
  40153. * Create Mask Coordinates
  40154. *
  40155. * @private
  40156. * @param {Feature<Polygon>} [mask] default to world if undefined
  40157. * @returns {Feature<Polygon>} mask coordinate
  40158. */
  40159. function createMask(mask) {
  40160. var world = [[[180, 90], [-180, 90], [-180, -90], [180, -90], [180, 90]]];
  40161. var coordinates = mask && mask.geometry.coordinates || world;
  40162. return polygon(coordinates);
  40163. }
  40164. /**
  40165. * Union Polygons
  40166. *
  40167. * @private
  40168. * @param {FeatureCollection<Polygon>} polygons collection of polygons
  40169. * @returns {FeatureCollection<Polygon>} polygons only apply union if they collide
  40170. */
  40171. function unionPolygons(polygons$$1) {
  40172. if (polygons$$1.features.length <= 1) return polygons$$1;
  40173. var tree = createIndex(polygons$$1);
  40174. var results = [];
  40175. var removed = {};
  40176. flattenEach(polygons$$1, function (currentFeature, currentIndex) {
  40177. // Exclude any removed features
  40178. if (removed[currentIndex]) return true;
  40179. // Don't search for itself
  40180. tree.remove({index: currentIndex}, filterByIndex);
  40181. removed[currentIndex] = true;
  40182. // Keep applying the union operation until no more overlapping features
  40183. while (true) {
  40184. var bbox$$1 = bbox(currentFeature);
  40185. var search = tree.search({
  40186. minX: bbox$$1[0],
  40187. minY: bbox$$1[1],
  40188. maxX: bbox$$1[2],
  40189. maxY: bbox$$1[3]
  40190. });
  40191. if (search.length > 0) {
  40192. var polys = search.map(function (item) {
  40193. removed[item.index] = true;
  40194. tree.remove({index: item.index}, filterByIndex);
  40195. return item.geojson;
  40196. });
  40197. polys.push(currentFeature);
  40198. currentFeature = union.apply(this, polys);
  40199. }
  40200. // Done
  40201. if (search.length === 0) break;
  40202. }
  40203. results.push(currentFeature);
  40204. });
  40205. return featureCollection(results);
  40206. }
  40207. /**
  40208. * Filter by Index - RBush helper function
  40209. *
  40210. * @private
  40211. * @param {Object} a remove item
  40212. * @param {Object} b search item
  40213. * @returns {boolean} true if matches
  40214. */
  40215. function filterByIndex(a, b) {
  40216. return a.index === b.index;
  40217. }
  40218. /**
  40219. * Create RBush Tree Index
  40220. *
  40221. * @private
  40222. * @param {FeatureCollection<any>} features GeoJSON FeatureCollection
  40223. * @returns {RBush} RBush Tree
  40224. */
  40225. function createIndex(features) {
  40226. var tree = rbush_1();
  40227. var load = [];
  40228. flattenEach(features, function (feature$$1, index) {
  40229. var bbox$$1 = bbox(feature$$1);
  40230. load.push({
  40231. minX: bbox$$1[0],
  40232. minY: bbox$$1[1],
  40233. maxX: bbox$$1[2],
  40234. maxY: bbox$$1[3],
  40235. geojson: feature$$1,
  40236. index: index
  40237. });
  40238. });
  40239. tree.load(load);
  40240. return tree;
  40241. }
  40242. /**
  40243. * Creates a square grid from a bounding box, {@link Feature} or {@link FeatureCollection}.
  40244. *
  40245. * @name squareGrid
  40246. * @param {Array<number>} bbox extent in [minX, minY, maxX, maxY] order
  40247. * @param {number} cellSide of each cell, in units
  40248. * @param {Object} [options={}] Optional parameters
  40249. * @param {string} [options.units='kilometers'] used in calculating cellSide, can be degrees, radians, miles, or kilometers
  40250. * @param {Feature<Polygon|MultiPolygon>} [options.mask] if passed a Polygon or MultiPolygon, the grid Points will be created only inside it
  40251. * @param {Object} [options.properties={}] passed to each point of the grid
  40252. * @returns {FeatureCollection<Polygon>} grid a grid of polygons
  40253. * @example
  40254. * var bbox = [-95, 30 ,-85, 40];
  40255. * var cellSide = 50;
  40256. * var options = {units: 'miles'};
  40257. *
  40258. * var squareGrid = turf.squareGrid(bbox, cellSide, options);
  40259. *
  40260. * //addToMap
  40261. * var addToMap = [squareGrid]
  40262. */
  40263. function squareGrid(bbox, cellSide, options) {
  40264. // Optional parameters
  40265. options = options || {};
  40266. if (!isObject(options)) throw new Error('options is invalid');
  40267. // var units = options.units;
  40268. var properties = options.properties;
  40269. var mask = options.mask;
  40270. // Containers
  40271. var results = [];
  40272. // Input Validation
  40273. if (cellSide === null || cellSide === undefined) throw new Error('cellSide is required');
  40274. if (!isNumber(cellSide)) throw new Error('cellSide is invalid');
  40275. if (!bbox) throw new Error('bbox is required');
  40276. if (!Array.isArray(bbox)) throw new Error('bbox must be array');
  40277. if (bbox.length !== 4) throw new Error('bbox must contain 4 numbers');
  40278. if (mask && ['Polygon', 'MultiPolygon'].indexOf(getType(mask)) === -1) throw new Error('options.mask must be a (Multi)Polygon');
  40279. var west = bbox[0];
  40280. var south = bbox[1];
  40281. var east = bbox[2];
  40282. var north = bbox[3];
  40283. var xFraction = cellSide / (distance([west, south], [east, south], options));
  40284. var cellWidth = xFraction * (east - west);
  40285. var yFraction = cellSide / (distance([west, south], [west, north], options));
  40286. var cellHeight = yFraction * (north - south);
  40287. // rows & columns
  40288. var bboxWidth = (east - west);
  40289. var bboxHeight = (north - south);
  40290. var columns = Math.floor(bboxWidth / cellWidth);
  40291. var rows = Math.floor(bboxHeight / cellHeight);
  40292. // adjust origin of the grid
  40293. var deltaX = (bboxWidth - columns * cellWidth) / 2;
  40294. var deltaY = (bboxHeight - rows * cellHeight) / 2;
  40295. // iterate over columns & rows
  40296. var currentX = west + deltaX;
  40297. for (var column = 0; column < columns; column++) {
  40298. var currentY = south + deltaY;
  40299. for (var row = 0; row < rows; row++) {
  40300. var cellPoly = polygon([[
  40301. [currentX, currentY],
  40302. [currentX, currentY + cellHeight],
  40303. [currentX + cellWidth, currentY + cellHeight],
  40304. [currentX + cellWidth, currentY],
  40305. [currentX, currentY]
  40306. ]], properties);
  40307. if (mask) {
  40308. if (intersect$2(mask, cellPoly)) results.push(cellPoly);
  40309. } else {
  40310. results.push(cellPoly);
  40311. }
  40312. currentY += cellHeight;
  40313. }
  40314. currentX += cellWidth;
  40315. }
  40316. return featureCollection(results);
  40317. }
  40318. /**
  40319. * Takes a bounding box and a cell depth and returns a set of triangular {@link Polygon|polygons} in a grid.
  40320. *
  40321. * @name triangleGrid
  40322. * @param {Array<number>} bbox extent in [minX, minY, maxX, maxY] order
  40323. * @param {number} cellSide dimension of each cell
  40324. * @param {Object} [options={}] Optional parameters
  40325. * @param {string} [options.units='kilometers'] used in calculating cellSide, can be degrees, radians, miles, or kilometers
  40326. * @param {Feature<Polygon|MultiPolygon>} [options.mask] if passed a Polygon or MultiPolygon, the grid Points will be created only inside it
  40327. * @param {Object} [options.properties={}] passed to each point of the grid
  40328. * @returns {FeatureCollection<Polygon>} grid of polygons
  40329. * @example
  40330. * var bbox = [-95, 30 ,-85, 40];
  40331. * var cellSide = 50;
  40332. * var options = {units: 'miles'};
  40333. *
  40334. * var triangleGrid = turf.triangleGrid(bbox, cellSide, options);
  40335. *
  40336. * //addToMap
  40337. * var addToMap = [triangleGrid];
  40338. */
  40339. function triangleGrid(bbox, cellSide, options) {
  40340. // Optional parameters
  40341. options = options || {};
  40342. if (!isObject(options)) throw new Error('options is invalid');
  40343. // var units = options.units;
  40344. var properties = options.properties;
  40345. var mask = options.mask;
  40346. // Containers
  40347. var results = [];
  40348. // Input Validation
  40349. if (cellSide === null || cellSide === undefined) throw new Error('cellSide is required');
  40350. if (!isNumber(cellSide)) throw new Error('cellSide is invalid');
  40351. if (!bbox) throw new Error('bbox is required');
  40352. if (!Array.isArray(bbox)) throw new Error('bbox must be array');
  40353. if (bbox.length !== 4) throw new Error('bbox must contain 4 numbers');
  40354. if (mask && ['Polygon', 'MultiPolygon'].indexOf(getType(mask)) === -1) throw new Error('options.mask must be a (Multi)Polygon');
  40355. // Main
  40356. var xFraction = cellSide / (distance([bbox[0], bbox[1]], [bbox[2], bbox[1]], options));
  40357. var cellWidth = xFraction * (bbox[2] - bbox[0]);
  40358. var yFraction = cellSide / (distance([bbox[0], bbox[1]], [bbox[0], bbox[3]], options));
  40359. var cellHeight = yFraction * (bbox[3] - bbox[1]);
  40360. var xi = 0;
  40361. var currentX = bbox[0];
  40362. while (currentX <= bbox[2]) {
  40363. var yi = 0;
  40364. var currentY = bbox[1];
  40365. while (currentY <= bbox[3]) {
  40366. var cellTriangle1 = null;
  40367. var cellTriangle2 = null;
  40368. if (xi % 2 === 0 && yi % 2 === 0) {
  40369. cellTriangle1 = polygon([[
  40370. [currentX, currentY],
  40371. [currentX, currentY + cellHeight],
  40372. [currentX + cellWidth, currentY],
  40373. [currentX, currentY]
  40374. ]], properties);
  40375. cellTriangle2 = polygon([[
  40376. [currentX, currentY + cellHeight],
  40377. [currentX + cellWidth, currentY + cellHeight],
  40378. [currentX + cellWidth, currentY],
  40379. [currentX, currentY + cellHeight]
  40380. ]], properties);
  40381. } else if (xi % 2 === 0 && yi % 2 === 1) {
  40382. cellTriangle1 = polygon([[
  40383. [currentX, currentY],
  40384. [currentX + cellWidth, currentY + cellHeight],
  40385. [currentX + cellWidth, currentY],
  40386. [currentX, currentY]
  40387. ]], properties);
  40388. cellTriangle2 = polygon([[
  40389. [currentX, currentY],
  40390. [currentX, currentY + cellHeight],
  40391. [currentX + cellWidth, currentY + cellHeight],
  40392. [currentX, currentY]
  40393. ]], properties);
  40394. } else if (yi % 2 === 0 && xi % 2 === 1) {
  40395. cellTriangle1 = polygon([[
  40396. [currentX, currentY],
  40397. [currentX, currentY + cellHeight],
  40398. [currentX + cellWidth, currentY + cellHeight],
  40399. [currentX, currentY]
  40400. ]], properties);
  40401. cellTriangle2 = polygon([[
  40402. [currentX, currentY],
  40403. [currentX + cellWidth, currentY + cellHeight],
  40404. [currentX + cellWidth, currentY],
  40405. [currentX, currentY]
  40406. ]], properties);
  40407. } else if (yi % 2 === 1 && xi % 2 === 1) {
  40408. cellTriangle1 = polygon([[
  40409. [currentX, currentY],
  40410. [currentX, currentY + cellHeight],
  40411. [currentX + cellWidth, currentY],
  40412. [currentX, currentY]
  40413. ]], properties);
  40414. cellTriangle2 = polygon([[
  40415. [currentX, currentY + cellHeight],
  40416. [currentX + cellWidth, currentY + cellHeight],
  40417. [currentX + cellWidth, currentY],
  40418. [currentX, currentY + cellHeight]
  40419. ]], properties);
  40420. }
  40421. if (mask) {
  40422. if (intersect$2(mask, cellTriangle1)) results.push(cellTriangle1);
  40423. if (intersect$2(mask, cellTriangle2)) results.push(cellTriangle2);
  40424. } else {
  40425. results.push(cellTriangle1);
  40426. results.push(cellTriangle2);
  40427. }
  40428. currentY += cellHeight;
  40429. yi++;
  40430. }
  40431. xi++;
  40432. currentX += cellWidth;
  40433. }
  40434. return featureCollection(results);
  40435. }
  40436. /**
  40437. * Takes a set of points and estimates their 'property' values on a grid using the [Inverse Distance Weighting (IDW) method](https://en.wikipedia.org/wiki/Inverse_distance_weighting).
  40438. *
  40439. * @name interpolate
  40440. * @param {FeatureCollection<Point>} points with known value
  40441. * @param {number} cellSize the distance across each grid point
  40442. * @param {Object} [options={}] Optional parameters
  40443. * @param {string} [options.gridType='square'] defines the output format based on a Grid Type (options: 'square' | 'point' | 'hex' | 'triangle')
  40444. * @param {string} [options.property='elevation'] the property name in `points` from which z-values will be pulled, zValue fallbacks to 3rd coordinate if no property exists.
  40445. * @param {string} [options.units='kilometers'] used in calculating cellSize, can be degrees, radians, miles, or kilometers
  40446. * @param {number} [options.weight=1] exponent regulating the distance-decay weighting
  40447. * @returns {FeatureCollection<Point|Polygon>} grid of points or polygons with interpolated 'property'
  40448. * @example
  40449. * var points = turf.randomPoint(30, {bbox: [50, 30, 70, 50]});
  40450. *
  40451. * // add a random property to each point
  40452. * turf.featureEach(points, function(point) {
  40453. * point.properties.solRad = Math.random() * 50;
  40454. * });
  40455. * var options = {gridType: 'points', property: 'solRad', units: 'miles'};
  40456. * var grid = turf.interpolate(points, 100, options);
  40457. *
  40458. * //addToMap
  40459. * var addToMap = [grid];
  40460. */
  40461. function interpolate$1(points$$1, cellSize, options) {
  40462. // Optional parameters
  40463. options = options || {};
  40464. if (typeof options !== 'object') throw new Error('options is invalid');
  40465. var gridType = options.gridType;
  40466. var property = options.property;
  40467. var weight = options.weight;
  40468. // validation
  40469. if (!points$$1) throw new Error('points is required');
  40470. collectionOf(points$$1, 'Point', 'input must contain Points');
  40471. if (!cellSize) throw new Error('cellSize is required');
  40472. if (weight !== undefined && typeof weight !== 'number') throw new Error('weight must be a number');
  40473. // default values
  40474. property = property || 'elevation';
  40475. gridType = gridType || 'square';
  40476. weight = weight || 1;
  40477. var box = bbox(points$$1);
  40478. var grid;
  40479. switch (gridType) {
  40480. case 'point':
  40481. case 'points':
  40482. grid = pointGrid(box, cellSize, options);
  40483. break;
  40484. case 'square':
  40485. case 'squares':
  40486. grid = squareGrid(box, cellSize, options);
  40487. break;
  40488. case 'hex':
  40489. case 'hexes':
  40490. grid = hexGrid(box, cellSize, options);
  40491. break;
  40492. case 'triangle':
  40493. case 'triangles':
  40494. grid = triangleGrid(box, cellSize, options);
  40495. break;
  40496. default:
  40497. throw new Error('invalid gridType');
  40498. }
  40499. var results = [];
  40500. featureEach(grid, function (gridFeature) {
  40501. var zw = 0;
  40502. var sw = 0;
  40503. // calculate the distance from each input point to the grid points
  40504. featureEach(points$$1, function (point$$1) {
  40505. var gridPoint = (gridType === 'point') ? gridFeature : centroid(gridFeature);
  40506. var d = distance(gridPoint, point$$1, options);
  40507. var zValue;
  40508. // property has priority for zValue, fallbacks to 3rd coordinate from geometry
  40509. if (property !== undefined) zValue = point$$1.properties[property];
  40510. if (zValue === undefined) zValue = point$$1.geometry.coordinates[2];
  40511. if (zValue === undefined) throw new Error('zValue is missing');
  40512. if (d === 0) zw = zValue;
  40513. var w = 1.0 / Math.pow(d, weight);
  40514. sw += w;
  40515. zw += w * zValue;
  40516. });
  40517. // write interpolated value for each grid point
  40518. var newFeature = clone(gridFeature);
  40519. newFeature.properties[property] = zw / sw;
  40520. results.push(newFeature);
  40521. });
  40522. return featureCollection(results);
  40523. }
  40524. /**
  40525. * Turf is a modular geospatial analysis engine written in JavaScript. It performs geospatial
  40526. * processing tasks with GeoJSON data and can be run on a server or in a browser.
  40527. *
  40528. * @module turf
  40529. * @summary Geospatial analysis for JavaScript
  40530. */
  40531. exports.projection = main_es$3;
  40532. exports.random = main_es$4;
  40533. exports.clusters = main_es$5;
  40534. exports.helpers = main_es$1;
  40535. exports.invariant = main_es$2;
  40536. exports.meta = main_es;
  40537. exports.isolines = isolines;
  40538. exports.convex = convex;
  40539. exports.pointsWithinPolygon = pointsWithinPolygon;
  40540. exports.concave = concave;
  40541. exports.collect = collect;
  40542. exports.flip = flip;
  40543. exports.simplify = simplify;
  40544. exports.bezierSpline = bezier;
  40545. exports.tag = tag;
  40546. exports.sample = sample;
  40547. exports.envelope = envelope;
  40548. exports.square = square;
  40549. exports.circle = circle;
  40550. exports.midpoint = midpoint;
  40551. exports.center = center;
  40552. exports.centerOfMass = centerOfMass;
  40553. exports.centroid = centroid;
  40554. exports.combine = combine;
  40555. exports.distance = distance;
  40556. exports.explode = explode;
  40557. exports.bbox = bbox;
  40558. exports.tesselate = tesselate;
  40559. exports.bboxPolygon = bboxPolygon;
  40560. exports.booleanPointInPolygon = booleanPointInPolygon;
  40561. exports.nearestPoint = nearestPoint;
  40562. exports.nearestPointOnLine = nearestPointOnLine;
  40563. exports.nearestPointToLine = nearestPointToLine;
  40564. exports.planepoint = planepoint;
  40565. exports.tin = tin;
  40566. exports.bearing = bearing;
  40567. exports.destination = destination;
  40568. exports.kinks = kinks;
  40569. exports.pointOnFeature = pointOnFeature;
  40570. exports.area = area$1;
  40571. exports.along = along;
  40572. exports.length = length;
  40573. exports.lineSlice = lineSlice;
  40574. exports.lineSliceAlong = lineSliceAlong;
  40575. exports.pointGrid = pointGrid;
  40576. exports.truncate = truncate;
  40577. exports.flatten = flatten;
  40578. exports.lineIntersect = lineIntersect;
  40579. exports.lineChunk = lineChunk;
  40580. exports.unkinkPolygon = unkinkPolygon;
  40581. exports.greatCircle = greatCircle;
  40582. exports.lineSegment = lineSegment;
  40583. exports.lineSplit = lineSplit;
  40584. exports.lineArc = lineArc;
  40585. exports.polygonToLine = polygonToLine;
  40586. exports.lineToPolygon = lineToPolygon;
  40587. exports.bboxClip = bboxClip;
  40588. exports.lineOverlap = lineOverlap;
  40589. exports.sector = sector;
  40590. exports.rhumbBearing = rhumbBearing;
  40591. exports.rhumbDistance = rhumbDistance;
  40592. exports.rhumbDestination = rhumbDestination;
  40593. exports.polygonTangents = polygonTangents;
  40594. exports.rewind = rewind;
  40595. exports.isobands = isobands;
  40596. exports.transformRotate = transformRotate;
  40597. exports.transformScale = transformScale;
  40598. exports.transformTranslate = transformTranslate;
  40599. exports.lineOffset = lineOffset;
  40600. exports.polygonize = polygonize$1;
  40601. exports.booleanDisjoint = booleanDisjoint;
  40602. exports.booleanContains = booleanContains;
  40603. exports.booleanCrosses = booleanCrosses;
  40604. exports.booleanClockwise = booleanClockwise;
  40605. exports.booleanOverlap = booleanOverlap;
  40606. exports.booleanPointOnLine = booleanPointOnLine;
  40607. exports.booleanEqual = booleanEqual;
  40608. exports.booleanWithin = booleanWithin;
  40609. exports.clone = clone;
  40610. exports.cleanCoords = cleanCoords;
  40611. exports.clustersDbscan = clustersDbscan;
  40612. exports.clustersKmeans = clustersKmeans;
  40613. exports.pointToLineDistance = pointToLineDistance;
  40614. exports.booleanParallel = booleanParallel;
  40615. exports.shortestPath = shortestPath;
  40616. exports.voronoi = voronoi$1;
  40617. exports.ellipse = ellipse;
  40618. exports.centerMean = centerMean;
  40619. exports.centerMedian = centerMedian;
  40620. exports.standardDeviationalEllipse = standardDeviationalEllipse;
  40621. exports.difference = difference;
  40622. exports.buffer = buffer$1;
  40623. exports.union = union;
  40624. exports.intersect = intersect$2;
  40625. exports.dissolve = dissolve$1;
  40626. exports.hexGrid = hexGrid;
  40627. exports.mask = mask;
  40628. exports.squareGrid = squareGrid;
  40629. exports.triangleGrid = triangleGrid;
  40630. exports.interpolate = interpolate$1;
  40631. exports.pointOnSurface = pointOnFeature;
  40632. exports.polygonToLineString = polygonToLine;
  40633. exports.lineStringToPolygon = lineToPolygon;
  40634. exports.inside = booleanPointInPolygon;
  40635. exports.within = pointsWithinPolygon;
  40636. exports.bezier = bezier;
  40637. exports.nearest = nearestPoint;
  40638. exports.pointOnLine = nearestPointOnLine;
  40639. exports.lineDistance = length;
  40640. exports.radians2degrees = radiansToDegrees;
  40641. exports.degrees2radians = degreesToRadians;
  40642. exports.distanceToDegrees = lengthToDegrees;
  40643. exports.distanceToRadians = lengthToRadians;
  40644. exports.radiansToDistance = radiansToLength;
  40645. exports.bearingToAngle = bearingToAzimuth;
  40646. exports.convertDistance = convertLength;
  40647. exports.toMercator = toMercator;
  40648. exports.toWgs84 = toWgs84;
  40649. exports.randomPosition = randomPosition;
  40650. exports.randomPoint = randomPoint;
  40651. exports.randomPolygon = randomPolygon;
  40652. exports.randomLineString = randomLineString;
  40653. exports.getCluster = getCluster;
  40654. exports.clusterEach = clusterEach;
  40655. exports.clusterReduce = clusterReduce;
  40656. exports.createBins = createBins;
  40657. exports.applyFilter = applyFilter;
  40658. exports.propertiesContainsFilter = propertiesContainsFilter;
  40659. exports.filterProperties = filterProperties;
  40660. exports.earthRadius = earthRadius;
  40661. exports.factors = factors;
  40662. exports.unitsFactors = unitsFactors;
  40663. exports.areaFactors = areaFactors;
  40664. exports.feature = feature;
  40665. exports.geometry = geometry;
  40666. exports.point = point;
  40667. exports.points = points;
  40668. exports.polygon = polygon;
  40669. exports.polygons = polygons;
  40670. exports.lineString = lineString;
  40671. exports.lineStrings = lineStrings;
  40672. exports.featureCollection = featureCollection;
  40673. exports.multiLineString = multiLineString;
  40674. exports.multiPoint = multiPoint;
  40675. exports.multiPolygon = multiPolygon;
  40676. exports.geometryCollection = geometryCollection;
  40677. exports.round = round;
  40678. exports.radiansToLength = radiansToLength;
  40679. exports.lengthToRadians = lengthToRadians;
  40680. exports.lengthToDegrees = lengthToDegrees;
  40681. exports.bearingToAzimuth = bearingToAzimuth;
  40682. exports.radiansToDegrees = radiansToDegrees;
  40683. exports.degreesToRadians = degreesToRadians;
  40684. exports.convertLength = convertLength;
  40685. exports.convertArea = convertArea;
  40686. exports.isNumber = isNumber;
  40687. exports.isObject = isObject;
  40688. exports.validateBBox = validateBBox;
  40689. exports.validateId = validateId;
  40690. exports.getCoord = getCoord;
  40691. exports.getCoords = getCoords;
  40692. exports.containsNumber = containsNumber;
  40693. exports.geojsonType = geojsonType;
  40694. exports.featureOf = featureOf;
  40695. exports.collectionOf = collectionOf;
  40696. exports.getGeom = getGeom;
  40697. exports.getGeomType = getGeomType;
  40698. exports.getType = getType;
  40699. exports.coordEach = coordEach;
  40700. exports.coordReduce = coordReduce;
  40701. exports.propEach = propEach;
  40702. exports.propReduce = propReduce;
  40703. exports.featureEach = featureEach;
  40704. exports.featureReduce = featureReduce;
  40705. exports.coordAll = coordAll;
  40706. exports.geomEach = geomEach;
  40707. exports.geomReduce = geomReduce;
  40708. exports.flattenEach = flattenEach;
  40709. exports.flattenReduce = flattenReduce;
  40710. exports.segmentEach = segmentEach;
  40711. exports.segmentReduce = segmentReduce;
  40712. exports.lineEach = lineEach;
  40713. exports.lineReduce = lineReduce;
  40714. Object.defineProperty(exports, '__esModule', { value: true });
  40715. })));