jsts.es6.js 876 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273302743027530276302773027830279302803028130282302833028430285302863028730288302893029030291302923029330294302953029630297302983029930300303013030230303303043030530306303073030830309303103031130312303133031430315303163031730318303193032030321303223032330324303253032630327303283032930330303313033230333303343033530336303373033830339303403034130342303433034430345303463034730348303493035030351303523035330354303553035630357303583035930360303613036230363303643036530366303673036830369303703037130372303733037430375303763037730378303793038030381303823038330384303853038630387303883038930390303913039230393303943039530396303973039830399304003040130402304033040430405304063040730408304093041030411304123041330414304153041630417304183041930420304213042230423304243042530426304273042830429304303043130432304333043430435304363043730438304393044030441304423044330444304453044630447304483044930450304513045230453304543045530456304573045830459304603046130462304633046430465304663046730468304693047030471304723047330474304753047630477304783047930480304813048230483304843048530486304873048830489304903049130492304933049430495304963049730498304993050030501305023050330504305053050630507305083050930510305113051230513305143051530516305173051830519305203052130522305233052430525305263052730528305293053030531305323053330534305353053630537305383053930540305413054230543305443054530546305473054830549305503055130552305533055430555305563055730558305593056030561305623056330564305653056630567305683056930570305713057230573305743057530576305773057830579305803058130582305833058430585305863058730588305893059030591305923059330594305953059630597305983059930600306013060230603306043060530606306073060830609306103061130612306133061430615306163061730618306193062030621306223062330624306253062630627306283062930630306313063230633306343063530636306373063830639306403064130642306433064430645306463064730648306493065030651306523065330654306553065630657306583065930660306613066230663306643066530666306673066830669306703067130672306733067430675306763067730678306793068030681306823068330684306853068630687306883068930690306913069230693306943069530696306973069830699307003070130702307033070430705307063070730708307093071030711307123071330714307153071630717307183071930720307213072230723307243072530726307273072830729307303073130732307333073430735307363073730738307393074030741307423074330744307453074630747307483074930750307513075230753307543075530756307573075830759307603076130762307633076430765307663076730768307693077030771307723077330774307753077630777307783077930780307813078230783307843078530786307873078830789307903079130792307933079430795307963079730798307993080030801308023080330804308053080630807308083080930810308113081230813308143081530816308173081830819308203082130822308233082430825308263082730828308293083030831308323083330834308353083630837308383083930840308413084230843308443084530846308473084830849308503085130852308533085430855308563085730858308593086030861308623086330864308653086630867308683086930870308713087230873308743087530876308773087830879308803088130882308833088430885308863088730888308893089030891308923089330894308953089630897308983089930900309013090230903309043090530906309073090830909309103091130912309133091430915309163091730918309193092030921309223092330924309253092630927309283092930930309313093230933309343093530936309373093830939309403094130942309433094430945309463094730948309493095030951309523095330954309553095630957309583095930960309613096230963309643096530966309673096830969309703097130972309733097430975309763097730978309793098030981309823098330984309853098630987309883098930990309913099230993309943099530996309973099830999310003100131002310033100431005310063100731008310093101031011310123101331014310153101631017310183101931020310213102231023310243102531026310273102831029310303103131032310333103431035310363103731038310393104031041310423104331044310453104631047310483104931050310513105231053310543105531056310573105831059310603106131062310633106431065310663106731068310693107031071310723107331074310753107631077310783107931080310813108231083310843108531086310873108831089310903109131092310933109431095310963109731098310993110031101311023110331104311053110631107311083110931110311113111231113311143111531116311173111831119311203112131122311233112431125311263112731128311293113031131311323113331134311353113631137311383113931140311413114231143311443114531146311473114831149311503115131152311533115431155311563115731158311593116031161311623116331164311653116631167311683116931170311713117231173311743117531176311773117831179311803118131182311833118431185311863118731188311893119031191311923119331194311953119631197311983119931200312013120231203312043120531206312073120831209312103121131212312133121431215312163121731218312193122031221312223122331224312253122631227312283122931230312313123231233312343123531236312373123831239312403124131242312433124431245312463124731248312493125031251312523125331254312553125631257312583125931260312613126231263312643126531266312673126831269312703127131272312733127431275312763127731278312793128031281312823128331284312853128631287312883128931290312913129231293312943129531296312973129831299313003130131302313033130431305313063130731308313093131031311313123131331314313153131631317313183131931320313213132231323313243132531326313273132831329313303133131332313333133431335313363133731338313393134031341313423134331344313453134631347313483134931350313513135231353313543135531356313573135831359313603136131362313633136431365313663136731368313693137031371313723137331374313753137631377313783137931380313813138231383313843138531386313873138831389313903139131392313933139431395313963139731398313993140031401314023140331404314053140631407314083140931410314113141231413314143141531416314173141831419314203142131422314233142431425314263142731428314293143031431314323143331434314353143631437314383143931440314413144231443314443144531446314473144831449314503145131452314533145431455314563145731458314593146031461314623146331464314653146631467314683146931470314713147231473314743147531476314773147831479314803148131482314833148431485314863148731488314893149031491314923149331494314953149631497314983149931500315013150231503315043150531506315073150831509315103151131512315133151431515315163151731518315193152031521315223152331524315253152631527315283152931530315313153231533315343153531536315373153831539315403154131542315433154431545315463154731548315493155031551315523155331554315553155631557315583155931560315613156231563315643156531566315673156831569315703157131572315733157431575315763157731578315793158031581315823158331584315853158631587315883158931590315913159231593315943159531596315973159831599316003160131602316033160431605316063160731608316093161031611316123161331614316153161631617316183161931620316213162231623316243162531626316273162831629316303163131632316333163431635316363163731638316393164031641316423164331644316453164631647316483164931650316513165231653316543165531656316573165831659316603166131662316633166431665316663166731668316693167031671316723167331674316753167631677316783167931680316813168231683316843168531686316873168831689316903169131692316933169431695316963169731698316993170031701317023170331704317053170631707317083170931710317113171231713317143171531716317173171831719317203172131722317233172431725317263172731728317293173031731317323173331734317353173631737317383173931740317413174231743317443174531746317473174831749317503175131752317533175431755317563175731758317593176031761317623176331764317653176631767317683176931770317713177231773317743177531776317773177831779317803178131782317833178431785317863178731788317893179031791317923179331794317953179631797317983179931800318013180231803318043180531806318073180831809318103181131812318133181431815318163181731818318193182031821318223182331824318253182631827318283182931830318313183231833318343183531836318373183831839318403184131842318433184431845318463184731848318493185031851318523185331854318553185631857318583185931860318613186231863318643186531866318673186831869318703187131872318733187431875318763187731878318793188031881318823188331884318853188631887318883188931890318913189231893318943189531896318973189831899319003190131902319033190431905319063190731908319093191031911319123191331914319153191631917319183191931920319213192231923319243192531926319273192831929319303193131932319333193431935319363193731938319393194031941319423194331944319453194631947319483194931950319513195231953319543195531956319573195831959319603196131962319633196431965319663196731968319693197031971319723197331974319753197631977319783197931980319813198231983319843198531986319873198831989319903199131992319933199431995319963199731998319993200032001320023200332004320053200632007320083200932010320113201232013320143201532016320173201832019320203202132022320233202432025320263202732028320293203032031320323203332034320353203632037320383203932040320413204232043320443204532046320473204832049320503205132052320533205432055320563205732058320593206032061320623206332064320653206632067320683206932070320713207232073320743207532076320773207832079320803208132082320833208432085320863208732088320893209032091320923209332094320953209632097320983209932100321013210232103321043210532106321073210832109321103211132112321133211432115321163211732118321193212032121321223212332124321253212632127321283212932130321313213232133321343213532136321373213832139321403214132142321433214432145321463214732148321493215032151321523215332154321553215632157321583215932160321613216232163321643216532166321673216832169321703217132172321733217432175321763217732178321793218032181321823218332184321853218632187321883218932190321913219232193321943219532196321973219832199322003220132202322033220432205322063220732208322093221032211322123221332214322153221632217322183221932220322213222232223322243222532226322273222832229322303223132232322333223432235322363223732238322393224032241322423224332244322453224632247322483224932250322513225232253322543225532256322573225832259322603226132262322633226432265322663226732268322693227032271322723227332274322753227632277322783227932280322813228232283322843228532286322873228832289322903229132292322933229432295322963229732298322993230032301323023230332304323053230632307323083230932310323113231232313323143231532316323173231832319323203232132322323233232432325323263232732328323293233032331323323233332334323353233632337323383233932340323413234232343323443234532346323473234832349323503235132352323533235432355323563235732358323593236032361323623236332364323653236632367323683236932370323713237232373323743237532376323773237832379323803238132382323833238432385323863238732388323893239032391323923239332394323953239632397323983239932400324013240232403324043240532406324073240832409324103241132412324133241432415324163241732418324193242032421324223242332424324253242632427324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448324493245032451324523245332454324553245632457324583245932460324613246232463324643246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487324883248932490324913249232493324943249532496324973249832499325003250132502325033250432505325063250732508325093251032511325123251332514325153251632517325183251932520325213252232523325243252532526325273252832529325303253132532325333253432535325363253732538325393254032541325423254332544325453254632547325483254932550325513255232553325543255532556325573255832559325603256132562325633256432565325663256732568325693257032571325723257332574325753257632577325783257932580325813258232583325843258532586325873258832589325903259132592325933259432595325963259732598325993260032601326023260332604326053260632607326083260932610326113261232613326143261532616326173261832619326203262132622326233262432625326263262732628326293263032631326323263332634326353263632637326383263932640326413264232643326443264532646326473264832649326503265132652326533265432655326563265732658326593266032661326623266332664326653266632667326683266932670326713267232673326743267532676326773267832679326803268132682326833268432685326863268732688326893269032691326923269332694326953269632697326983269932700327013270232703327043270532706327073270832709327103271132712327133271432715327163271732718327193272032721327223272332724327253272632727327283272932730327313273232733327343273532736327373273832739327403274132742327433274432745327463274732748327493275032751327523275332754327553275632757327583275932760327613276232763327643276532766327673276832769327703277132772327733277432775327763277732778327793278032781327823278332784327853278632787327883278932790327913279232793327943279532796327973279832799328003280132802328033280432805328063280732808328093281032811328123281332814328153281632817328183281932820328213282232823328243282532826328273282832829328303283132832328333283432835328363283732838328393284032841328423284332844328453284632847328483284932850328513285232853328543285532856328573285832859328603286132862328633286432865328663286732868328693287032871328723287332874328753287632877328783287932880328813288232883328843288532886328873288832889328903289132892328933289432895328963289732898328993290032901329023290332904329053290632907329083290932910329113291232913329143291532916329173291832919329203292132922329233292432925329263292732928329293293032931329323293332934329353293632937329383293932940329413294232943329443294532946329473294832949329503295132952329533295432955329563295732958329593296032961329623296332964329653296632967329683296932970329713297232973329743297532976329773297832979329803298132982329833298432985329863298732988329893299032991329923299332994329953299632997329983299933000
  1. /**
  2. * JSTS. See https://github.com/bjornharrtell/jsts
  3. * https://github.com/bjornharrtell/jsts/blob/master/LICENSE_EDLv1.txt
  4. * https://github.com/bjornharrtell/jsts/blob/master/LICENSE_EPLv1.txt
  5. * @license
  6. */
  7. class NumberUtil {
  8. static equalsWithTolerance(x1, x2, tolerance) {
  9. return Math.abs(x1 - x2) <= tolerance;
  10. }
  11. }
  12. class Exception extends Error {
  13. constructor(message) {
  14. super(message);
  15. this.name = Object.keys({
  16. Exception
  17. })[0];
  18. }
  19. toString() {
  20. return this.message;
  21. }
  22. }
  23. class IllegalArgumentException extends Exception {
  24. constructor(message) {
  25. super(message);
  26. this.name = Object.keys({
  27. IllegalArgumentException
  28. })[0];
  29. }
  30. }
  31. class Long {
  32. constructor(high, low) {
  33. this.low = low || 0;
  34. this.high = high || 0;
  35. }
  36. static toBinaryString(i) {
  37. let mask;
  38. let result = '';
  39. for (mask = 0x80000000; mask > 0; mask >>>= 1) result += (i.high & mask) === mask ? '1' : '0';
  40. for (mask = 0x80000000; mask > 0; mask >>>= 1) result += (i.low & mask) === mask ? '1' : '0';
  41. return result;
  42. }
  43. }
  44. function Double() {}
  45. Double.NaN = NaN;
  46. Double.isNaN = n => Number.isNaN(n);
  47. Double.isInfinite = n => !Number.isFinite(n);
  48. Double.MAX_VALUE = Number.MAX_VALUE;
  49. Double.POSITIVE_INFINITY = Number.POSITIVE_INFINITY;
  50. Double.NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY;
  51. if (typeof Float64Array === 'function' && typeof Int32Array === 'function') // Simple and fast conversion between double and long bits
  52. // using TypedArrays and ArrayViewBuffers.
  53. (function () {
  54. const EXP_BIT_MASK = 0x7ff00000;
  55. const SIGNIF_BIT_MASK = 0xFFFFF;
  56. const f64buf = new Float64Array(1);
  57. const i32buf = new Int32Array(f64buf.buffer);
  58. Double.doubleToLongBits = function (value) {
  59. f64buf[0] = value;
  60. let low = i32buf[0] | 0;
  61. let high = i32buf[1] | 0; // Check for NaN based on values of bit fields, maximum
  62. // exponent and nonzero significand.
  63. if ((high & EXP_BIT_MASK) === EXP_BIT_MASK && (high & SIGNIF_BIT_MASK) !== 0 && low !== 0) {
  64. low = 0 | 0;
  65. high = 0x7ff80000 | 0;
  66. }
  67. return new Long(high, low);
  68. };
  69. Double.longBitsToDouble = function (bits) {
  70. i32buf[0] = bits.low;
  71. i32buf[1] = bits.high;
  72. return f64buf[0];
  73. };
  74. })();else // More complex and slower fallback implementation using
  75. // math and the divide-by-two and multiply-by-two algorithms.
  76. (function () {
  77. const BIAS = 1023;
  78. const log2 = Math.log2;
  79. const floor = Math.floor;
  80. const pow = Math.pow;
  81. const MAX_REL_BITS_INTEGER = function () {
  82. for (let i = 53; i > 0; i--) {
  83. const bits = pow(2, i) - 1;
  84. if (floor(log2(bits)) + 1 === i) return bits;
  85. }
  86. return 0;
  87. }();
  88. Double.doubleToLongBits = function (value) {
  89. let x, y, f, bits, skip;
  90. let sign, exp, high, low; // Get the sign bit and absolute value.
  91. if (value < 0 || 1 / value === Number.NEGATIVE_INFINITY) {
  92. sign = 1 << 31;
  93. value = -value;
  94. } else {
  95. sign = 0;
  96. } // Handle some special values.
  97. if (value === 0) {
  98. // Handle zeros (+/-0).
  99. low = 0 | 0;
  100. high = sign; // exponent: 00..00, significand: 00..00
  101. return new Long(high, low);
  102. }
  103. if (value === Infinity) {
  104. // Handle infinity (only positive values for value possible).
  105. low = 0 | 0;
  106. high = sign | 0x7ff00000; // exponent: 11..11, significand: 00..00
  107. return new Long(high, low);
  108. }
  109. if (value !== value) {
  110. // eslint-disable-line
  111. // Handle NaNs (boiled down to only one distinct NaN).
  112. low = 0 | 0;
  113. high = 0x7ff80000; // exponent: 11..11, significand: 10..00
  114. return new Long(high, low);
  115. } // Preinitialize variables, that are not neccessarily set by
  116. // the algorithm.
  117. bits = 0;
  118. low = 0 | 0; // Get the (always positive) integer part of value.
  119. x = floor(value); // Process the integer part if it's greater than 1. Zero requires
  120. // no bits at all, 1 represents the implicit (hidden) leading bit,
  121. // which must not be written as well.
  122. if (x > 1) // If we can reliably determine the number of bits required for
  123. // the integer part,
  124. if (x <= MAX_REL_BITS_INTEGER) {
  125. // get the number of bits required to represent it minus 1
  126. bits = floor(log2(x));
  127. /* + 1 - 1 */
  128. // and simply copy/shift the integer bits into low and high.
  129. // That's much faster than the divide-by-two algorithm (saves
  130. // up to ~60%).
  131. // We always need to mask out the most significant bit, which
  132. // is the implicit (aka hidden) bit.
  133. if (bits <= 20) {
  134. // The simple case in which the integer fits into the
  135. // lower 20 bits of the high word is worth to be handled
  136. // separately (saves ~25%).
  137. low = 0 | 0;
  138. high = x << 20 - bits & 0xfffff;
  139. } else {
  140. // Here, the integer part is split into low and high.
  141. // Since its value may require more than 32 bits, we
  142. // cannot use bitwise operators (which implicitly cast
  143. // to Int32), but use arithmetic operators % and / to
  144. // get low and high parts. The uppper 20 bits go to high,
  145. // the remaining bits (in f) to low.
  146. f = bits - 20; // Like (1 << f) but safe with even more than 32 bits.
  147. y = pow(2, f);
  148. low = x % y << 32 - f;
  149. high = x / y & 0xfffff;
  150. }
  151. } else {
  152. // For greater values, we must use the much slower divide-by-two
  153. // algorithm. Bits are generated from right to left, that is from
  154. // least to most significant bit. For each bit, we left-shift both
  155. // low and high by one and carry bit #0 from high to #31 in low.
  156. // The next bit is then copied into bit #19 in high, the leftmost
  157. // bit of the double's significand.
  158. // Preserve x for later user, so work with f.
  159. f = x;
  160. low = 0 | 0;
  161. for (;;) {
  162. y = f / 2;
  163. f = floor(y);
  164. if (f === 0) // We just found the most signigicant (1-)bit, which
  165. // is the implicit bit and so, not stored in the double
  166. // value. So, it's time to leave the loop.
  167. break; // Count this bit, shift low and carry bit #0 from high.
  168. bits++;
  169. low >>>= 1;
  170. low |= (high & 0x1) << 31; // Shift high.
  171. high >>>= 1;
  172. if (y !== f) // Copy the new bit into bit #19 in high (only required if 1).
  173. high |= 0x80000;
  174. }
  175. } // Bias the exponent.
  176. exp = bits + BIAS; // If the integer part is zero, we've not yet seen the implicit
  177. // leading bit. Variable skip is later used while processing the
  178. // fractional part (if any).
  179. skip = x === 0; // Get fraction only into x.
  180. x = value - x; // If some significand bits are still left to be filled and
  181. // the fractional part is not zero, convert the fraction using
  182. // the multiply-by-2 algorithm.
  183. if (bits < 52 && x !== 0) {
  184. // Initialize 'buffer' f, into which newly created bits get
  185. // shifted from right to left.
  186. f = 0;
  187. for (;;) {
  188. y = x * 2;
  189. if (y >= 1) {
  190. // This is a new 1-bit. Add and count this bit, if not
  191. // prohibited by skip.
  192. x = y - 1;
  193. if (!skip) {
  194. f <<= 1;
  195. f |= 1;
  196. bits++;
  197. } else {
  198. // Otherwise, decrement the exponent and unset
  199. // skip, so that all following bits get written.
  200. exp--;
  201. skip = false;
  202. }
  203. } else {
  204. // This is a new 0-bit. Add and count this bit, if not
  205. // prohibited by skip.
  206. x = y;
  207. if (!skip) {
  208. f <<= 1;
  209. bits++;
  210. } else if (--exp === 0) {
  211. // Otherwise we've just decremented the exponent. If the
  212. // biased exponent is zero now (-1023), we process a
  213. // subnormal number, which has no impled leading 1-bit.
  214. // So, count this 0-bit and unset skip to write out
  215. // all the following bits.
  216. bits++;
  217. skip = false;
  218. }
  219. }
  220. if (bits === 20) {
  221. // When 20 bits have been created in total, we're done with
  222. // the high word. Copy the bits from 'buffer' f into high
  223. // and reset 'buffer' f. Following bits will end up in the
  224. // low word.
  225. high |= f;
  226. f = 0;
  227. } else if (bits === 52) {
  228. // When 52 bits have been created in total, we're done with
  229. // low word as well. Copy the bits from 'buffer' f into low
  230. // and exit the loop.
  231. low |= f;
  232. break;
  233. }
  234. if (y === 1) {
  235. // When y is exactly 1, there is no remainder and the process
  236. // is complete (the number is finite). Copy the bits from
  237. // 'buffer' f into either low or high and exit the loop.
  238. if (bits < 20) high |= f << 20 - bits;else if (bits < 52) low |= f << 52 - bits;
  239. break;
  240. }
  241. }
  242. } // Copy/shift the exponent and sign bits into the high word.
  243. high |= exp << 20;
  244. high |= sign;
  245. return new Long(high, low);
  246. };
  247. Double.longBitsToDouble = function (bits) {
  248. let i;
  249. let x, exp, fract;
  250. const high = bits.high;
  251. const low = bits.low; // Extract the sign.
  252. const sign = high & 1 << 31 ? -1 : 1; // Extract the unbiased exponent.
  253. exp = ((high & 0x7ff00000) >> 20) - BIAS; // Calculate the fraction from left to right. Start
  254. // off with the 20 lower bits from the high word.
  255. fract = 0;
  256. x = 1 << 19;
  257. for (i = 1; i <= 20; i++) {
  258. if (high & x) fract += pow(2, -i);
  259. x >>>= 1;
  260. } // Continue with all 32 bits from the low word.
  261. x = 1 << 31;
  262. for (i = 21; i <= 52; i++) {
  263. if (low & x) fract += pow(2, -i);
  264. x >>>= 1;
  265. } // Handle special values.
  266. // Check for zero and subnormal values.
  267. if (exp === -BIAS) {
  268. if (fract === 0) // +/-1.0 * 0.0 => +/-0.0
  269. return sign * 0;
  270. exp = -1022;
  271. } else if (exp === BIAS + 1) {
  272. // Check for +/-Infinity or NaN.
  273. if (fract === 0) // +/-1.0 / 0.0 => +/-Infinity
  274. return sign / 0;
  275. return NaN;
  276. } else {
  277. // Nothing special? Seems to be a normal number.
  278. // Add the implicit leading bit (1*2^0).
  279. fract += 1;
  280. }
  281. return sign * fract * pow(2, exp);
  282. };
  283. })();
  284. function Comparable() {}
  285. function Clonable() {}
  286. function Comparator() {}
  287. function Serializable() {}
  288. class RuntimeException extends Exception {
  289. constructor(message) {
  290. super(message);
  291. this.name = Object.keys({
  292. RuntimeException
  293. })[0];
  294. }
  295. }
  296. class AssertionFailedException extends RuntimeException {
  297. constructor() {
  298. super();
  299. AssertionFailedException.constructor_.apply(this, arguments);
  300. }
  301. static constructor_() {
  302. if (arguments.length === 0) {
  303. RuntimeException.constructor_.call(this);
  304. } else if (arguments.length === 1) {
  305. const message = arguments[0];
  306. RuntimeException.constructor_.call(this, message);
  307. }
  308. }
  309. }
  310. class Assert {
  311. static shouldNeverReachHere() {
  312. if (arguments.length === 0) {
  313. Assert.shouldNeverReachHere(null);
  314. } else if (arguments.length === 1) {
  315. const message = arguments[0];
  316. throw new AssertionFailedException('Should never reach here' + (message !== null ? ': ' + message : ''));
  317. }
  318. }
  319. static isTrue() {
  320. if (arguments.length === 1) {
  321. const assertion = arguments[0];
  322. Assert.isTrue(assertion, null);
  323. } else if (arguments.length === 2) {
  324. const assertion = arguments[0],
  325. message = arguments[1];
  326. if (!assertion) if (message === null) throw new AssertionFailedException();else throw new AssertionFailedException(message);
  327. }
  328. }
  329. static equals() {
  330. if (arguments.length === 2) {
  331. const expectedValue = arguments[0],
  332. actualValue = arguments[1];
  333. Assert.equals(expectedValue, actualValue, null);
  334. } else if (arguments.length === 3) {
  335. const expectedValue = arguments[0],
  336. actualValue = arguments[1],
  337. message = arguments[2];
  338. if (!actualValue.equals(expectedValue)) throw new AssertionFailedException('Expected ' + expectedValue + ' but encountered ' + actualValue + (message !== null ? ': ' + message : ''));
  339. }
  340. }
  341. }
  342. const kBuf = new ArrayBuffer(8);
  343. const kBufAsF64 = new Float64Array(kBuf);
  344. const kBufAsI32 = new Int32Array(kBuf);
  345. class Coordinate {
  346. constructor() {
  347. Coordinate.constructor_.apply(this, arguments);
  348. }
  349. static constructor_() {
  350. this.x = null;
  351. this.y = null;
  352. this.z = null;
  353. if (arguments.length === 0) {
  354. Coordinate.constructor_.call(this, 0.0, 0.0);
  355. } else if (arguments.length === 1) {
  356. const c = arguments[0];
  357. Coordinate.constructor_.call(this, c.x, c.y, c.getZ());
  358. } else if (arguments.length === 2) {
  359. const x = arguments[0],
  360. y = arguments[1];
  361. Coordinate.constructor_.call(this, x, y, Coordinate.NULL_ORDINATE);
  362. } else if (arguments.length === 3) {
  363. const x = arguments[0],
  364. y = arguments[1],
  365. z = arguments[2];
  366. this.x = x;
  367. this.y = y;
  368. this.z = z;
  369. }
  370. }
  371. static hashCode(n) {
  372. kBufAsF64[0] = n;
  373. return kBufAsI32[0] ^ kBufAsI32[1];
  374. }
  375. getM() {
  376. return Double.NaN;
  377. }
  378. setOrdinate(ordinateIndex, value) {
  379. switch (ordinateIndex) {
  380. case Coordinate.X:
  381. this.x = value;
  382. break;
  383. case Coordinate.Y:
  384. this.y = value;
  385. break;
  386. case Coordinate.Z:
  387. this.setZ(value);
  388. break;
  389. default:
  390. throw new IllegalArgumentException('Invalid ordinate index: ' + ordinateIndex);
  391. }
  392. }
  393. equals2D() {
  394. if (arguments.length === 1) {
  395. const other = arguments[0];
  396. if (this.x !== other.x) return false;
  397. if (this.y !== other.y) return false;
  398. return true;
  399. } else if (arguments.length === 2) {
  400. const c = arguments[0],
  401. tolerance = arguments[1];
  402. if (!NumberUtil.equalsWithTolerance(this.x, c.x, tolerance)) return false;
  403. if (!NumberUtil.equalsWithTolerance(this.y, c.y, tolerance)) return false;
  404. return true;
  405. }
  406. }
  407. setM(m) {
  408. throw new IllegalArgumentException('Invalid ordinate index: ' + Coordinate.M);
  409. }
  410. getZ() {
  411. return this.z;
  412. }
  413. getOrdinate(ordinateIndex) {
  414. switch (ordinateIndex) {
  415. case Coordinate.X:
  416. return this.x;
  417. case Coordinate.Y:
  418. return this.y;
  419. case Coordinate.Z:
  420. return this.getZ();
  421. }
  422. throw new IllegalArgumentException('Invalid ordinate index: ' + ordinateIndex);
  423. }
  424. equals3D(other) {
  425. return this.x === other.x && this.y === other.y && (this.getZ() === other.getZ() || Double.isNaN(this.getZ()) && Double.isNaN(other.getZ()));
  426. }
  427. equals(other) {
  428. if (!(other instanceof Coordinate)) return false;
  429. return this.equals2D(other);
  430. }
  431. equalInZ(c, tolerance) {
  432. return NumberUtil.equalsWithTolerance(this.getZ(), c.getZ(), tolerance);
  433. }
  434. setX(x) {
  435. this.x = x;
  436. }
  437. compareTo(o) {
  438. const other = o;
  439. if (this.x < other.x) return -1;
  440. if (this.x > other.x) return 1;
  441. if (this.y < other.y) return -1;
  442. if (this.y > other.y) return 1;
  443. return 0;
  444. }
  445. getX() {
  446. return this.x;
  447. }
  448. setZ(z) {
  449. this.z = z;
  450. }
  451. clone() {
  452. try {
  453. const coord = null;
  454. return coord;
  455. } catch (e) {
  456. if (e instanceof CloneNotSupportedException) {
  457. Assert.shouldNeverReachHere('this shouldn\'t happen because this class is Cloneable');
  458. return null;
  459. } else {
  460. throw e;
  461. }
  462. } finally {}
  463. }
  464. copy() {
  465. return new Coordinate(this);
  466. }
  467. toString() {
  468. return '(' + this.x + ', ' + this.y + ', ' + this.getZ() + ')';
  469. }
  470. distance3D(c) {
  471. const dx = this.x - c.x;
  472. const dy = this.y - c.y;
  473. const dz = this.getZ() - c.getZ();
  474. return Math.sqrt(dx * dx + dy * dy + dz * dz);
  475. }
  476. getY() {
  477. return this.y;
  478. }
  479. setY(y) {
  480. this.y = y;
  481. }
  482. distance(c) {
  483. const dx = this.x - c.x;
  484. const dy = this.y - c.y;
  485. return Math.sqrt(dx * dx + dy * dy);
  486. }
  487. hashCode() {
  488. let result = 17;
  489. result = 37 * result + Coordinate.hashCode(this.x);
  490. result = 37 * result + Coordinate.hashCode(this.y);
  491. return result;
  492. }
  493. setCoordinate(other) {
  494. this.x = other.x;
  495. this.y = other.y;
  496. this.z = other.getZ();
  497. }
  498. get interfaces_() {
  499. return [Comparable, Clonable, Serializable];
  500. }
  501. }
  502. class DimensionalComparator {
  503. constructor() {
  504. DimensionalComparator.constructor_.apply(this, arguments);
  505. }
  506. static constructor_() {
  507. this._dimensionsToTest = 2;
  508. if (arguments.length === 0) {
  509. DimensionalComparator.constructor_.call(this, 2);
  510. } else if (arguments.length === 1) {
  511. const dimensionsToTest = arguments[0];
  512. if (dimensionsToTest !== 2 && dimensionsToTest !== 3) throw new IllegalArgumentException('only 2 or 3 dimensions may be specified');
  513. this._dimensionsToTest = dimensionsToTest;
  514. }
  515. }
  516. static compare(a, b) {
  517. if (a < b) return -1;
  518. if (a > b) return 1;
  519. if (Double.isNaN(a)) {
  520. if (Double.isNaN(b)) return 0;
  521. return -1;
  522. }
  523. if (Double.isNaN(b)) return 1;
  524. return 0;
  525. }
  526. compare(c1, c2) {
  527. const compX = DimensionalComparator.compare(c1.x, c2.x);
  528. if (compX !== 0) return compX;
  529. const compY = DimensionalComparator.compare(c1.y, c2.y);
  530. if (compY !== 0) return compY;
  531. if (this._dimensionsToTest <= 2) return 0;
  532. const compZ = DimensionalComparator.compare(c1.getZ(), c2.getZ());
  533. return compZ;
  534. }
  535. get interfaces_() {
  536. return [Comparator];
  537. }
  538. }
  539. Coordinate.DimensionalComparator = DimensionalComparator;
  540. Coordinate.NULL_ORDINATE = Double.NaN;
  541. Coordinate.X = 0;
  542. Coordinate.Y = 1;
  543. Coordinate.Z = 2;
  544. Coordinate.M = 3;
  545. class CoordinateXY extends Coordinate {
  546. constructor() {
  547. super();
  548. CoordinateXY.constructor_.apply(this, arguments);
  549. }
  550. static constructor_() {
  551. if (arguments.length === 0) {
  552. Coordinate.constructor_.call(this);
  553. } else if (arguments.length === 1) {
  554. if (arguments[0] instanceof CoordinateXY) {
  555. const coord = arguments[0];
  556. Coordinate.constructor_.call(this, coord.x, coord.y);
  557. } else if (arguments[0] instanceof Coordinate) {
  558. const coord = arguments[0];
  559. Coordinate.constructor_.call(this, coord.x, coord.y);
  560. }
  561. } else if (arguments.length === 2) {
  562. const x = arguments[0],
  563. y = arguments[1];
  564. Coordinate.constructor_.call(this, x, y, Coordinate.NULL_ORDINATE);
  565. }
  566. }
  567. setOrdinate(ordinateIndex, value) {
  568. switch (ordinateIndex) {
  569. case CoordinateXY.X:
  570. this.x = value;
  571. break;
  572. case CoordinateXY.Y:
  573. this.y = value;
  574. break;
  575. default:
  576. throw new IllegalArgumentException('Invalid ordinate index: ' + ordinateIndex);
  577. }
  578. }
  579. getZ() {
  580. return Coordinate.NULL_ORDINATE;
  581. }
  582. getOrdinate(ordinateIndex) {
  583. switch (ordinateIndex) {
  584. case CoordinateXY.X:
  585. return this.x;
  586. case CoordinateXY.Y:
  587. return this.y;
  588. }
  589. throw new IllegalArgumentException('Invalid ordinate index: ' + ordinateIndex);
  590. }
  591. setZ(z) {
  592. throw new IllegalArgumentException('CoordinateXY dimension 2 does not support z-ordinate');
  593. }
  594. copy() {
  595. return new CoordinateXY(this);
  596. }
  597. toString() {
  598. return '(' + this.x + ', ' + this.y + ')';
  599. }
  600. setCoordinate(other) {
  601. this.x = other.x;
  602. this.y = other.y;
  603. this.z = other.getZ();
  604. }
  605. }
  606. CoordinateXY.X = 0;
  607. CoordinateXY.Y = 1;
  608. CoordinateXY.Z = -1;
  609. CoordinateXY.M = -1;
  610. class CoordinateXYM extends Coordinate {
  611. constructor() {
  612. super();
  613. CoordinateXYM.constructor_.apply(this, arguments);
  614. }
  615. static constructor_() {
  616. this._m = null;
  617. if (arguments.length === 0) {
  618. Coordinate.constructor_.call(this);
  619. this._m = 0.0;
  620. } else if (arguments.length === 1) {
  621. if (arguments[0] instanceof CoordinateXYM) {
  622. const coord = arguments[0];
  623. Coordinate.constructor_.call(this, coord.x, coord.y);
  624. this._m = coord._m;
  625. } else if (arguments[0] instanceof Coordinate) {
  626. const coord = arguments[0];
  627. Coordinate.constructor_.call(this, coord.x, coord.y);
  628. this._m = this.getM();
  629. }
  630. } else if (arguments.length === 3) {
  631. const x = arguments[0],
  632. y = arguments[1],
  633. m = arguments[2];
  634. Coordinate.constructor_.call(this, x, y, Coordinate.NULL_ORDINATE);
  635. this._m = m;
  636. }
  637. }
  638. getM() {
  639. return this._m;
  640. }
  641. setOrdinate(ordinateIndex, value) {
  642. switch (ordinateIndex) {
  643. case CoordinateXYM.X:
  644. this.x = value;
  645. break;
  646. case CoordinateXYM.Y:
  647. this.y = value;
  648. break;
  649. case CoordinateXYM.M:
  650. this._m = value;
  651. break;
  652. default:
  653. throw new IllegalArgumentException('Invalid ordinate index: ' + ordinateIndex);
  654. }
  655. }
  656. setM(m) {
  657. this._m = m;
  658. }
  659. getZ() {
  660. return Coordinate.NULL_ORDINATE;
  661. }
  662. getOrdinate(ordinateIndex) {
  663. switch (ordinateIndex) {
  664. case CoordinateXYM.X:
  665. return this.x;
  666. case CoordinateXYM.Y:
  667. return this.y;
  668. case CoordinateXYM.M:
  669. return this._m;
  670. }
  671. throw new IllegalArgumentException('Invalid ordinate index: ' + ordinateIndex);
  672. }
  673. setZ(z) {
  674. throw new IllegalArgumentException('CoordinateXY dimension 2 does not support z-ordinate');
  675. }
  676. copy() {
  677. return new CoordinateXYM(this);
  678. }
  679. toString() {
  680. return '(' + this.x + ', ' + this.y + ' m=' + this.getM() + ')';
  681. }
  682. setCoordinate(other) {
  683. this.x = other.x;
  684. this.y = other.y;
  685. this.z = other.getZ();
  686. this._m = other.getM();
  687. }
  688. }
  689. CoordinateXYM.X = 0;
  690. CoordinateXYM.Y = 1;
  691. CoordinateXYM.Z = -1;
  692. CoordinateXYM.M = 2;
  693. class CoordinateXYZM extends Coordinate {
  694. constructor() {
  695. super();
  696. CoordinateXYZM.constructor_.apply(this, arguments);
  697. }
  698. static constructor_() {
  699. this._m = null;
  700. if (arguments.length === 0) {
  701. Coordinate.constructor_.call(this);
  702. this._m = 0.0;
  703. } else if (arguments.length === 1) {
  704. if (arguments[0] instanceof CoordinateXYZM) {
  705. const coord = arguments[0];
  706. Coordinate.constructor_.call(this, coord);
  707. this._m = coord._m;
  708. } else if (arguments[0] instanceof Coordinate) {
  709. const coord = arguments[0];
  710. Coordinate.constructor_.call(this, coord);
  711. this._m = this.getM();
  712. }
  713. } else if (arguments.length === 4) {
  714. const x = arguments[0],
  715. y = arguments[1],
  716. z = arguments[2],
  717. m = arguments[3];
  718. Coordinate.constructor_.call(this, x, y, z);
  719. this._m = m;
  720. }
  721. }
  722. getM() {
  723. return this._m;
  724. }
  725. setOrdinate(ordinateIndex, value) {
  726. switch (ordinateIndex) {
  727. case Coordinate.X:
  728. this.x = value;
  729. break;
  730. case Coordinate.Y:
  731. this.y = value;
  732. break;
  733. case Coordinate.Z:
  734. this.z = value;
  735. break;
  736. case Coordinate.M:
  737. this._m = value;
  738. break;
  739. default:
  740. throw new IllegalArgumentException('Invalid ordinate index: ' + ordinateIndex);
  741. }
  742. }
  743. setM(m) {
  744. this._m = m;
  745. }
  746. getOrdinate(ordinateIndex) {
  747. switch (ordinateIndex) {
  748. case Coordinate.X:
  749. return this.x;
  750. case Coordinate.Y:
  751. return this.y;
  752. case Coordinate.Z:
  753. return this.getZ();
  754. case Coordinate.M:
  755. return this.getM();
  756. }
  757. throw new IllegalArgumentException('Invalid ordinate index: ' + ordinateIndex);
  758. }
  759. copy() {
  760. return new CoordinateXYZM(this);
  761. }
  762. toString() {
  763. return '(' + this.x + ', ' + this.y + ', ' + this.getZ() + ' m=' + this.getM() + ')';
  764. }
  765. setCoordinate(other) {
  766. this.x = other.x;
  767. this.y = other.y;
  768. this.z = other.getZ();
  769. this._m = other.getM();
  770. }
  771. }
  772. function hasInterface (o, i) {
  773. return o.interfaces_ && o.interfaces_.indexOf(i) > -1;
  774. }
  775. /**
  776. * @see http://download.oracle.com/javase/6/docs/api/java/util/Collection.html
  777. */
  778. class Collection {
  779. /**
  780. * Ensures that this collection contains the specified element (optional
  781. * operation).
  782. * @param {Object} e
  783. * @return {boolean}
  784. */
  785. add() {}
  786. /**
  787. * Appends all of the elements in the specified collection to the end of this
  788. * list, in the order that they are returned by the specified collection's
  789. * iterator (optional operation).
  790. * @param {javascript.util.Collection} c
  791. * @return {boolean}
  792. */
  793. addAll() {}
  794. /**
  795. * Returns true if this collection contains no elements.
  796. * @return {boolean}
  797. */
  798. isEmpty() {}
  799. /**
  800. * Returns an iterator over the elements in this collection.
  801. * @return {javascript.util.Iterator}
  802. */
  803. iterator() {}
  804. /**
  805. * Returns an iterator over the elements in this collection.
  806. * @return {number}
  807. */
  808. size() {}
  809. /**
  810. * Returns an array containing all of the elements in this collection.
  811. * @return {Array}
  812. */
  813. toArray() {}
  814. /**
  815. * Removes a single instance of the specified element from this collection if it
  816. * is present. (optional)
  817. * @param {Object} e
  818. * @return {boolean}
  819. */
  820. remove() {}
  821. }
  822. class IndexOutOfBoundsException extends Exception {
  823. constructor(message) {
  824. super(message);
  825. this.name = Object.keys({
  826. IndexOutOfBoundsException
  827. })[0];
  828. }
  829. }
  830. /**
  831. * @see http://download.oracle.com/javase/6/docs/api/java/util/List.html
  832. */
  833. class List extends Collection {
  834. /**
  835. * Returns the element at the specified position in this list.
  836. * @param {number} index
  837. * @return {Object}
  838. */
  839. get() {}
  840. /**
  841. * Replaces the element at the specified position in this list with the
  842. * specified element (optional operation).
  843. * @param {number} index
  844. * @param {Object} e
  845. * @return {Object}
  846. */
  847. set() {}
  848. /**
  849. * Returns true if this collection contains no elements.
  850. * @return {boolean}
  851. */
  852. isEmpty() {}
  853. }
  854. class NoSuchElementException extends Exception {
  855. constructor(message) {
  856. super(message);
  857. this.name = Object.keys({
  858. NoSuchElementException
  859. })[0];
  860. }
  861. }
  862. /**
  863. * @see http://download.oracle.com/javase/6/docs/api/java/util/ArrayList.html
  864. */
  865. class ArrayList extends List {
  866. constructor(o) {
  867. super();
  868. this.array = [];
  869. if (o instanceof Collection) this.addAll(o);
  870. }
  871. get interfaces_() {
  872. return [List, Collection];
  873. }
  874. ensureCapacity() {}
  875. add(e) {
  876. if (arguments.length === 1) this.array.push(e);else this.array.splice(arguments[0], 0, arguments[1]);
  877. return true;
  878. }
  879. clear() {
  880. this.array = [];
  881. }
  882. addAll(c) {
  883. for (const e of c) this.array.push(e);
  884. }
  885. set(index, element) {
  886. const oldElement = this.array[index];
  887. this.array[index] = element;
  888. return oldElement;
  889. }
  890. iterator() {
  891. return new Iterator$3(this);
  892. }
  893. get(index) {
  894. if (index < 0 || index >= this.size()) throw new IndexOutOfBoundsException();
  895. return this.array[index];
  896. }
  897. isEmpty() {
  898. return this.array.length === 0;
  899. }
  900. sort(comparator) {
  901. if (comparator) this.array.sort((a, b) => comparator.compare(a, b));else this.array.sort();
  902. }
  903. size() {
  904. return this.array.length;
  905. }
  906. toArray() {
  907. return this.array.slice();
  908. }
  909. remove(o) {
  910. for (let i = 0, len = this.array.length; i < len; i++) if (this.array[i] === o) return !!this.array.splice(i, 1);
  911. return false;
  912. }
  913. [Symbol.iterator]() {
  914. return this.array.values();
  915. }
  916. }
  917. class Iterator$3 {
  918. constructor(arrayList) {
  919. this.arrayList = arrayList;
  920. this.position = 0;
  921. }
  922. next() {
  923. if (this.position === this.arrayList.size()) throw new NoSuchElementException();
  924. return this.arrayList.get(this.position++);
  925. }
  926. hasNext() {
  927. return this.position < this.arrayList.size();
  928. }
  929. set(element) {
  930. return this.arrayList.set(this.position - 1, element);
  931. }
  932. remove() {
  933. this.arrayList.remove(this.arrayList.get(this.position));
  934. }
  935. }
  936. class CoordinateList extends ArrayList {
  937. constructor() {
  938. super();
  939. CoordinateList.constructor_.apply(this, arguments);
  940. }
  941. static constructor_() {
  942. if (arguments.length === 0) ; else if (arguments.length === 1) {
  943. const coord = arguments[0];
  944. this.ensureCapacity(coord.length);
  945. this.add(coord, true);
  946. } else if (arguments.length === 2) {
  947. const coord = arguments[0],
  948. allowRepeated = arguments[1];
  949. this.ensureCapacity(coord.length);
  950. this.add(coord, allowRepeated);
  951. }
  952. }
  953. getCoordinate(i) {
  954. return this.get(i);
  955. }
  956. addAll() {
  957. if (arguments.length === 2 && typeof arguments[1] === 'boolean' && hasInterface(arguments[0], Collection)) {
  958. const coll = arguments[0],
  959. allowRepeated = arguments[1];
  960. let isChanged = false;
  961. for (let i = coll.iterator(); i.hasNext();) {
  962. this.add(i.next(), allowRepeated);
  963. isChanged = true;
  964. }
  965. return isChanged;
  966. } else {
  967. return super.addAll.apply(this, arguments);
  968. }
  969. }
  970. clone() {
  971. const clone = super.clone.call(this);
  972. for (let i = 0; i < this.size(); i++) clone.add(i, this.get(i).clone());
  973. return clone;
  974. }
  975. toCoordinateArray() {
  976. if (arguments.length === 0) {
  977. return this.toArray(CoordinateList.coordArrayType);
  978. } else if (arguments.length === 1) {
  979. const isForward = arguments[0];
  980. if (isForward) return this.toArray(CoordinateList.coordArrayType);
  981. const size = this.size();
  982. const pts = new Array(size).fill(null);
  983. for (let i = 0; i < size; i++) pts[i] = this.get(size - i - 1);
  984. return pts;
  985. }
  986. }
  987. add() {
  988. if (arguments.length === 1) {
  989. const coord = arguments[0];
  990. return super.add.call(this, coord);
  991. } else if (arguments.length === 2) {
  992. if (arguments[0] instanceof Array && typeof arguments[1] === 'boolean') {
  993. const coord = arguments[0],
  994. allowRepeated = arguments[1];
  995. this.add(coord, allowRepeated, true);
  996. return true;
  997. } else if (arguments[0] instanceof Coordinate && typeof arguments[1] === 'boolean') {
  998. const coord = arguments[0],
  999. allowRepeated = arguments[1];
  1000. if (!allowRepeated) if (this.size() >= 1) {
  1001. const last = this.get(this.size() - 1);
  1002. if (last.equals2D(coord)) return null;
  1003. }
  1004. super.add.call(this, coord);
  1005. } else if (arguments[0] instanceof Object && typeof arguments[1] === 'boolean') {
  1006. const obj = arguments[0],
  1007. allowRepeated = arguments[1];
  1008. this.add(obj, allowRepeated);
  1009. return true;
  1010. }
  1011. } else if (arguments.length === 3) {
  1012. if (typeof arguments[2] === 'boolean' && arguments[0] instanceof Array && typeof arguments[1] === 'boolean') {
  1013. const coord = arguments[0],
  1014. allowRepeated = arguments[1],
  1015. direction = arguments[2];
  1016. if (direction) for (let i = 0; i < coord.length; i++) this.add(coord[i], allowRepeated);else for (let i = coord.length - 1; i >= 0; i--) this.add(coord[i], allowRepeated);
  1017. return true;
  1018. } else if (typeof arguments[2] === 'boolean' && Number.isInteger(arguments[0]) && arguments[1] instanceof Coordinate) {
  1019. const i = arguments[0],
  1020. coord = arguments[1],
  1021. allowRepeated = arguments[2];
  1022. if (!allowRepeated) {
  1023. const size = this.size();
  1024. if (size > 0) {
  1025. if (i > 0) {
  1026. const prev = this.get(i - 1);
  1027. if (prev.equals2D(coord)) return null;
  1028. }
  1029. if (i < size) {
  1030. const next = this.get(i);
  1031. if (next.equals2D(coord)) return null;
  1032. }
  1033. }
  1034. }
  1035. super.add.call(this, i, coord);
  1036. }
  1037. } else if (arguments.length === 4) {
  1038. const coord = arguments[0],
  1039. allowRepeated = arguments[1],
  1040. start = arguments[2],
  1041. end = arguments[3];
  1042. let inc = 1;
  1043. if (start > end) inc = -1;
  1044. for (let i = start; i !== end; i += inc) this.add(coord[i], allowRepeated);
  1045. return true;
  1046. }
  1047. }
  1048. closeRing() {
  1049. if (this.size() > 0) {
  1050. const duplicate = this.get(0).copy();
  1051. this.add(duplicate, false);
  1052. }
  1053. }
  1054. }
  1055. CoordinateList.coordArrayType = new Array(0).fill(null);
  1056. class CoordinateSequenceFilter {
  1057. filter(seq, i) {}
  1058. isDone() {}
  1059. isGeometryChanged() {}
  1060. }
  1061. class Envelope {
  1062. constructor() {
  1063. Envelope.constructor_.apply(this, arguments);
  1064. }
  1065. static constructor_() {
  1066. this._minx = null;
  1067. this._maxx = null;
  1068. this._miny = null;
  1069. this._maxy = null;
  1070. if (arguments.length === 0) {
  1071. this.init();
  1072. } else if (arguments.length === 1) {
  1073. if (arguments[0] instanceof Coordinate) {
  1074. const p = arguments[0];
  1075. this.init(p.x, p.x, p.y, p.y);
  1076. } else if (arguments[0] instanceof Envelope) {
  1077. const env = arguments[0];
  1078. this.init(env);
  1079. }
  1080. } else if (arguments.length === 2) {
  1081. const p1 = arguments[0],
  1082. p2 = arguments[1];
  1083. this.init(p1.x, p2.x, p1.y, p2.y);
  1084. } else if (arguments.length === 4) {
  1085. const x1 = arguments[0],
  1086. x2 = arguments[1],
  1087. y1 = arguments[2],
  1088. y2 = arguments[3];
  1089. this.init(x1, x2, y1, y2);
  1090. }
  1091. }
  1092. static intersects() {
  1093. if (arguments.length === 3) {
  1094. const p1 = arguments[0],
  1095. p2 = arguments[1],
  1096. q = arguments[2];
  1097. 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)) return true;
  1098. return false;
  1099. } else if (arguments.length === 4) {
  1100. const p1 = arguments[0],
  1101. p2 = arguments[1],
  1102. q1 = arguments[2],
  1103. q2 = arguments[3];
  1104. let minq = Math.min(q1.x, q2.x);
  1105. let maxq = Math.max(q1.x, q2.x);
  1106. let minp = Math.min(p1.x, p2.x);
  1107. let maxp = Math.max(p1.x, p2.x);
  1108. if (minp > maxq) return false;
  1109. if (maxp < minq) return false;
  1110. minq = Math.min(q1.y, q2.y);
  1111. maxq = Math.max(q1.y, q2.y);
  1112. minp = Math.min(p1.y, p2.y);
  1113. maxp = Math.max(p1.y, p2.y);
  1114. if (minp > maxq) return false;
  1115. if (maxp < minq) return false;
  1116. return true;
  1117. }
  1118. }
  1119. getArea() {
  1120. return this.getWidth() * this.getHeight();
  1121. }
  1122. equals(other) {
  1123. if (!(other instanceof Envelope)) return false;
  1124. const otherEnvelope = other;
  1125. if (this.isNull()) return otherEnvelope.isNull();
  1126. return this._maxx === otherEnvelope.getMaxX() && this._maxy === otherEnvelope.getMaxY() && this._minx === otherEnvelope.getMinX() && this._miny === otherEnvelope.getMinY();
  1127. }
  1128. intersection(env) {
  1129. if (this.isNull() || env.isNull() || !this.intersects(env)) return new Envelope();
  1130. const intMinX = this._minx > env._minx ? this._minx : env._minx;
  1131. const intMinY = this._miny > env._miny ? this._miny : env._miny;
  1132. const intMaxX = this._maxx < env._maxx ? this._maxx : env._maxx;
  1133. const intMaxY = this._maxy < env._maxy ? this._maxy : env._maxy;
  1134. return new Envelope(intMinX, intMaxX, intMinY, intMaxY);
  1135. }
  1136. isNull() {
  1137. return this._maxx < this._minx;
  1138. }
  1139. getMaxX() {
  1140. return this._maxx;
  1141. }
  1142. covers() {
  1143. if (arguments.length === 1) {
  1144. if (arguments[0] instanceof Coordinate) {
  1145. const p = arguments[0];
  1146. return this.covers(p.x, p.y);
  1147. } else if (arguments[0] instanceof Envelope) {
  1148. const other = arguments[0];
  1149. if (this.isNull() || other.isNull()) return false;
  1150. return other.getMinX() >= this._minx && other.getMaxX() <= this._maxx && other.getMinY() >= this._miny && other.getMaxY() <= this._maxy;
  1151. }
  1152. } else if (arguments.length === 2) {
  1153. const x = arguments[0],
  1154. y = arguments[1];
  1155. if (this.isNull()) return false;
  1156. return x >= this._minx && x <= this._maxx && y >= this._miny && y <= this._maxy;
  1157. }
  1158. }
  1159. intersects() {
  1160. if (arguments.length === 1) {
  1161. if (arguments[0] instanceof Envelope) {
  1162. const other = arguments[0];
  1163. if (this.isNull() || other.isNull()) return false;
  1164. return !(other._minx > this._maxx || other._maxx < this._minx || other._miny > this._maxy || other._maxy < this._miny);
  1165. } else if (arguments[0] instanceof Coordinate) {
  1166. const p = arguments[0];
  1167. return this.intersects(p.x, p.y);
  1168. }
  1169. } else if (arguments.length === 2) {
  1170. if (arguments[0] instanceof Coordinate && arguments[1] instanceof Coordinate) {
  1171. const a = arguments[0],
  1172. b = arguments[1];
  1173. if (this.isNull()) return false;
  1174. const envminx = a.x < b.x ? a.x : b.x;
  1175. if (envminx > this._maxx) return false;
  1176. const envmaxx = a.x > b.x ? a.x : b.x;
  1177. if (envmaxx < this._minx) return false;
  1178. const envminy = a.y < b.y ? a.y : b.y;
  1179. if (envminy > this._maxy) return false;
  1180. const envmaxy = a.y > b.y ? a.y : b.y;
  1181. if (envmaxy < this._miny) return false;
  1182. return true;
  1183. } else if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') {
  1184. const x = arguments[0],
  1185. y = arguments[1];
  1186. if (this.isNull()) return false;
  1187. return !(x > this._maxx || x < this._minx || y > this._maxy || y < this._miny);
  1188. }
  1189. }
  1190. }
  1191. getMinY() {
  1192. return this._miny;
  1193. }
  1194. getDiameter() {
  1195. if (this.isNull()) return 0;
  1196. const w = this.getWidth();
  1197. const h = this.getHeight();
  1198. return Math.sqrt(w * w + h * h);
  1199. }
  1200. getMinX() {
  1201. return this._minx;
  1202. }
  1203. expandToInclude() {
  1204. if (arguments.length === 1) {
  1205. if (arguments[0] instanceof Coordinate) {
  1206. const p = arguments[0];
  1207. this.expandToInclude(p.x, p.y);
  1208. } else if (arguments[0] instanceof Envelope) {
  1209. const other = arguments[0];
  1210. if (other.isNull()) return null;
  1211. if (this.isNull()) {
  1212. this._minx = other.getMinX();
  1213. this._maxx = other.getMaxX();
  1214. this._miny = other.getMinY();
  1215. this._maxy = other.getMaxY();
  1216. } else {
  1217. if (other._minx < this._minx) this._minx = other._minx;
  1218. if (other._maxx > this._maxx) this._maxx = other._maxx;
  1219. if (other._miny < this._miny) this._miny = other._miny;
  1220. if (other._maxy > this._maxy) this._maxy = other._maxy;
  1221. }
  1222. }
  1223. } else if (arguments.length === 2) {
  1224. const x = arguments[0],
  1225. y = arguments[1];
  1226. if (this.isNull()) {
  1227. this._minx = x;
  1228. this._maxx = x;
  1229. this._miny = y;
  1230. this._maxy = y;
  1231. } else {
  1232. if (x < this._minx) this._minx = x;
  1233. if (x > this._maxx) this._maxx = x;
  1234. if (y < this._miny) this._miny = y;
  1235. if (y > this._maxy) this._maxy = y;
  1236. }
  1237. }
  1238. }
  1239. minExtent() {
  1240. if (this.isNull()) return 0.0;
  1241. const w = this.getWidth();
  1242. const h = this.getHeight();
  1243. if (w < h) return w;
  1244. return h;
  1245. }
  1246. getWidth() {
  1247. if (this.isNull()) return 0;
  1248. return this._maxx - this._minx;
  1249. }
  1250. compareTo(o) {
  1251. const env = o;
  1252. if (this.isNull()) {
  1253. if (env.isNull()) return 0;
  1254. return -1;
  1255. } else {
  1256. if (env.isNull()) return 1;
  1257. }
  1258. if (this._minx < env._minx) return -1;
  1259. if (this._minx > env._minx) return 1;
  1260. if (this._miny < env._miny) return -1;
  1261. if (this._miny > env._miny) return 1;
  1262. if (this._maxx < env._maxx) return -1;
  1263. if (this._maxx > env._maxx) return 1;
  1264. if (this._maxy < env._maxy) return -1;
  1265. if (this._maxy > env._maxy) return 1;
  1266. return 0;
  1267. }
  1268. translate(transX, transY) {
  1269. if (this.isNull()) return null;
  1270. this.init(this.getMinX() + transX, this.getMaxX() + transX, this.getMinY() + transY, this.getMaxY() + transY);
  1271. }
  1272. copy() {
  1273. return new Envelope(this);
  1274. }
  1275. toString() {
  1276. return 'Env[' + this._minx + ' : ' + this._maxx + ', ' + this._miny + ' : ' + this._maxy + ']';
  1277. }
  1278. setToNull() {
  1279. this._minx = 0;
  1280. this._maxx = -1;
  1281. this._miny = 0;
  1282. this._maxy = -1;
  1283. }
  1284. disjoint(other) {
  1285. if (this.isNull() || other.isNull()) return true;
  1286. return other._minx > this._maxx || other._maxx < this._minx || other._miny > this._maxy || other._maxy < this._miny;
  1287. }
  1288. getHeight() {
  1289. if (this.isNull()) return 0;
  1290. return this._maxy - this._miny;
  1291. }
  1292. maxExtent() {
  1293. if (this.isNull()) return 0.0;
  1294. const w = this.getWidth();
  1295. const h = this.getHeight();
  1296. if (w > h) return w;
  1297. return h;
  1298. }
  1299. expandBy() {
  1300. if (arguments.length === 1) {
  1301. const distance = arguments[0];
  1302. this.expandBy(distance, distance);
  1303. } else if (arguments.length === 2) {
  1304. const deltaX = arguments[0],
  1305. deltaY = arguments[1];
  1306. if (this.isNull()) return null;
  1307. this._minx -= deltaX;
  1308. this._maxx += deltaX;
  1309. this._miny -= deltaY;
  1310. this._maxy += deltaY;
  1311. if (this._minx > this._maxx || this._miny > this._maxy) this.setToNull();
  1312. }
  1313. }
  1314. contains() {
  1315. if (arguments.length === 1) {
  1316. if (arguments[0] instanceof Envelope) {
  1317. const other = arguments[0];
  1318. return this.covers(other);
  1319. } else if (arguments[0] instanceof Coordinate) {
  1320. const p = arguments[0];
  1321. return this.covers(p);
  1322. }
  1323. } else if (arguments.length === 2) {
  1324. const x = arguments[0],
  1325. y = arguments[1];
  1326. return this.covers(x, y);
  1327. }
  1328. }
  1329. centre() {
  1330. if (this.isNull()) return null;
  1331. return new Coordinate((this.getMinX() + this.getMaxX()) / 2.0, (this.getMinY() + this.getMaxY()) / 2.0);
  1332. }
  1333. init() {
  1334. if (arguments.length === 0) {
  1335. this.setToNull();
  1336. } else if (arguments.length === 1) {
  1337. if (arguments[0] instanceof Coordinate) {
  1338. const p = arguments[0];
  1339. this.init(p.x, p.x, p.y, p.y);
  1340. } else if (arguments[0] instanceof Envelope) {
  1341. const env = arguments[0];
  1342. this._minx = env._minx;
  1343. this._maxx = env._maxx;
  1344. this._miny = env._miny;
  1345. this._maxy = env._maxy;
  1346. }
  1347. } else if (arguments.length === 2) {
  1348. const p1 = arguments[0],
  1349. p2 = arguments[1];
  1350. this.init(p1.x, p2.x, p1.y, p2.y);
  1351. } else if (arguments.length === 4) {
  1352. const x1 = arguments[0],
  1353. x2 = arguments[1],
  1354. y1 = arguments[2],
  1355. y2 = arguments[3];
  1356. if (x1 < x2) {
  1357. this._minx = x1;
  1358. this._maxx = x2;
  1359. } else {
  1360. this._minx = x2;
  1361. this._maxx = x1;
  1362. }
  1363. if (y1 < y2) {
  1364. this._miny = y1;
  1365. this._maxy = y2;
  1366. } else {
  1367. this._miny = y2;
  1368. this._maxy = y1;
  1369. }
  1370. }
  1371. }
  1372. getMaxY() {
  1373. return this._maxy;
  1374. }
  1375. distance(env) {
  1376. if (this.intersects(env)) return 0;
  1377. let dx = 0.0;
  1378. if (this._maxx < env._minx) dx = env._minx - this._maxx;else if (this._minx > env._maxx) dx = this._minx - env._maxx;
  1379. let dy = 0.0;
  1380. if (this._maxy < env._miny) dy = env._miny - this._maxy;else if (this._miny > env._maxy) dy = this._miny - env._maxy;
  1381. if (dx === 0.0) return dy;
  1382. if (dy === 0.0) return dx;
  1383. return Math.sqrt(dx * dx + dy * dy);
  1384. }
  1385. hashCode() {
  1386. let result = 17;
  1387. result = 37 * result + Coordinate.hashCode(this._minx);
  1388. result = 37 * result + Coordinate.hashCode(this._maxx);
  1389. result = 37 * result + Coordinate.hashCode(this._miny);
  1390. result = 37 * result + Coordinate.hashCode(this._maxy);
  1391. return result;
  1392. }
  1393. get interfaces_() {
  1394. return [Comparable, Serializable];
  1395. }
  1396. }
  1397. class StringBuffer {
  1398. constructor(str) {
  1399. this.str = str;
  1400. }
  1401. append(e) {
  1402. this.str += e;
  1403. }
  1404. setCharAt(i, c) {
  1405. this.str = this.str.substr(0, i) + c + this.str.substr(i + 1);
  1406. }
  1407. toString() {
  1408. return this.str;
  1409. }
  1410. }
  1411. class Integer {
  1412. constructor(value) {
  1413. this.value = value;
  1414. }
  1415. intValue() {
  1416. return this.value;
  1417. }
  1418. compareTo(o) {
  1419. if (this.value < o) return -1;
  1420. if (this.value > o) return 1;
  1421. return 0;
  1422. }
  1423. static compare(x, y) {
  1424. if (x < y) return -1;
  1425. if (x > y) return 1;
  1426. return 0;
  1427. }
  1428. static isNan(n) {
  1429. return Number.isNaN(n);
  1430. }
  1431. static valueOf(value) {
  1432. return new Integer(value);
  1433. }
  1434. }
  1435. class Character {
  1436. static isWhitespace(c) {
  1437. return c <= 32 && c >= 0 || c === 127;
  1438. }
  1439. static toUpperCase(c) {
  1440. return c.toUpperCase();
  1441. }
  1442. }
  1443. class DD {
  1444. constructor() {
  1445. DD.constructor_.apply(this, arguments);
  1446. }
  1447. static constructor_() {
  1448. this._hi = 0.0;
  1449. this._lo = 0.0;
  1450. if (arguments.length === 0) {
  1451. this.init(0.0);
  1452. } else if (arguments.length === 1) {
  1453. if (typeof arguments[0] === 'number') {
  1454. const x = arguments[0];
  1455. this.init(x);
  1456. } else if (arguments[0] instanceof DD) {
  1457. const dd = arguments[0];
  1458. this.init(dd);
  1459. } else if (typeof arguments[0] === 'string') {
  1460. const str = arguments[0];
  1461. DD.constructor_.call(this, DD.parse(str));
  1462. }
  1463. } else if (arguments.length === 2) {
  1464. const hi = arguments[0],
  1465. lo = arguments[1];
  1466. this.init(hi, lo);
  1467. }
  1468. }
  1469. static determinant() {
  1470. if (typeof arguments[3] === 'number' && typeof arguments[2] === 'number' && typeof arguments[0] === 'number' && typeof arguments[1] === 'number') {
  1471. const x1 = arguments[0],
  1472. y1 = arguments[1],
  1473. x2 = arguments[2],
  1474. y2 = arguments[3];
  1475. return DD.determinant(DD.valueOf(x1), DD.valueOf(y1), DD.valueOf(x2), DD.valueOf(y2));
  1476. } else if (arguments[3] instanceof DD && arguments[2] instanceof DD && arguments[0] instanceof DD && arguments[1] instanceof DD) {
  1477. const x1 = arguments[0],
  1478. y1 = arguments[1],
  1479. x2 = arguments[2],
  1480. y2 = arguments[3];
  1481. const det = x1.multiply(y2).selfSubtract(y1.multiply(x2));
  1482. return det;
  1483. }
  1484. }
  1485. static sqr(x) {
  1486. return DD.valueOf(x).selfMultiply(x);
  1487. }
  1488. static valueOf() {
  1489. if (typeof arguments[0] === 'string') {
  1490. const str = arguments[0];
  1491. return DD.parse(str);
  1492. } else if (typeof arguments[0] === 'number') {
  1493. const x = arguments[0];
  1494. return new DD(x);
  1495. }
  1496. }
  1497. static sqrt(x) {
  1498. return DD.valueOf(x).sqrt();
  1499. }
  1500. static parse(str) {
  1501. let i = 0;
  1502. const strlen = str.length;
  1503. while (Character.isWhitespace(str.charAt(i))) i++;
  1504. let isNegative = false;
  1505. if (i < strlen) {
  1506. const signCh = str.charAt(i);
  1507. if (signCh === '-' || signCh === '+') {
  1508. i++;
  1509. if (signCh === '-') isNegative = true;
  1510. }
  1511. }
  1512. const val = new DD();
  1513. let numDigits = 0;
  1514. let numBeforeDec = 0;
  1515. let exp = 0;
  1516. let hasDecimalChar = false;
  1517. while (true) {
  1518. if (i >= strlen) break;
  1519. const ch = str.charAt(i);
  1520. i++;
  1521. if (Character.isDigit(ch)) {
  1522. const d = ch - '0';
  1523. val.selfMultiply(DD.TEN);
  1524. val.selfAdd(d);
  1525. numDigits++;
  1526. continue;
  1527. }
  1528. if (ch === '.') {
  1529. numBeforeDec = numDigits;
  1530. hasDecimalChar = true;
  1531. continue;
  1532. }
  1533. if (ch === 'e' || ch === 'E') {
  1534. const expStr = str.substring(i);
  1535. try {
  1536. exp = Integer.parseInt(expStr);
  1537. } catch (ex) {
  1538. if (ex instanceof NumberFormatException) throw new NumberFormatException('Invalid exponent ' + expStr + ' in string ' + str);else throw ex;
  1539. } finally {}
  1540. break;
  1541. }
  1542. throw new NumberFormatException('Unexpected character \'' + ch + '\' at position ' + i + ' in string ' + str);
  1543. }
  1544. let val2 = val;
  1545. if (!hasDecimalChar) numBeforeDec = numDigits;
  1546. const numDecPlaces = numDigits - numBeforeDec - exp;
  1547. if (numDecPlaces === 0) {
  1548. val2 = val;
  1549. } else if (numDecPlaces > 0) {
  1550. const scale = DD.TEN.pow(numDecPlaces);
  1551. val2 = val.divide(scale);
  1552. } else if (numDecPlaces < 0) {
  1553. const scale = DD.TEN.pow(-numDecPlaces);
  1554. val2 = val.multiply(scale);
  1555. }
  1556. if (isNegative) return val2.negate();
  1557. return val2;
  1558. }
  1559. static createNaN() {
  1560. return new DD(Double.NaN, Double.NaN);
  1561. }
  1562. static copy(dd) {
  1563. return new DD(dd);
  1564. }
  1565. static magnitude(x) {
  1566. const xAbs = Math.abs(x);
  1567. const xLog10 = Math.log(xAbs) / Math.log(10);
  1568. let xMag = Math.trunc(Math.floor(xLog10));
  1569. const xApprox = Math.pow(10, xMag);
  1570. if (xApprox * 10 <= xAbs) xMag += 1;
  1571. return xMag;
  1572. }
  1573. static stringOfChar(ch, len) {
  1574. const buf = new StringBuffer();
  1575. for (let i = 0; i < len; i++) buf.append(ch);
  1576. return buf.toString();
  1577. }
  1578. le(y) {
  1579. return this._hi < y._hi || this._hi === y._hi && this._lo <= y._lo;
  1580. }
  1581. extractSignificantDigits(insertDecimalPoint, magnitude) {
  1582. let y = this.abs();
  1583. let mag = DD.magnitude(y._hi);
  1584. const scale = DD.TEN.pow(mag);
  1585. y = y.divide(scale);
  1586. if (y.gt(DD.TEN)) {
  1587. y = y.divide(DD.TEN);
  1588. mag += 1;
  1589. } else if (y.lt(DD.ONE)) {
  1590. y = y.multiply(DD.TEN);
  1591. mag -= 1;
  1592. }
  1593. const decimalPointPos = mag + 1;
  1594. const buf = new StringBuffer();
  1595. const numDigits = DD.MAX_PRINT_DIGITS - 1;
  1596. for (let i = 0; i <= numDigits; i++) {
  1597. if (insertDecimalPoint && i === decimalPointPos) buf.append('.');
  1598. const digit = Math.trunc(y._hi);
  1599. if (digit < 0) break;
  1600. let rebiasBy10 = false;
  1601. let digitChar = 0;
  1602. if (digit > 9) {
  1603. rebiasBy10 = true;
  1604. digitChar = '9';
  1605. } else {
  1606. digitChar = '0' + digit;
  1607. }
  1608. buf.append(digitChar);
  1609. y = y.subtract(DD.valueOf(digit)).multiply(DD.TEN);
  1610. if (rebiasBy10) y.selfAdd(DD.TEN);
  1611. let continueExtractingDigits = true;
  1612. const remMag = DD.magnitude(y._hi);
  1613. if (remMag < 0 && Math.abs(remMag) >= numDigits - i) continueExtractingDigits = false;
  1614. if (!continueExtractingDigits) break;
  1615. }
  1616. magnitude[0] = mag;
  1617. return buf.toString();
  1618. }
  1619. sqr() {
  1620. return this.multiply(this);
  1621. }
  1622. doubleValue() {
  1623. return this._hi + this._lo;
  1624. }
  1625. subtract() {
  1626. if (arguments[0] instanceof DD) {
  1627. const y = arguments[0];
  1628. return this.add(y.negate());
  1629. } else if (typeof arguments[0] === 'number') {
  1630. const y = arguments[0];
  1631. return this.add(-y);
  1632. }
  1633. }
  1634. equals() {
  1635. if (arguments.length === 1 && arguments[0] instanceof DD) {
  1636. const y = arguments[0];
  1637. return this._hi === y._hi && this._lo === y._lo;
  1638. }
  1639. }
  1640. isZero() {
  1641. return this._hi === 0.0 && this._lo === 0.0;
  1642. }
  1643. selfSubtract() {
  1644. if (arguments[0] instanceof DD) {
  1645. const y = arguments[0];
  1646. if (this.isNaN()) return this;
  1647. return this.selfAdd(-y._hi, -y._lo);
  1648. } else if (typeof arguments[0] === 'number') {
  1649. const y = arguments[0];
  1650. if (this.isNaN()) return this;
  1651. return this.selfAdd(-y, 0.0);
  1652. }
  1653. }
  1654. getSpecialNumberString() {
  1655. if (this.isZero()) return '0.0';
  1656. if (this.isNaN()) return 'NaN ';
  1657. return null;
  1658. }
  1659. min(x) {
  1660. if (this.le(x)) return this;else return x;
  1661. }
  1662. selfDivide() {
  1663. if (arguments.length === 1) {
  1664. if (arguments[0] instanceof DD) {
  1665. const y = arguments[0];
  1666. return this.selfDivide(y._hi, y._lo);
  1667. } else if (typeof arguments[0] === 'number') {
  1668. const y = arguments[0];
  1669. return this.selfDivide(y, 0.0);
  1670. }
  1671. } else if (arguments.length === 2) {
  1672. const yhi = arguments[0],
  1673. ylo = arguments[1];
  1674. let hc = null,
  1675. tc = null,
  1676. hy = null,
  1677. ty = null,
  1678. C = null,
  1679. c = null,
  1680. U = null,
  1681. u = null;
  1682. C = this._hi / yhi;
  1683. c = DD.SPLIT * C;
  1684. hc = c - C;
  1685. u = DD.SPLIT * yhi;
  1686. hc = c - hc;
  1687. tc = C - hc;
  1688. hy = u - yhi;
  1689. U = C * yhi;
  1690. hy = u - hy;
  1691. ty = yhi - hy;
  1692. u = hc * hy - U + hc * ty + tc * hy + tc * ty;
  1693. c = (this._hi - U - u + this._lo - C * ylo) / yhi;
  1694. u = C + c;
  1695. this._hi = u;
  1696. this._lo = C - u + c;
  1697. return this;
  1698. }
  1699. }
  1700. dump() {
  1701. return 'DD<' + this._hi + ', ' + this._lo + '>';
  1702. }
  1703. divide() {
  1704. if (arguments[0] instanceof DD) {
  1705. const y = arguments[0];
  1706. let hc = null,
  1707. tc = null,
  1708. hy = null,
  1709. ty = null,
  1710. C = null,
  1711. c = null,
  1712. U = null,
  1713. u = null;
  1714. C = this._hi / y._hi;
  1715. c = DD.SPLIT * C;
  1716. hc = c - C;
  1717. u = DD.SPLIT * y._hi;
  1718. hc = c - hc;
  1719. tc = C - hc;
  1720. hy = u - y._hi;
  1721. U = C * y._hi;
  1722. hy = u - hy;
  1723. ty = y._hi - hy;
  1724. u = hc * hy - U + hc * ty + tc * hy + tc * ty;
  1725. c = (this._hi - U - u + this._lo - C * y._lo) / y._hi;
  1726. u = C + c;
  1727. const zhi = u;
  1728. const zlo = C - u + c;
  1729. return new DD(zhi, zlo);
  1730. } else if (typeof arguments[0] === 'number') {
  1731. const y = arguments[0];
  1732. if (Double.isNaN(y)) return DD.createNaN();
  1733. return DD.copy(this).selfDivide(y, 0.0);
  1734. }
  1735. }
  1736. ge(y) {
  1737. return this._hi > y._hi || this._hi === y._hi && this._lo >= y._lo;
  1738. }
  1739. pow(exp) {
  1740. if (exp === 0.0) return DD.valueOf(1.0);
  1741. let r = new DD(this);
  1742. let s = DD.valueOf(1.0);
  1743. let n = Math.abs(exp);
  1744. if (n > 1) while (n > 0) {
  1745. if (n % 2 === 1) s.selfMultiply(r);
  1746. n /= 2;
  1747. if (n > 0) r = r.sqr();
  1748. } else s = r;
  1749. if (exp < 0) return s.reciprocal();
  1750. return s;
  1751. }
  1752. ceil() {
  1753. if (this.isNaN()) return DD.NaN;
  1754. const fhi = Math.ceil(this._hi);
  1755. let flo = 0.0;
  1756. if (fhi === this._hi) flo = Math.ceil(this._lo);
  1757. return new DD(fhi, flo);
  1758. }
  1759. compareTo(o) {
  1760. const other = o;
  1761. if (this._hi < other._hi) return -1;
  1762. if (this._hi > other._hi) return 1;
  1763. if (this._lo < other._lo) return -1;
  1764. if (this._lo > other._lo) return 1;
  1765. return 0;
  1766. }
  1767. rint() {
  1768. if (this.isNaN()) return this;
  1769. const plus5 = this.add(0.5);
  1770. return plus5.floor();
  1771. }
  1772. setValue() {
  1773. if (arguments[0] instanceof DD) {
  1774. const value = arguments[0];
  1775. this.init(value);
  1776. return this;
  1777. } else if (typeof arguments[0] === 'number') {
  1778. const value = arguments[0];
  1779. this.init(value);
  1780. return this;
  1781. }
  1782. }
  1783. max(x) {
  1784. if (this.ge(x)) return this;else return x;
  1785. }
  1786. sqrt() {
  1787. if (this.isZero()) return DD.valueOf(0.0);
  1788. if (this.isNegative()) return DD.NaN;
  1789. const x = 1.0 / Math.sqrt(this._hi);
  1790. const ax = this._hi * x;
  1791. const axdd = DD.valueOf(ax);
  1792. const diffSq = this.subtract(axdd.sqr());
  1793. const d2 = diffSq._hi * (x * 0.5);
  1794. return axdd.add(d2);
  1795. }
  1796. selfAdd() {
  1797. if (arguments.length === 1) {
  1798. if (arguments[0] instanceof DD) {
  1799. const y = arguments[0];
  1800. return this.selfAdd(y._hi, y._lo);
  1801. } else if (typeof arguments[0] === 'number') {
  1802. const y = arguments[0];
  1803. let H = null,
  1804. h = null,
  1805. S = null,
  1806. s = null,
  1807. e = null,
  1808. f = null;
  1809. S = this._hi + y;
  1810. e = S - this._hi;
  1811. s = S - e;
  1812. s = y - e + (this._hi - s);
  1813. f = s + this._lo;
  1814. H = S + f;
  1815. h = f + (S - H);
  1816. this._hi = H + h;
  1817. this._lo = h + (H - this._hi);
  1818. return this;
  1819. }
  1820. } else if (arguments.length === 2) {
  1821. const yhi = arguments[0],
  1822. ylo = arguments[1];
  1823. let H = null,
  1824. h = null,
  1825. T = null,
  1826. t = null,
  1827. S = null,
  1828. s = null,
  1829. e = null,
  1830. f = null;
  1831. S = this._hi + yhi;
  1832. T = this._lo + ylo;
  1833. e = S - this._hi;
  1834. f = T - this._lo;
  1835. s = S - e;
  1836. t = T - f;
  1837. s = yhi - e + (this._hi - s);
  1838. t = ylo - f + (this._lo - t);
  1839. e = s + T;
  1840. H = S + e;
  1841. h = e + (S - H);
  1842. e = t + h;
  1843. const zhi = H + e;
  1844. const zlo = e + (H - zhi);
  1845. this._hi = zhi;
  1846. this._lo = zlo;
  1847. return this;
  1848. }
  1849. }
  1850. selfMultiply() {
  1851. if (arguments.length === 1) {
  1852. if (arguments[0] instanceof DD) {
  1853. const y = arguments[0];
  1854. return this.selfMultiply(y._hi, y._lo);
  1855. } else if (typeof arguments[0] === 'number') {
  1856. const y = arguments[0];
  1857. return this.selfMultiply(y, 0.0);
  1858. }
  1859. } else if (arguments.length === 2) {
  1860. const yhi = arguments[0],
  1861. ylo = arguments[1];
  1862. let hx = null,
  1863. tx = null,
  1864. hy = null,
  1865. ty = null,
  1866. C = null,
  1867. c = null;
  1868. C = DD.SPLIT * this._hi;
  1869. hx = C - this._hi;
  1870. c = DD.SPLIT * yhi;
  1871. hx = C - hx;
  1872. tx = this._hi - hx;
  1873. hy = c - yhi;
  1874. C = this._hi * yhi;
  1875. hy = c - hy;
  1876. ty = yhi - hy;
  1877. c = hx * hy - C + hx * ty + tx * hy + tx * ty + (this._hi * ylo + this._lo * yhi);
  1878. const zhi = C + c;
  1879. hx = C - zhi;
  1880. const zlo = c + hx;
  1881. this._hi = zhi;
  1882. this._lo = zlo;
  1883. return this;
  1884. }
  1885. }
  1886. selfSqr() {
  1887. return this.selfMultiply(this);
  1888. }
  1889. floor() {
  1890. if (this.isNaN()) return DD.NaN;
  1891. const fhi = Math.floor(this._hi);
  1892. let flo = 0.0;
  1893. if (fhi === this._hi) flo = Math.floor(this._lo);
  1894. return new DD(fhi, flo);
  1895. }
  1896. negate() {
  1897. if (this.isNaN()) return this;
  1898. return new DD(-this._hi, -this._lo);
  1899. }
  1900. clone() {
  1901. try {
  1902. return null;
  1903. } catch (ex) {
  1904. if (ex instanceof CloneNotSupportedException) return null;else throw ex;
  1905. } finally {}
  1906. }
  1907. multiply() {
  1908. if (arguments[0] instanceof DD) {
  1909. const y = arguments[0];
  1910. if (y.isNaN()) return DD.createNaN();
  1911. return DD.copy(this).selfMultiply(y);
  1912. } else if (typeof arguments[0] === 'number') {
  1913. const y = arguments[0];
  1914. if (Double.isNaN(y)) return DD.createNaN();
  1915. return DD.copy(this).selfMultiply(y, 0.0);
  1916. }
  1917. }
  1918. isNaN() {
  1919. return Double.isNaN(this._hi);
  1920. }
  1921. intValue() {
  1922. return Math.trunc(this._hi);
  1923. }
  1924. toString() {
  1925. const mag = DD.magnitude(this._hi);
  1926. if (mag >= -3 && mag <= 20) return this.toStandardNotation();
  1927. return this.toSciNotation();
  1928. }
  1929. toStandardNotation() {
  1930. const specialStr = this.getSpecialNumberString();
  1931. if (specialStr !== null) return specialStr;
  1932. const magnitude = new Array(1).fill(null);
  1933. const sigDigits = this.extractSignificantDigits(true, magnitude);
  1934. const decimalPointPos = magnitude[0] + 1;
  1935. let num = sigDigits;
  1936. if (sigDigits.charAt(0) === '.') {
  1937. num = '0' + sigDigits;
  1938. } else if (decimalPointPos < 0) {
  1939. num = '0.' + DD.stringOfChar('0', -decimalPointPos) + sigDigits;
  1940. } else if (sigDigits.indexOf('.') === -1) {
  1941. const numZeroes = decimalPointPos - sigDigits.length;
  1942. const zeroes = DD.stringOfChar('0', numZeroes);
  1943. num = sigDigits + zeroes + '.0';
  1944. }
  1945. if (this.isNegative()) return '-' + num;
  1946. return num;
  1947. }
  1948. reciprocal() {
  1949. let hc = null,
  1950. tc = null,
  1951. hy = null,
  1952. ty = null,
  1953. C = null,
  1954. c = null,
  1955. U = null,
  1956. u = null;
  1957. C = 1.0 / this._hi;
  1958. c = DD.SPLIT * C;
  1959. hc = c - C;
  1960. u = DD.SPLIT * this._hi;
  1961. hc = c - hc;
  1962. tc = C - hc;
  1963. hy = u - this._hi;
  1964. U = C * this._hi;
  1965. hy = u - hy;
  1966. ty = this._hi - hy;
  1967. u = hc * hy - U + hc * ty + tc * hy + tc * ty;
  1968. c = (1.0 - U - u - C * this._lo) / this._hi;
  1969. const zhi = C + c;
  1970. const zlo = C - zhi + c;
  1971. return new DD(zhi, zlo);
  1972. }
  1973. toSciNotation() {
  1974. if (this.isZero()) return DD.SCI_NOT_ZERO;
  1975. const specialStr = this.getSpecialNumberString();
  1976. if (specialStr !== null) return specialStr;
  1977. const magnitude = new Array(1).fill(null);
  1978. const digits = this.extractSignificantDigits(false, magnitude);
  1979. const expStr = DD.SCI_NOT_EXPONENT_CHAR + magnitude[0];
  1980. if (digits.charAt(0) === '0') throw new IllegalStateException('Found leading zero: ' + digits);
  1981. let trailingDigits = '';
  1982. if (digits.length > 1) trailingDigits = digits.substring(1);
  1983. const digitsWithDecimal = digits.charAt(0) + '.' + trailingDigits;
  1984. if (this.isNegative()) return '-' + digitsWithDecimal + expStr;
  1985. return digitsWithDecimal + expStr;
  1986. }
  1987. abs() {
  1988. if (this.isNaN()) return DD.NaN;
  1989. if (this.isNegative()) return this.negate();
  1990. return new DD(this);
  1991. }
  1992. isPositive() {
  1993. return this._hi > 0.0 || this._hi === 0.0 && this._lo > 0.0;
  1994. }
  1995. lt(y) {
  1996. return this._hi < y._hi || this._hi === y._hi && this._lo < y._lo;
  1997. }
  1998. add() {
  1999. if (arguments[0] instanceof DD) {
  2000. const y = arguments[0];
  2001. return DD.copy(this).selfAdd(y);
  2002. } else if (typeof arguments[0] === 'number') {
  2003. const y = arguments[0];
  2004. return DD.copy(this).selfAdd(y);
  2005. }
  2006. }
  2007. init() {
  2008. if (arguments.length === 1) {
  2009. if (typeof arguments[0] === 'number') {
  2010. const x = arguments[0];
  2011. this._hi = x;
  2012. this._lo = 0.0;
  2013. } else if (arguments[0] instanceof DD) {
  2014. const dd = arguments[0];
  2015. this._hi = dd._hi;
  2016. this._lo = dd._lo;
  2017. }
  2018. } else if (arguments.length === 2) {
  2019. const hi = arguments[0],
  2020. lo = arguments[1];
  2021. this._hi = hi;
  2022. this._lo = lo;
  2023. }
  2024. }
  2025. gt(y) {
  2026. return this._hi > y._hi || this._hi === y._hi && this._lo > y._lo;
  2027. }
  2028. isNegative() {
  2029. return this._hi < 0.0 || this._hi === 0.0 && this._lo < 0.0;
  2030. }
  2031. trunc() {
  2032. if (this.isNaN()) return DD.NaN;
  2033. if (this.isPositive()) return this.floor();else return this.ceil();
  2034. }
  2035. signum() {
  2036. if (this._hi > 0) return 1;
  2037. if (this._hi < 0) return -1;
  2038. if (this._lo > 0) return 1;
  2039. if (this._lo < 0) return -1;
  2040. return 0;
  2041. }
  2042. get interfaces_() {
  2043. return [Serializable, Comparable, Clonable];
  2044. }
  2045. }
  2046. DD.PI = new DD(3.141592653589793116e+00, 1.224646799147353207e-16);
  2047. DD.TWO_PI = new DD(6.283185307179586232e+00, 2.449293598294706414e-16);
  2048. DD.PI_2 = new DD(1.570796326794896558e+00, 6.123233995736766036e-17);
  2049. DD.E = new DD(2.718281828459045091e+00, 1.445646891729250158e-16);
  2050. DD.NaN = new DD(Double.NaN, Double.NaN);
  2051. DD.EPS = 1.23259516440783e-32;
  2052. DD.SPLIT = 134217729.0;
  2053. DD.MAX_PRINT_DIGITS = 32;
  2054. DD.TEN = DD.valueOf(10.0);
  2055. DD.ONE = DD.valueOf(1.0);
  2056. DD.SCI_NOT_EXPONENT_CHAR = 'E';
  2057. DD.SCI_NOT_ZERO = '0.0E0';
  2058. class CGAlgorithmsDD {
  2059. static orientationIndex(p1, p2, q) {
  2060. const index = CGAlgorithmsDD.orientationIndexFilter(p1, p2, q);
  2061. if (index <= 1) return index;
  2062. const dx1 = DD.valueOf(p2.x).selfAdd(-p1.x);
  2063. const dy1 = DD.valueOf(p2.y).selfAdd(-p1.y);
  2064. const dx2 = DD.valueOf(q.x).selfAdd(-p2.x);
  2065. const dy2 = DD.valueOf(q.y).selfAdd(-p2.y);
  2066. return dx1.selfMultiply(dy2).selfSubtract(dy1.selfMultiply(dx2)).signum();
  2067. }
  2068. static signOfDet2x2() {
  2069. if (arguments[3] instanceof DD && arguments[2] instanceof DD && arguments[0] instanceof DD && arguments[1] instanceof DD) {
  2070. const x1 = arguments[0],
  2071. y1 = arguments[1],
  2072. x2 = arguments[2],
  2073. y2 = arguments[3];
  2074. const det = x1.multiply(y2).selfSubtract(y1.multiply(x2));
  2075. return det.signum();
  2076. } else if (typeof arguments[3] === 'number' && typeof arguments[2] === 'number' && typeof arguments[0] === 'number' && typeof arguments[1] === 'number') {
  2077. const dx1 = arguments[0],
  2078. dy1 = arguments[1],
  2079. dx2 = arguments[2],
  2080. dy2 = arguments[3];
  2081. const x1 = DD.valueOf(dx1);
  2082. const y1 = DD.valueOf(dy1);
  2083. const x2 = DD.valueOf(dx2);
  2084. const y2 = DD.valueOf(dy2);
  2085. const det = x1.multiply(y2).selfSubtract(y1.multiply(x2));
  2086. return det.signum();
  2087. }
  2088. }
  2089. static intersection(p1, p2, q1, q2) {
  2090. const px = new DD(p1.y).selfSubtract(p2.y);
  2091. const py = new DD(p2.x).selfSubtract(p1.x);
  2092. const pw = new DD(p1.x).selfMultiply(p2.y).selfSubtract(new DD(p2.x).selfMultiply(p1.y));
  2093. const qx = new DD(q1.y).selfSubtract(q2.y);
  2094. const qy = new DD(q2.x).selfSubtract(q1.x);
  2095. const qw = new DD(q1.x).selfMultiply(q2.y).selfSubtract(new DD(q2.x).selfMultiply(q1.y));
  2096. const x = py.multiply(qw).selfSubtract(qy.multiply(pw));
  2097. const y = qx.multiply(pw).selfSubtract(px.multiply(qw));
  2098. const w = px.multiply(qy).selfSubtract(qx.multiply(py));
  2099. const xInt = x.selfDivide(w).doubleValue();
  2100. const yInt = y.selfDivide(w).doubleValue();
  2101. if (Double.isNaN(xInt) || Double.isInfinite(xInt) || Double.isNaN(yInt) || Double.isInfinite(yInt)) return null;
  2102. return new Coordinate(xInt, yInt);
  2103. }
  2104. static orientationIndexFilter(pa, pb, pc) {
  2105. let detsum = null;
  2106. const detleft = (pa.x - pc.x) * (pb.y - pc.y);
  2107. const detright = (pa.y - pc.y) * (pb.x - pc.x);
  2108. const det = detleft - detright;
  2109. if (detleft > 0.0) {
  2110. if (detright <= 0.0) return CGAlgorithmsDD.signum(det);else detsum = detleft + detright;
  2111. } else if (detleft < 0.0) {
  2112. if (detright >= 0.0) return CGAlgorithmsDD.signum(det);else detsum = -detleft - detright;
  2113. } else return CGAlgorithmsDD.signum(det);
  2114. const errbound = CGAlgorithmsDD.DP_SAFE_EPSILON * detsum;
  2115. if (det >= errbound || -det >= errbound) return CGAlgorithmsDD.signum(det);
  2116. return 2;
  2117. }
  2118. static signum(x) {
  2119. if (x > 0) return 1;
  2120. if (x < 0) return -1;
  2121. return 0;
  2122. }
  2123. }
  2124. CGAlgorithmsDD.DP_SAFE_EPSILON = 1e-15;
  2125. class CoordinateSequence {
  2126. getM(index) {
  2127. if (this.hasM()) {
  2128. const mIndex = this.getDimension() - this.getMeasures();
  2129. return this.getOrdinate(index, mIndex);
  2130. } else {
  2131. return Double.NaN;
  2132. }
  2133. }
  2134. setOrdinate(index, ordinateIndex, value) {}
  2135. getZ(index) {
  2136. if (this.hasZ()) return this.getOrdinate(index, 2);else return Double.NaN;
  2137. }
  2138. size() {}
  2139. getOrdinate(index, ordinateIndex) {}
  2140. getCoordinate() {
  2141. }
  2142. getCoordinateCopy(i) {}
  2143. createCoordinate() {}
  2144. getDimension() {}
  2145. hasM() {
  2146. return this.getMeasures() > 0;
  2147. }
  2148. getX(index) {}
  2149. hasZ() {
  2150. return this.getDimension() - this.getMeasures() > 2;
  2151. }
  2152. getMeasures() {
  2153. return 0;
  2154. }
  2155. expandEnvelope(env) {}
  2156. copy() {}
  2157. getY(index) {}
  2158. toCoordinateArray() {}
  2159. get interfaces_() {
  2160. return [Clonable];
  2161. }
  2162. }
  2163. CoordinateSequence.X = 0;
  2164. CoordinateSequence.Y = 1;
  2165. CoordinateSequence.Z = 2;
  2166. CoordinateSequence.M = 3;
  2167. class Orientation {
  2168. static index(p1, p2, q) {
  2169. return CGAlgorithmsDD.orientationIndex(p1, p2, q);
  2170. }
  2171. static isCCW() {
  2172. if (arguments[0] instanceof Array) {
  2173. const ring = arguments[0];
  2174. const nPts = ring.length - 1;
  2175. if (nPts < 3) throw new IllegalArgumentException('Ring has fewer than 4 points, so orientation cannot be determined');
  2176. let hiPt = ring[0];
  2177. let hiIndex = 0;
  2178. for (let i = 1; i <= nPts; i++) {
  2179. const p = ring[i];
  2180. if (p.y > hiPt.y) {
  2181. hiPt = p;
  2182. hiIndex = i;
  2183. }
  2184. }
  2185. let iPrev = hiIndex;
  2186. do {
  2187. iPrev = iPrev - 1;
  2188. if (iPrev < 0) iPrev = nPts;
  2189. } while (ring[iPrev].equals2D(hiPt) && iPrev !== hiIndex);
  2190. let iNext = hiIndex;
  2191. do iNext = (iNext + 1) % nPts; while (ring[iNext].equals2D(hiPt) && iNext !== hiIndex);
  2192. const prev = ring[iPrev];
  2193. const next = ring[iNext];
  2194. if (prev.equals2D(hiPt) || next.equals2D(hiPt) || prev.equals2D(next)) return false;
  2195. const disc = Orientation.index(prev, hiPt, next);
  2196. let isCCW = null;
  2197. if (disc === 0) isCCW = prev.x > next.x;else isCCW = disc > 0;
  2198. return isCCW;
  2199. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  2200. const ring = arguments[0];
  2201. const nPts = ring.size() - 1;
  2202. if (nPts < 3) throw new IllegalArgumentException('Ring has fewer than 4 points, so orientation cannot be determined');
  2203. let hiPt = ring.getCoordinate(0);
  2204. let hiIndex = 0;
  2205. for (let i = 1; i <= nPts; i++) {
  2206. const p = ring.getCoordinate(i);
  2207. if (p.y > hiPt.y) {
  2208. hiPt = p;
  2209. hiIndex = i;
  2210. }
  2211. }
  2212. let prev = null;
  2213. let iPrev = hiIndex;
  2214. do {
  2215. iPrev = iPrev - 1;
  2216. if (iPrev < 0) iPrev = nPts;
  2217. prev = ring.getCoordinate(iPrev);
  2218. } while (prev.equals2D(hiPt) && iPrev !== hiIndex);
  2219. let next = null;
  2220. let iNext = hiIndex;
  2221. do {
  2222. iNext = (iNext + 1) % nPts;
  2223. next = ring.getCoordinate(iNext);
  2224. } while (next.equals2D(hiPt) && iNext !== hiIndex);
  2225. if (prev.equals2D(hiPt) || next.equals2D(hiPt) || prev.equals2D(next)) return false;
  2226. const disc = Orientation.index(prev, hiPt, next);
  2227. let isCCW = null;
  2228. if (disc === 0) isCCW = prev.x > next.x;else isCCW = disc > 0;
  2229. return isCCW;
  2230. }
  2231. }
  2232. }
  2233. Orientation.CLOCKWISE = -1;
  2234. Orientation.RIGHT = Orientation.CLOCKWISE;
  2235. Orientation.COUNTERCLOCKWISE = 1;
  2236. Orientation.LEFT = Orientation.COUNTERCLOCKWISE;
  2237. Orientation.COLLINEAR = 0;
  2238. Orientation.STRAIGHT = Orientation.COLLINEAR;
  2239. class Intersection {
  2240. static intersection(p1, p2, q1, q2) {
  2241. const minX0 = p1.x < p2.x ? p1.x : p2.x;
  2242. const minY0 = p1.y < p2.y ? p1.y : p2.y;
  2243. const maxX0 = p1.x > p2.x ? p1.x : p2.x;
  2244. const maxY0 = p1.y > p2.y ? p1.y : p2.y;
  2245. const minX1 = q1.x < q2.x ? q1.x : q2.x;
  2246. const minY1 = q1.y < q2.y ? q1.y : q2.y;
  2247. const maxX1 = q1.x > q2.x ? q1.x : q2.x;
  2248. const maxY1 = q1.y > q2.y ? q1.y : q2.y;
  2249. const intMinX = minX0 > minX1 ? minX0 : minX1;
  2250. const intMaxX = maxX0 < maxX1 ? maxX0 : maxX1;
  2251. const intMinY = minY0 > minY1 ? minY0 : minY1;
  2252. const intMaxY = maxY0 < maxY1 ? maxY0 : maxY1;
  2253. const midx = (intMinX + intMaxX) / 2.0;
  2254. const midy = (intMinY + intMaxY) / 2.0;
  2255. const p1x = p1.x - midx;
  2256. const p1y = p1.y - midy;
  2257. const p2x = p2.x - midx;
  2258. const p2y = p2.y - midy;
  2259. const q1x = q1.x - midx;
  2260. const q1y = q1.y - midy;
  2261. const q2x = q2.x - midx;
  2262. const q2y = q2.y - midy;
  2263. const px = p1y - p2y;
  2264. const py = p2x - p1x;
  2265. const pw = p1x * p2y - p2x * p1y;
  2266. const qx = q1y - q2y;
  2267. const qy = q2x - q1x;
  2268. const qw = q1x * q2y - q2x * q1y;
  2269. const x = py * qw - qy * pw;
  2270. const y = qx * pw - px * qw;
  2271. const w = px * qy - qx * py;
  2272. const xInt = x / w;
  2273. const yInt = y / w;
  2274. if (Double.isNaN(xInt) || Double.isInfinite(xInt) || Double.isNaN(yInt) || Double.isInfinite(yInt)) return null;
  2275. return new Coordinate(xInt + midx, yInt + midy);
  2276. }
  2277. }
  2278. class System {
  2279. static arraycopy(src, srcPos, dest, destPos, len) {
  2280. let c = 0;
  2281. for (let i = srcPos; i < srcPos + len; i++) {
  2282. dest[destPos + c] = src[i];
  2283. c++;
  2284. }
  2285. }
  2286. static getProperty(name) {
  2287. return {
  2288. 'line.separator': '\n'
  2289. }[name];
  2290. }
  2291. }
  2292. class MathUtil {
  2293. static log10(x) {
  2294. const ln = Math.log(x);
  2295. if (Double.isInfinite(ln)) return ln;
  2296. if (Double.isNaN(ln)) return ln;
  2297. return ln / MathUtil.LOG_10;
  2298. }
  2299. static min(v1, v2, v3, v4) {
  2300. let min = v1;
  2301. if (v2 < min) min = v2;
  2302. if (v3 < min) min = v3;
  2303. if (v4 < min) min = v4;
  2304. return min;
  2305. }
  2306. static clamp() {
  2307. if (typeof arguments[2] === 'number' && typeof arguments[0] === 'number' && typeof arguments[1] === 'number') {
  2308. const x = arguments[0],
  2309. min = arguments[1],
  2310. max = arguments[2];
  2311. if (x < min) return min;
  2312. if (x > max) return max;
  2313. return x;
  2314. } else if (Number.isInteger(arguments[2]) && Number.isInteger(arguments[0]) && Number.isInteger(arguments[1])) {
  2315. const x = arguments[0],
  2316. min = arguments[1],
  2317. max = arguments[2];
  2318. if (x < min) return min;
  2319. if (x > max) return max;
  2320. return x;
  2321. }
  2322. }
  2323. static wrap(index, max) {
  2324. if (index < 0) return max - -index % max;
  2325. return index % max;
  2326. }
  2327. static max() {
  2328. if (arguments.length === 3) {
  2329. const v1 = arguments[0],
  2330. v2 = arguments[1],
  2331. v3 = arguments[2];
  2332. let max = v1;
  2333. if (v2 > max) max = v2;
  2334. if (v3 > max) max = v3;
  2335. return max;
  2336. } else if (arguments.length === 4) {
  2337. const v1 = arguments[0],
  2338. v2 = arguments[1],
  2339. v3 = arguments[2],
  2340. v4 = arguments[3];
  2341. let max = v1;
  2342. if (v2 > max) max = v2;
  2343. if (v3 > max) max = v3;
  2344. if (v4 > max) max = v4;
  2345. return max;
  2346. }
  2347. }
  2348. static average(x1, x2) {
  2349. return (x1 + x2) / 2.0;
  2350. }
  2351. }
  2352. MathUtil.LOG_10 = Math.log(10);
  2353. class Distance {
  2354. static segmentToSegment(A, B, C, D) {
  2355. if (A.equals(B)) return Distance.pointToSegment(A, C, D);
  2356. if (C.equals(D)) return Distance.pointToSegment(D, A, B);
  2357. let noIntersection = false;
  2358. if (!Envelope.intersects(A, B, C, D)) {
  2359. noIntersection = true;
  2360. } else {
  2361. const denom = (B.x - A.x) * (D.y - C.y) - (B.y - A.y) * (D.x - C.x);
  2362. if (denom === 0) {
  2363. noIntersection = true;
  2364. } else {
  2365. const r_num = (A.y - C.y) * (D.x - C.x) - (A.x - C.x) * (D.y - C.y);
  2366. const s_num = (A.y - C.y) * (B.x - A.x) - (A.x - C.x) * (B.y - A.y);
  2367. const s = s_num / denom;
  2368. const r = r_num / denom;
  2369. if (r < 0 || r > 1 || s < 0 || s > 1) noIntersection = true;
  2370. }
  2371. }
  2372. if (noIntersection) return MathUtil.min(Distance.pointToSegment(A, C, D), Distance.pointToSegment(B, C, D), Distance.pointToSegment(C, A, B), Distance.pointToSegment(D, A, B));
  2373. return 0.0;
  2374. }
  2375. static pointToSegment(p, A, B) {
  2376. if (A.x === B.x && A.y === B.y) return p.distance(A);
  2377. const len2 = (B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y);
  2378. const r = ((p.x - A.x) * (B.x - A.x) + (p.y - A.y) * (B.y - A.y)) / len2;
  2379. if (r <= 0.0) return p.distance(A);
  2380. if (r >= 1.0) return p.distance(B);
  2381. const s = ((A.y - p.y) * (B.x - A.x) - (A.x - p.x) * (B.y - A.y)) / len2;
  2382. return Math.abs(s) * Math.sqrt(len2);
  2383. }
  2384. static pointToLinePerpendicular(p, A, B) {
  2385. const len2 = (B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y);
  2386. const s = ((A.y - p.y) * (B.x - A.x) - (A.x - p.x) * (B.y - A.y)) / len2;
  2387. return Math.abs(s) * Math.sqrt(len2);
  2388. }
  2389. static pointToSegmentString(p, line) {
  2390. if (line.length === 0) throw new IllegalArgumentException('Line array must contain at least one vertex');
  2391. let minDistance = p.distance(line[0]);
  2392. for (let i = 0; i < line.length - 1; i++) {
  2393. const dist = Distance.pointToSegment(p, line[i], line[i + 1]);
  2394. if (dist < minDistance) minDistance = dist;
  2395. }
  2396. return minDistance;
  2397. }
  2398. }
  2399. class CoordinateSequenceFactory {
  2400. create() {
  2401. if (arguments.length === 1) {
  2402. if (arguments[0] instanceof Array) ; else if (hasInterface(arguments[0], CoordinateSequence)) ;
  2403. } else if (arguments.length === 2) ; else if (arguments.length === 3) {
  2404. const size = arguments[0],
  2405. dimension = arguments[1];
  2406. return this.create(size, dimension);
  2407. }
  2408. }
  2409. }
  2410. class GeometryComponentFilter {
  2411. filter(geom) {}
  2412. }
  2413. class Geometry {
  2414. constructor() {
  2415. Geometry.constructor_.apply(this, arguments);
  2416. }
  2417. isGeometryCollection() {
  2418. return this.getTypeCode() === Geometry.TYPECODE_GEOMETRYCOLLECTION;
  2419. }
  2420. getFactory() {
  2421. return this._factory;
  2422. }
  2423. getGeometryN(n) {
  2424. return this;
  2425. }
  2426. getArea() {
  2427. return 0.0;
  2428. }
  2429. isRectangle() {
  2430. return false;
  2431. }
  2432. equalsExact(other) {
  2433. return this === other || this.equalsExact(other, 0);
  2434. }
  2435. geometryChanged() {
  2436. this.apply(Geometry.geometryChangedFilter);
  2437. }
  2438. geometryChangedAction() {
  2439. this._envelope = null;
  2440. }
  2441. equalsNorm(g) {
  2442. if (g === null) return false;
  2443. return this.norm().equalsExact(g.norm());
  2444. }
  2445. getLength() {
  2446. return 0.0;
  2447. }
  2448. getNumGeometries() {
  2449. return 1;
  2450. }
  2451. compareTo() {
  2452. let other;
  2453. if (arguments.length === 1) {
  2454. const o = arguments[0];
  2455. other = o;
  2456. if (this.getTypeCode() !== other.getTypeCode()) return this.getTypeCode() - other.getTypeCode();
  2457. if (this.isEmpty() && other.isEmpty()) return 0;
  2458. if (this.isEmpty()) return -1;
  2459. if (other.isEmpty()) return 1;
  2460. return this.compareToSameClass(o);
  2461. } else if (arguments.length === 2) {
  2462. const o = arguments[0];
  2463. const comp = arguments[1];
  2464. other = o;
  2465. if (this.getTypeCode() !== other.getTypeCode()) return this.getTypeCode() - other.getTypeCode();
  2466. if (this.isEmpty() && other.isEmpty()) return 0;
  2467. if (this.isEmpty()) return -1;
  2468. if (other.isEmpty()) return 1;
  2469. return this.compareToSameClass(o, comp);
  2470. }
  2471. }
  2472. getUserData() {
  2473. return this._userData;
  2474. }
  2475. getSRID() {
  2476. return this._SRID;
  2477. }
  2478. getEnvelope() {
  2479. return this.getFactory().toGeometry(this.getEnvelopeInternal());
  2480. }
  2481. checkNotGeometryCollection(g) {
  2482. if (g.getTypeCode() === Geometry.TYPECODE_GEOMETRYCOLLECTION) throw new IllegalArgumentException('This method does not support GeometryCollection arguments');
  2483. }
  2484. equal(a, b, tolerance) {
  2485. if (tolerance === 0) return a.equals(b);
  2486. return a.distance(b) <= tolerance;
  2487. }
  2488. norm() {
  2489. const copy = this.copy();
  2490. copy.normalize();
  2491. return copy;
  2492. }
  2493. reverse() {
  2494. const res = this.reverseInternal();
  2495. if (this.envelope != null) res.envelope = this.envelope.copy();
  2496. res.setSRID(this.getSRID());
  2497. return res;
  2498. }
  2499. copy() {
  2500. const copy = this.copyInternal();
  2501. copy.envelope = this._envelope == null ? null : this._envelope.copy();
  2502. copy._SRID = this._SRID;
  2503. copy._userData = this._userData;
  2504. return copy;
  2505. }
  2506. getPrecisionModel() {
  2507. return this._factory.getPrecisionModel();
  2508. }
  2509. getEnvelopeInternal() {
  2510. if (this._envelope === null) this._envelope = this.computeEnvelopeInternal();
  2511. return new Envelope(this._envelope);
  2512. }
  2513. setSRID(SRID) {
  2514. this._SRID = SRID;
  2515. }
  2516. setUserData(userData) {
  2517. this._userData = userData;
  2518. }
  2519. compare(a, b) {
  2520. const i = a.iterator();
  2521. const j = b.iterator();
  2522. while (i.hasNext() && j.hasNext()) {
  2523. const aElement = i.next();
  2524. const bElement = j.next();
  2525. const comparison = aElement.compareTo(bElement);
  2526. if (comparison !== 0) return comparison;
  2527. }
  2528. if (i.hasNext()) return 1;
  2529. if (j.hasNext()) return -1;
  2530. return 0;
  2531. }
  2532. hashCode() {
  2533. return this.getEnvelopeInternal().hashCode();
  2534. }
  2535. isEquivalentClass(other) {
  2536. return this.getClass() === other.getClass();
  2537. }
  2538. isGeometryCollectionOrDerived() {
  2539. if (this.getTypeCode() === Geometry.TYPECODE_GEOMETRYCOLLECTION || this.getTypeCode() === Geometry.TYPECODE_MULTIPOINT || this.getTypeCode() === Geometry.TYPECODE_MULTILINESTRING || this.getTypeCode() === Geometry.TYPECODE_MULTIPOLYGON) return true;
  2540. return false;
  2541. }
  2542. get interfaces_() {
  2543. return [Clonable, Comparable, Serializable];
  2544. }
  2545. getClass() {
  2546. return Geometry;
  2547. }
  2548. static hasNonEmptyElements(geometries) {
  2549. for (let i = 0; i < geometries.length; i++) if (!geometries[i].isEmpty()) return true;
  2550. return false;
  2551. }
  2552. static hasNullElements(array) {
  2553. for (let i = 0; i < array.length; i++) if (array[i] === null) return true;
  2554. return false;
  2555. }
  2556. }
  2557. Geometry.constructor_ = function (factory) {
  2558. if (!factory) return;
  2559. this._envelope = null;
  2560. this._userData = null;
  2561. this._factory = factory;
  2562. this._SRID = factory.getSRID();
  2563. };
  2564. Geometry.TYPECODE_POINT = 0;
  2565. Geometry.TYPECODE_MULTIPOINT = 1;
  2566. Geometry.TYPECODE_LINESTRING = 2;
  2567. Geometry.TYPECODE_LINEARRING = 3;
  2568. Geometry.TYPECODE_MULTILINESTRING = 4;
  2569. Geometry.TYPECODE_POLYGON = 5;
  2570. Geometry.TYPECODE_MULTIPOLYGON = 6;
  2571. Geometry.TYPECODE_GEOMETRYCOLLECTION = 7;
  2572. Geometry.TYPENAME_POINT = 'Point';
  2573. Geometry.TYPENAME_MULTIPOINT = 'MultiPoint';
  2574. Geometry.TYPENAME_LINESTRING = 'LineString';
  2575. Geometry.TYPENAME_LINEARRING = 'LinearRing';
  2576. Geometry.TYPENAME_MULTILINESTRING = 'MultiLineString';
  2577. Geometry.TYPENAME_POLYGON = 'Polygon';
  2578. Geometry.TYPENAME_MULTIPOLYGON = 'MultiPolygon';
  2579. Geometry.TYPENAME_GEOMETRYCOLLECTION = 'GeometryCollection';
  2580. Geometry.geometryChangedFilter = {
  2581. get interfaces_() {
  2582. return [GeometryComponentFilter];
  2583. },
  2584. filter(geom) {
  2585. geom.geometryChangedAction();
  2586. }
  2587. };
  2588. class CoordinateFilter {
  2589. filter(coord) {}
  2590. }
  2591. class Length {
  2592. static ofLine(pts) {
  2593. const n = pts.size();
  2594. if (n <= 1) return 0.0;
  2595. let len = 0.0;
  2596. const p = new Coordinate();
  2597. pts.getCoordinate(0, p);
  2598. let x0 = p.x;
  2599. let y0 = p.y;
  2600. for (let i = 1; i < n; i++) {
  2601. pts.getCoordinate(i, p);
  2602. const x1 = p.x;
  2603. const y1 = p.y;
  2604. const dx = x1 - x0;
  2605. const dy = y1 - y0;
  2606. len += Math.sqrt(dx * dx + dy * dy);
  2607. x0 = x1;
  2608. y0 = y1;
  2609. }
  2610. return len;
  2611. }
  2612. }
  2613. class Lineal {}
  2614. class CoordinateSequences {
  2615. static copyCoord(src, srcPos, dest, destPos) {
  2616. const minDim = Math.min(src.getDimension(), dest.getDimension());
  2617. for (let dim = 0; dim < minDim; dim++) dest.setOrdinate(destPos, dim, src.getOrdinate(srcPos, dim));
  2618. }
  2619. static isRing(seq) {
  2620. const n = seq.size();
  2621. if (n === 0) return true;
  2622. if (n <= 3) return false;
  2623. return seq.getOrdinate(0, CoordinateSequence.X) === seq.getOrdinate(n - 1, CoordinateSequence.X) && seq.getOrdinate(0, CoordinateSequence.Y) === seq.getOrdinate(n - 1, CoordinateSequence.Y);
  2624. }
  2625. static scroll() {
  2626. if (arguments.length === 2) {
  2627. if (hasInterface(arguments[0], CoordinateSequence) && Number.isInteger(arguments[1])) {
  2628. const seq = arguments[0],
  2629. indexOfFirstCoordinate = arguments[1];
  2630. CoordinateSequences.scroll(seq, indexOfFirstCoordinate, CoordinateSequences.isRing(seq));
  2631. } else if (hasInterface(arguments[0], CoordinateSequence) && arguments[1] instanceof Coordinate) {
  2632. const seq = arguments[0],
  2633. firstCoordinate = arguments[1];
  2634. const i = CoordinateSequences.indexOf(firstCoordinate, seq);
  2635. if (i <= 0) return null;
  2636. CoordinateSequences.scroll(seq, i);
  2637. }
  2638. } else if (arguments.length === 3) {
  2639. const seq = arguments[0],
  2640. indexOfFirstCoordinate = arguments[1],
  2641. ensureRing = arguments[2];
  2642. const i = indexOfFirstCoordinate;
  2643. if (i <= 0) return null;
  2644. const copy = seq.copy();
  2645. const last = ensureRing ? seq.size() - 1 : seq.size();
  2646. for (let j = 0; j < last; j++) for (let k = 0; k < seq.getDimension(); k++) seq.setOrdinate(j, k, copy.getOrdinate((indexOfFirstCoordinate + j) % last, k));
  2647. if (ensureRing) for (let k = 0; k < seq.getDimension(); k++) seq.setOrdinate(last, k, seq.getOrdinate(0, k));
  2648. }
  2649. }
  2650. static isEqual(cs1, cs2) {
  2651. const cs1Size = cs1.size();
  2652. const cs2Size = cs2.size();
  2653. if (cs1Size !== cs2Size) return false;
  2654. const dim = Math.min(cs1.getDimension(), cs2.getDimension());
  2655. for (let i = 0; i < cs1Size; i++) for (let d = 0; d < dim; d++) {
  2656. const v1 = cs1.getOrdinate(i, d);
  2657. const v2 = cs2.getOrdinate(i, d);
  2658. if (cs1.getOrdinate(i, d) === cs2.getOrdinate(i, d)) continue;
  2659. if (Double.isNaN(v1) && Double.isNaN(v2)) continue;
  2660. return false;
  2661. }
  2662. return true;
  2663. }
  2664. static minCoordinateIndex() {
  2665. if (arguments.length === 1) {
  2666. const seq = arguments[0];
  2667. return CoordinateSequences.minCoordinateIndex(seq, 0, seq.size() - 1);
  2668. } else if (arguments.length === 3) {
  2669. const seq = arguments[0],
  2670. from = arguments[1],
  2671. to = arguments[2];
  2672. let minCoordIndex = -1;
  2673. let minCoord = null;
  2674. for (let i = from; i <= to; i++) {
  2675. const testCoord = seq.getCoordinate(i);
  2676. if (minCoord === null || minCoord.compareTo(testCoord) > 0) {
  2677. minCoord = testCoord;
  2678. minCoordIndex = i;
  2679. }
  2680. }
  2681. return minCoordIndex;
  2682. }
  2683. }
  2684. static extend(fact, seq, size) {
  2685. const newseq = fact.create(size, seq.getDimension());
  2686. const n = seq.size();
  2687. CoordinateSequences.copy(seq, 0, newseq, 0, n);
  2688. if (n > 0) for (let i = n; i < size; i++) CoordinateSequences.copy(seq, n - 1, newseq, i, 1);
  2689. return newseq;
  2690. }
  2691. static reverse(seq) {
  2692. const last = seq.size() - 1;
  2693. const mid = Math.trunc(last / 2);
  2694. for (let i = 0; i <= mid; i++) CoordinateSequences.swap(seq, i, last - i);
  2695. }
  2696. static swap(seq, i, j) {
  2697. if (i === j) return null;
  2698. for (let dim = 0; dim < seq.getDimension(); dim++) {
  2699. const tmp = seq.getOrdinate(i, dim);
  2700. seq.setOrdinate(i, dim, seq.getOrdinate(j, dim));
  2701. seq.setOrdinate(j, dim, tmp);
  2702. }
  2703. }
  2704. static copy(src, srcPos, dest, destPos, length) {
  2705. for (let i = 0; i < length; i++) CoordinateSequences.copyCoord(src, srcPos + i, dest, destPos + i);
  2706. }
  2707. static ensureValidRing(fact, seq) {
  2708. const n = seq.size();
  2709. if (n === 0) return seq;
  2710. if (n <= 3) return CoordinateSequences.createClosedRing(fact, seq, 4);
  2711. const isClosed = seq.getOrdinate(0, CoordinateSequence.X) === seq.getOrdinate(n - 1, CoordinateSequence.X) && seq.getOrdinate(0, CoordinateSequence.Y) === seq.getOrdinate(n - 1, CoordinateSequence.Y);
  2712. if (isClosed) return seq;
  2713. return CoordinateSequences.createClosedRing(fact, seq, n + 1);
  2714. }
  2715. static indexOf(coordinate, seq) {
  2716. for (let i = 0; i < seq.size(); i++) if (coordinate.x === seq.getOrdinate(i, CoordinateSequence.X) && coordinate.y === seq.getOrdinate(i, CoordinateSequence.Y)) return i;
  2717. return -1;
  2718. }
  2719. static createClosedRing(fact, seq, size) {
  2720. const newseq = fact.create(size, seq.getDimension());
  2721. const n = seq.size();
  2722. CoordinateSequences.copy(seq, 0, newseq, 0, n);
  2723. for (let i = n; i < size; i++) CoordinateSequences.copy(seq, 0, newseq, i, 1);
  2724. return newseq;
  2725. }
  2726. static minCoordinate(seq) {
  2727. let minCoord = null;
  2728. for (let i = 0; i < seq.size(); i++) {
  2729. const testCoord = seq.getCoordinate(i);
  2730. if (minCoord === null || minCoord.compareTo(testCoord) > 0) minCoord = testCoord;
  2731. }
  2732. return minCoord;
  2733. }
  2734. }
  2735. class UnsupportedOperationException extends Exception {
  2736. constructor(message) {
  2737. super(message);
  2738. this.name = Object.keys({
  2739. UnsupportedOperationException
  2740. })[0];
  2741. }
  2742. }
  2743. class Dimension {
  2744. static toDimensionSymbol(dimensionValue) {
  2745. switch (dimensionValue) {
  2746. case Dimension.FALSE:
  2747. return Dimension.SYM_FALSE;
  2748. case Dimension.TRUE:
  2749. return Dimension.SYM_TRUE;
  2750. case Dimension.DONTCARE:
  2751. return Dimension.SYM_DONTCARE;
  2752. case Dimension.P:
  2753. return Dimension.SYM_P;
  2754. case Dimension.L:
  2755. return Dimension.SYM_L;
  2756. case Dimension.A:
  2757. return Dimension.SYM_A;
  2758. }
  2759. throw new IllegalArgumentException('Unknown dimension value: ' + dimensionValue);
  2760. }
  2761. static toDimensionValue(dimensionSymbol) {
  2762. switch (Character.toUpperCase(dimensionSymbol)) {
  2763. case Dimension.SYM_FALSE:
  2764. return Dimension.FALSE;
  2765. case Dimension.SYM_TRUE:
  2766. return Dimension.TRUE;
  2767. case Dimension.SYM_DONTCARE:
  2768. return Dimension.DONTCARE;
  2769. case Dimension.SYM_P:
  2770. return Dimension.P;
  2771. case Dimension.SYM_L:
  2772. return Dimension.L;
  2773. case Dimension.SYM_A:
  2774. return Dimension.A;
  2775. }
  2776. throw new IllegalArgumentException('Unknown dimension symbol: ' + dimensionSymbol);
  2777. }
  2778. }
  2779. Dimension.P = 0;
  2780. Dimension.L = 1;
  2781. Dimension.A = 2;
  2782. Dimension.FALSE = -1;
  2783. Dimension.TRUE = -2;
  2784. Dimension.DONTCARE = -3;
  2785. Dimension.SYM_FALSE = 'F';
  2786. Dimension.SYM_TRUE = 'T';
  2787. Dimension.SYM_DONTCARE = '*';
  2788. Dimension.SYM_P = '0';
  2789. Dimension.SYM_L = '1';
  2790. Dimension.SYM_A = '2';
  2791. class GeometryFilter {
  2792. filter(geom) {}
  2793. }
  2794. class LineString extends Geometry {
  2795. constructor() {
  2796. super();
  2797. LineString.constructor_.apply(this, arguments);
  2798. }
  2799. static constructor_() {
  2800. this._points = null;
  2801. if (arguments.length === 0) ; else if (arguments.length === 2) {
  2802. const points = arguments[0],
  2803. factory = arguments[1];
  2804. Geometry.constructor_.call(this, factory);
  2805. this.init(points);
  2806. }
  2807. }
  2808. computeEnvelopeInternal() {
  2809. if (this.isEmpty()) return new Envelope();
  2810. return this._points.expandEnvelope(new Envelope());
  2811. }
  2812. isRing() {
  2813. return this.isClosed() && this.isSimple();
  2814. }
  2815. getCoordinates() {
  2816. return this._points.toCoordinateArray();
  2817. }
  2818. copyInternal() {
  2819. return new LineString(this._points.copy(), this._factory);
  2820. }
  2821. equalsExact() {
  2822. if (arguments.length === 2 && typeof arguments[1] === 'number' && arguments[0] instanceof Geometry) {
  2823. const other = arguments[0],
  2824. tolerance = arguments[1];
  2825. if (!this.isEquivalentClass(other)) return false;
  2826. const otherLineString = other;
  2827. if (this._points.size() !== otherLineString._points.size()) return false;
  2828. for (let i = 0; i < this._points.size(); i++) if (!this.equal(this._points.getCoordinate(i), otherLineString._points.getCoordinate(i), tolerance)) return false;
  2829. return true;
  2830. } else {
  2831. return super.equalsExact.apply(this, arguments);
  2832. }
  2833. }
  2834. normalize() {
  2835. for (let i = 0; i < Math.trunc(this._points.size() / 2); i++) {
  2836. const j = this._points.size() - 1 - i;
  2837. if (!this._points.getCoordinate(i).equals(this._points.getCoordinate(j))) {
  2838. if (this._points.getCoordinate(i).compareTo(this._points.getCoordinate(j)) > 0) {
  2839. const copy = this._points.copy();
  2840. CoordinateSequences.reverse(copy);
  2841. this._points = copy;
  2842. }
  2843. return null;
  2844. }
  2845. }
  2846. }
  2847. getCoordinate() {
  2848. if (this.isEmpty()) return null;
  2849. return this._points.getCoordinate(0);
  2850. }
  2851. getBoundaryDimension() {
  2852. if (this.isClosed()) return Dimension.FALSE;
  2853. return 0;
  2854. }
  2855. isClosed() {
  2856. if (this.isEmpty()) return false;
  2857. return this.getCoordinateN(0).equals2D(this.getCoordinateN(this.getNumPoints() - 1));
  2858. }
  2859. reverseInternal() {
  2860. const seq = this._points.copy();
  2861. CoordinateSequences.reverse(seq);
  2862. return this.getFactory().createLineString(seq);
  2863. }
  2864. getEndPoint() {
  2865. if (this.isEmpty()) return null;
  2866. return this.getPointN(this.getNumPoints() - 1);
  2867. }
  2868. getTypeCode() {
  2869. return Geometry.TYPECODE_LINESTRING;
  2870. }
  2871. getDimension() {
  2872. return 1;
  2873. }
  2874. getLength() {
  2875. return Length.ofLine(this._points);
  2876. }
  2877. getNumPoints() {
  2878. return this._points.size();
  2879. }
  2880. compareToSameClass() {
  2881. if (arguments.length === 1) {
  2882. const o = arguments[0];
  2883. const line = o;
  2884. let i = 0;
  2885. let j = 0;
  2886. while (i < this._points.size() && j < line._points.size()) {
  2887. const comparison = this._points.getCoordinate(i).compareTo(line._points.getCoordinate(j));
  2888. if (comparison !== 0) return comparison;
  2889. i++;
  2890. j++;
  2891. }
  2892. if (i < this._points.size()) return 1;
  2893. if (j < line._points.size()) return -1;
  2894. return 0;
  2895. } else if (arguments.length === 2) {
  2896. const o = arguments[0],
  2897. comp = arguments[1];
  2898. const line = o;
  2899. return comp.compare(this._points, line._points);
  2900. }
  2901. }
  2902. apply() {
  2903. if (hasInterface(arguments[0], CoordinateFilter)) {
  2904. const filter = arguments[0];
  2905. for (let i = 0; i < this._points.size(); i++) filter.filter(this._points.getCoordinate(i));
  2906. } else if (hasInterface(arguments[0], CoordinateSequenceFilter)) {
  2907. const filter = arguments[0];
  2908. if (this._points.size() === 0) return null;
  2909. for (let i = 0; i < this._points.size(); i++) {
  2910. filter.filter(this._points, i);
  2911. if (filter.isDone()) break;
  2912. }
  2913. if (filter.isGeometryChanged()) this.geometryChanged();
  2914. } else if (hasInterface(arguments[0], GeometryFilter)) {
  2915. const filter = arguments[0];
  2916. filter.filter(this);
  2917. } else if (hasInterface(arguments[0], GeometryComponentFilter)) {
  2918. const filter = arguments[0];
  2919. filter.filter(this);
  2920. }
  2921. }
  2922. getBoundary() {
  2923. throw new UnsupportedOperationException();
  2924. }
  2925. isEquivalentClass(other) {
  2926. return other instanceof LineString;
  2927. }
  2928. getCoordinateN(n) {
  2929. return this._points.getCoordinate(n);
  2930. }
  2931. getGeometryType() {
  2932. return Geometry.TYPENAME_LINESTRING;
  2933. }
  2934. getCoordinateSequence() {
  2935. return this._points;
  2936. }
  2937. isEmpty() {
  2938. return this._points.size() === 0;
  2939. }
  2940. init(points) {
  2941. if (points === null) points = this.getFactory().getCoordinateSequenceFactory().create([]);
  2942. if (points.size() === 1) throw new IllegalArgumentException('Invalid number of points in LineString (found ' + points.size() + ' - must be 0 or >= 2)');
  2943. this._points = points;
  2944. }
  2945. isCoordinate(pt) {
  2946. for (let i = 0; i < this._points.size(); i++) if (this._points.getCoordinate(i).equals(pt)) return true;
  2947. return false;
  2948. }
  2949. getStartPoint() {
  2950. if (this.isEmpty()) return null;
  2951. return this.getPointN(0);
  2952. }
  2953. getPointN(n) {
  2954. return this.getFactory().createPoint(this._points.getCoordinate(n));
  2955. }
  2956. get interfaces_() {
  2957. return [Lineal];
  2958. }
  2959. }
  2960. class Puntal {}
  2961. class Point extends Geometry {
  2962. constructor() {
  2963. super();
  2964. Point.constructor_.apply(this, arguments);
  2965. }
  2966. static constructor_() {
  2967. this._coordinates = null;
  2968. const coordinates = arguments[0],
  2969. factory = arguments[1];
  2970. Geometry.constructor_.call(this, factory);
  2971. this.init(coordinates);
  2972. }
  2973. computeEnvelopeInternal() {
  2974. if (this.isEmpty()) return new Envelope();
  2975. const env = new Envelope();
  2976. env.expandToInclude(this._coordinates.getX(0), this._coordinates.getY(0));
  2977. return env;
  2978. }
  2979. getCoordinates() {
  2980. return this.isEmpty() ? [] : [this.getCoordinate()];
  2981. }
  2982. copyInternal() {
  2983. return new Point(this._coordinates.copy(), this._factory);
  2984. }
  2985. equalsExact() {
  2986. if (arguments.length === 2 && typeof arguments[1] === 'number' && arguments[0] instanceof Geometry) {
  2987. const other = arguments[0],
  2988. tolerance = arguments[1];
  2989. if (!this.isEquivalentClass(other)) return false;
  2990. if (this.isEmpty() && other.isEmpty()) return true;
  2991. if (this.isEmpty() !== other.isEmpty()) return false;
  2992. return this.equal(other.getCoordinate(), this.getCoordinate(), tolerance);
  2993. } else {
  2994. return super.equalsExact.apply(this, arguments);
  2995. }
  2996. }
  2997. normalize() {}
  2998. getCoordinate() {
  2999. return this._coordinates.size() !== 0 ? this._coordinates.getCoordinate(0) : null;
  3000. }
  3001. getBoundaryDimension() {
  3002. return Dimension.FALSE;
  3003. }
  3004. reverseInternal() {
  3005. return this.getFactory().createPoint(this._coordinates.copy());
  3006. }
  3007. getTypeCode() {
  3008. return Geometry.TYPECODE_POINT;
  3009. }
  3010. getDimension() {
  3011. return 0;
  3012. }
  3013. getNumPoints() {
  3014. return this.isEmpty() ? 0 : 1;
  3015. }
  3016. getX() {
  3017. if (this.getCoordinate() === null) throw new IllegalStateException('getX called on empty Point');
  3018. return this.getCoordinate().x;
  3019. }
  3020. compareToSameClass() {
  3021. if (arguments.length === 1) {
  3022. const other = arguments[0];
  3023. const point = other;
  3024. return this.getCoordinate().compareTo(point.getCoordinate());
  3025. } else if (arguments.length === 2) {
  3026. const other = arguments[0],
  3027. comp = arguments[1];
  3028. const point = other;
  3029. return comp.compare(this._coordinates, point._coordinates);
  3030. }
  3031. }
  3032. apply() {
  3033. if (hasInterface(arguments[0], CoordinateFilter)) {
  3034. const filter = arguments[0];
  3035. if (this.isEmpty()) return null;
  3036. filter.filter(this.getCoordinate());
  3037. } else if (hasInterface(arguments[0], CoordinateSequenceFilter)) {
  3038. const filter = arguments[0];
  3039. if (this.isEmpty()) return null;
  3040. filter.filter(this._coordinates, 0);
  3041. if (filter.isGeometryChanged()) this.geometryChanged();
  3042. } else if (hasInterface(arguments[0], GeometryFilter)) {
  3043. const filter = arguments[0];
  3044. filter.filter(this);
  3045. } else if (hasInterface(arguments[0], GeometryComponentFilter)) {
  3046. const filter = arguments[0];
  3047. filter.filter(this);
  3048. }
  3049. }
  3050. getBoundary() {
  3051. return this.getFactory().createGeometryCollection();
  3052. }
  3053. getGeometryType() {
  3054. return Geometry.TYPENAME_POINT;
  3055. }
  3056. getCoordinateSequence() {
  3057. return this._coordinates;
  3058. }
  3059. getY() {
  3060. if (this.getCoordinate() === null) throw new IllegalStateException('getY called on empty Point');
  3061. return this.getCoordinate().y;
  3062. }
  3063. isEmpty() {
  3064. return this._coordinates.size() === 0;
  3065. }
  3066. init(coordinates) {
  3067. if (coordinates === null) coordinates = this.getFactory().getCoordinateSequenceFactory().create([]);
  3068. Assert.isTrue(coordinates.size() <= 1);
  3069. this._coordinates = coordinates;
  3070. }
  3071. isSimple() {
  3072. return true;
  3073. }
  3074. get interfaces_() {
  3075. return [Puntal];
  3076. }
  3077. }
  3078. class Area {
  3079. static ofRing() {
  3080. if (arguments[0] instanceof Array) {
  3081. const ring = arguments[0];
  3082. return Math.abs(Area.ofRingSigned(ring));
  3083. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  3084. const ring = arguments[0];
  3085. return Math.abs(Area.ofRingSigned(ring));
  3086. }
  3087. }
  3088. static ofRingSigned() {
  3089. if (arguments[0] instanceof Array) {
  3090. const ring = arguments[0];
  3091. if (ring.length < 3) return 0.0;
  3092. let sum = 0.0;
  3093. const x0 = ring[0].x;
  3094. for (let i = 1; i < ring.length - 1; i++) {
  3095. const x = ring[i].x - x0;
  3096. const y1 = ring[i + 1].y;
  3097. const y2 = ring[i - 1].y;
  3098. sum += x * (y2 - y1);
  3099. }
  3100. return sum / 2.0;
  3101. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  3102. const ring = arguments[0];
  3103. const n = ring.size();
  3104. if (n < 3) return 0.0;
  3105. const p0 = new Coordinate();
  3106. const p1 = new Coordinate();
  3107. const p2 = new Coordinate();
  3108. ring.getCoordinate(0, p1);
  3109. ring.getCoordinate(1, p2);
  3110. const x0 = p1.x;
  3111. p2.x -= x0;
  3112. let sum = 0.0;
  3113. for (let i = 1; i < n - 1; i++) {
  3114. p0.y = p1.y;
  3115. p1.x = p2.x;
  3116. p1.y = p2.y;
  3117. ring.getCoordinate(i + 1, p2);
  3118. p2.x -= x0;
  3119. sum += p1.x * (p0.y - p2.y);
  3120. }
  3121. return sum / 2.0;
  3122. }
  3123. }
  3124. }
  3125. /**
  3126. * @see http://download.oracle.com/javase/6/docs/api/java/util/Arrays.html
  3127. */
  3128. class Arrays {
  3129. static sort() {
  3130. const a = arguments[0];
  3131. if (arguments.length === 1) {
  3132. a.sort((a, b) => a.compareTo(b));
  3133. } else if (arguments.length === 2) {
  3134. a.sort((a, b) => arguments[1].compare(a, b));
  3135. } else if (arguments.length === 3) {
  3136. const t = a.slice(arguments[1], arguments[2]);
  3137. t.sort();
  3138. const r = a.slice(0, arguments[1]).concat(t, a.slice(arguments[2], a.length));
  3139. a.splice(0, a.length);
  3140. for (const e of r) a.push(e);
  3141. } else if (arguments.length === 4) {
  3142. const t = a.slice(arguments[1], arguments[2]);
  3143. t.sort((a, b) => arguments[3].compare(a, b));
  3144. const r = a.slice(0, arguments[1]).concat(t, a.slice(arguments[2], a.length));
  3145. a.splice(0, a.length);
  3146. for (const e of r) a.push(e);
  3147. }
  3148. }
  3149. /**
  3150. * @param {Array} array
  3151. * @return {ArrayList}
  3152. */
  3153. static asList(array) {
  3154. const arrayList = new ArrayList();
  3155. for (const e of array) arrayList.add(e);
  3156. return arrayList;
  3157. }
  3158. static copyOf(original, newLength) {
  3159. return original.slice(0, newLength);
  3160. }
  3161. }
  3162. class Polygonal {}
  3163. class Polygon extends Geometry {
  3164. constructor() {
  3165. super();
  3166. Polygon.constructor_.apply(this, arguments);
  3167. }
  3168. static constructor_() {
  3169. this._shell = null;
  3170. this._holes = null;
  3171. let shell = arguments[0],
  3172. holes = arguments[1],
  3173. factory = arguments[2];
  3174. Geometry.constructor_.call(this, factory);
  3175. if (shell === null) shell = this.getFactory().createLinearRing();
  3176. if (holes === null) holes = [];
  3177. if (Geometry.hasNullElements(holes)) throw new IllegalArgumentException('holes must not contain null elements');
  3178. if (shell.isEmpty() && Geometry.hasNonEmptyElements(holes)) throw new IllegalArgumentException('shell is empty but holes are not');
  3179. this._shell = shell;
  3180. this._holes = holes;
  3181. }
  3182. computeEnvelopeInternal() {
  3183. return this._shell.getEnvelopeInternal();
  3184. }
  3185. getCoordinates() {
  3186. if (this.isEmpty()) return [];
  3187. const coordinates = new Array(this.getNumPoints()).fill(null);
  3188. let k = -1;
  3189. const shellCoordinates = this._shell.getCoordinates();
  3190. for (let x = 0; x < shellCoordinates.length; x++) {
  3191. k++;
  3192. coordinates[k] = shellCoordinates[x];
  3193. }
  3194. for (let i = 0; i < this._holes.length; i++) {
  3195. const childCoordinates = this._holes[i].getCoordinates();
  3196. for (let j = 0; j < childCoordinates.length; j++) {
  3197. k++;
  3198. coordinates[k] = childCoordinates[j];
  3199. }
  3200. }
  3201. return coordinates;
  3202. }
  3203. getArea() {
  3204. let area = 0.0;
  3205. area += Area.ofRing(this._shell.getCoordinateSequence());
  3206. for (let i = 0; i < this._holes.length; i++) area -= Area.ofRing(this._holes[i].getCoordinateSequence());
  3207. return area;
  3208. }
  3209. copyInternal() {
  3210. const shellCopy = this._shell.copy();
  3211. const holeCopies = new Array(this._holes.length).fill(null);
  3212. for (let i = 0; i < this._holes.length; i++) holeCopies[i] = this._holes[i].copy();
  3213. return new Polygon(shellCopy, holeCopies, this._factory);
  3214. }
  3215. isRectangle() {
  3216. if (this.getNumInteriorRing() !== 0) return false;
  3217. if (this._shell === null) return false;
  3218. if (this._shell.getNumPoints() !== 5) return false;
  3219. const seq = this._shell.getCoordinateSequence();
  3220. const env = this.getEnvelopeInternal();
  3221. for (let i = 0; i < 5; i++) {
  3222. const x = seq.getX(i);
  3223. if (!(x === env.getMinX() || x === env.getMaxX())) return false;
  3224. const y = seq.getY(i);
  3225. if (!(y === env.getMinY() || y === env.getMaxY())) return false;
  3226. }
  3227. let prevX = seq.getX(0);
  3228. let prevY = seq.getY(0);
  3229. for (let i = 1; i <= 4; i++) {
  3230. const x = seq.getX(i);
  3231. const y = seq.getY(i);
  3232. const xChanged = x !== prevX;
  3233. const yChanged = y !== prevY;
  3234. if (xChanged === yChanged) return false;
  3235. prevX = x;
  3236. prevY = y;
  3237. }
  3238. return true;
  3239. }
  3240. equalsExact() {
  3241. if (arguments.length === 2 && typeof arguments[1] === 'number' && arguments[0] instanceof Geometry) {
  3242. const other = arguments[0],
  3243. tolerance = arguments[1];
  3244. if (!this.isEquivalentClass(other)) return false;
  3245. const otherPolygon = other;
  3246. const thisShell = this._shell;
  3247. const otherPolygonShell = otherPolygon._shell;
  3248. if (!thisShell.equalsExact(otherPolygonShell, tolerance)) return false;
  3249. if (this._holes.length !== otherPolygon._holes.length) return false;
  3250. for (let i = 0; i < this._holes.length; i++) if (!this._holes[i].equalsExact(otherPolygon._holes[i], tolerance)) return false;
  3251. return true;
  3252. } else {
  3253. return super.equalsExact.apply(this, arguments);
  3254. }
  3255. }
  3256. normalize() {
  3257. if (arguments.length === 0) {
  3258. this._shell = this.normalized(this._shell, true);
  3259. for (let i = 0; i < this._holes.length; i++) this._holes[i] = this.normalized(this._holes[i], false);
  3260. Arrays.sort(this._holes);
  3261. } else if (arguments.length === 2) {
  3262. const ring = arguments[0],
  3263. clockwise = arguments[1];
  3264. if (ring.isEmpty()) return null;
  3265. const seq = ring.getCoordinateSequence();
  3266. const minCoordinateIndex = CoordinateSequences.minCoordinateIndex(seq, 0, seq.size() - 2);
  3267. CoordinateSequences.scroll(seq, minCoordinateIndex, true);
  3268. if (Orientation.isCCW(seq) === clockwise) CoordinateSequences.reverse(seq);
  3269. }
  3270. }
  3271. getCoordinate() {
  3272. return this._shell.getCoordinate();
  3273. }
  3274. getNumInteriorRing() {
  3275. return this._holes.length;
  3276. }
  3277. getBoundaryDimension() {
  3278. return 1;
  3279. }
  3280. reverseInternal() {
  3281. const shell = this.getExteriorRing().reverse();
  3282. const holes = new Array(this.getNumInteriorRing()).fill(null);
  3283. for (let i = 0; i < holes.length; i++) holes[i] = this.getInteriorRingN(i).reverse();
  3284. return this.getFactory().createPolygon(shell, holes);
  3285. }
  3286. getTypeCode() {
  3287. return Geometry.TYPECODE_POLYGON;
  3288. }
  3289. getDimension() {
  3290. return 2;
  3291. }
  3292. getLength() {
  3293. let len = 0.0;
  3294. len += this._shell.getLength();
  3295. for (let i = 0; i < this._holes.length; i++) len += this._holes[i].getLength();
  3296. return len;
  3297. }
  3298. getNumPoints() {
  3299. let numPoints = this._shell.getNumPoints();
  3300. for (let i = 0; i < this._holes.length; i++) numPoints += this._holes[i].getNumPoints();
  3301. return numPoints;
  3302. }
  3303. convexHull() {
  3304. return this.getExteriorRing().convexHull();
  3305. }
  3306. normalized(ring, clockwise) {
  3307. const res = ring.copy();
  3308. this.normalize(res, clockwise);
  3309. return res;
  3310. }
  3311. compareToSameClass() {
  3312. if (arguments.length === 1) {
  3313. const o = arguments[0];
  3314. const thisShell = this._shell;
  3315. const otherShell = o._shell;
  3316. return thisShell.compareToSameClass(otherShell);
  3317. } else if (arguments.length === 2) {
  3318. const o = arguments[0],
  3319. comp = arguments[1];
  3320. const poly = o;
  3321. const thisShell = this._shell;
  3322. const otherShell = poly._shell;
  3323. const shellComp = thisShell.compareToSameClass(otherShell, comp);
  3324. if (shellComp !== 0) return shellComp;
  3325. const nHole1 = this.getNumInteriorRing();
  3326. const nHole2 = poly.getNumInteriorRing();
  3327. let i = 0;
  3328. while (i < nHole1 && i < nHole2) {
  3329. const thisHole = this.getInteriorRingN(i);
  3330. const otherHole = poly.getInteriorRingN(i);
  3331. const holeComp = thisHole.compareToSameClass(otherHole, comp);
  3332. if (holeComp !== 0) return holeComp;
  3333. i++;
  3334. }
  3335. if (i < nHole1) return 1;
  3336. if (i < nHole2) return -1;
  3337. return 0;
  3338. }
  3339. }
  3340. apply() {
  3341. if (hasInterface(arguments[0], CoordinateFilter)) {
  3342. const filter = arguments[0];
  3343. this._shell.apply(filter);
  3344. for (let i = 0; i < this._holes.length; i++) this._holes[i].apply(filter);
  3345. } else if (hasInterface(arguments[0], CoordinateSequenceFilter)) {
  3346. const filter = arguments[0];
  3347. this._shell.apply(filter);
  3348. if (!filter.isDone()) for (let i = 0; i < this._holes.length; i++) {
  3349. this._holes[i].apply(filter);
  3350. if (filter.isDone()) break;
  3351. }
  3352. if (filter.isGeometryChanged()) this.geometryChanged();
  3353. } else if (hasInterface(arguments[0], GeometryFilter)) {
  3354. const filter = arguments[0];
  3355. filter.filter(this);
  3356. } else if (hasInterface(arguments[0], GeometryComponentFilter)) {
  3357. const filter = arguments[0];
  3358. filter.filter(this);
  3359. this._shell.apply(filter);
  3360. for (let i = 0; i < this._holes.length; i++) this._holes[i].apply(filter);
  3361. }
  3362. }
  3363. getBoundary() {
  3364. if (this.isEmpty()) return this.getFactory().createMultiLineString();
  3365. const rings = new Array(this._holes.length + 1).fill(null);
  3366. rings[0] = this._shell;
  3367. for (let i = 0; i < this._holes.length; i++) rings[i + 1] = this._holes[i];
  3368. if (rings.length <= 1) return this.getFactory().createLinearRing(rings[0].getCoordinateSequence());
  3369. return this.getFactory().createMultiLineString(rings);
  3370. }
  3371. getGeometryType() {
  3372. return Geometry.TYPENAME_POLYGON;
  3373. }
  3374. getExteriorRing() {
  3375. return this._shell;
  3376. }
  3377. isEmpty() {
  3378. return this._shell.isEmpty();
  3379. }
  3380. getInteriorRingN(n) {
  3381. return this._holes[n];
  3382. }
  3383. get interfaces_() {
  3384. return [Polygonal];
  3385. }
  3386. }
  3387. /**
  3388. * @see http://download.oracle.com/javase/6/docs/api/java/util/Set.html
  3389. *
  3390. * @extends {Collection}
  3391. * @constructor
  3392. * @private
  3393. */
  3394. class Set extends Collection {
  3395. /**
  3396. * Returns true if this set contains the specified element. More formally,
  3397. * returns true if and only if this set contains an element e such that (o==null ?
  3398. * e==null : o.equals(e)).
  3399. * @param {Object} e
  3400. * @return {boolean}
  3401. */
  3402. contains() {}
  3403. }
  3404. /**
  3405. * @see http://download.oracle.com/javase/6/docs/api/java/util/SortedSet.html
  3406. */
  3407. class SortedSet extends Set {}
  3408. /**
  3409. * @see http://download.oracle.com/javase/6/docs/api/java/util/TreeSet.html
  3410. */
  3411. class TreeSet extends SortedSet {
  3412. constructor(o) {
  3413. super();
  3414. this.array = [];
  3415. if (o instanceof Collection) this.addAll(o);
  3416. }
  3417. contains(o) {
  3418. for (const e of this.array) if (e.compareTo(o) === 0) return true;
  3419. return false;
  3420. }
  3421. add(o) {
  3422. if (this.contains(o)) return false;
  3423. for (let i = 0, len = this.array.length; i < len; i++) {
  3424. const e = this.array[i];
  3425. if (e.compareTo(o) === 1) return !!this.array.splice(i, 0, o);
  3426. }
  3427. this.array.push(o);
  3428. return true;
  3429. }
  3430. addAll(c) {
  3431. for (const e of c) this.add(e);
  3432. return true;
  3433. }
  3434. remove() {
  3435. throw new UnsupportedOperationException();
  3436. }
  3437. size() {
  3438. return this.array.length;
  3439. }
  3440. isEmpty() {
  3441. return this.array.length === 0;
  3442. }
  3443. toArray() {
  3444. return this.array.slice();
  3445. }
  3446. iterator() {
  3447. return new Iterator$2(this.array);
  3448. }
  3449. }
  3450. class Iterator$2 {
  3451. constructor(array) {
  3452. this.array = array;
  3453. this.position = 0;
  3454. }
  3455. next() {
  3456. if (this.position === this.array.length) throw new NoSuchElementException();
  3457. return this.array[this.position++];
  3458. }
  3459. hasNext() {
  3460. return this.position < this.array.length;
  3461. }
  3462. remove() {
  3463. throw new UnsupportedOperationException();
  3464. }
  3465. }
  3466. class GeometryCollection extends Geometry {
  3467. constructor() {
  3468. super();
  3469. GeometryCollection.constructor_.apply(this, arguments);
  3470. }
  3471. static constructor_() {
  3472. this._geometries = null;
  3473. if (arguments.length === 0) ; else if (arguments.length === 2) {
  3474. let geometries = arguments[0],
  3475. factory = arguments[1];
  3476. Geometry.constructor_.call(this, factory);
  3477. if (geometries === null) geometries = [];
  3478. if (Geometry.hasNullElements(geometries)) throw new IllegalArgumentException('geometries must not contain null elements');
  3479. this._geometries = geometries;
  3480. }
  3481. }
  3482. computeEnvelopeInternal() {
  3483. const envelope = new Envelope();
  3484. for (let i = 0; i < this._geometries.length; i++) envelope.expandToInclude(this._geometries[i].getEnvelopeInternal());
  3485. return envelope;
  3486. }
  3487. getGeometryN(n) {
  3488. return this._geometries[n];
  3489. }
  3490. getCoordinates() {
  3491. const coordinates = new Array(this.getNumPoints()).fill(null);
  3492. let k = -1;
  3493. for (let i = 0; i < this._geometries.length; i++) {
  3494. const childCoordinates = this._geometries[i].getCoordinates();
  3495. for (let j = 0; j < childCoordinates.length; j++) {
  3496. k++;
  3497. coordinates[k] = childCoordinates[j];
  3498. }
  3499. }
  3500. return coordinates;
  3501. }
  3502. getArea() {
  3503. let area = 0.0;
  3504. for (let i = 0; i < this._geometries.length; i++) area += this._geometries[i].getArea();
  3505. return area;
  3506. }
  3507. copyInternal() {
  3508. const geometries = new Array(this._geometries.length).fill(null);
  3509. for (let i = 0; i < geometries.length; i++) geometries[i] = this._geometries[i].copy();
  3510. return new GeometryCollection(geometries, this._factory);
  3511. }
  3512. equalsExact() {
  3513. if (arguments.length === 2 && typeof arguments[1] === 'number' && arguments[0] instanceof Geometry) {
  3514. const other = arguments[0],
  3515. tolerance = arguments[1];
  3516. if (!this.isEquivalentClass(other)) return false;
  3517. const otherCollection = other;
  3518. if (this._geometries.length !== otherCollection._geometries.length) return false;
  3519. for (let i = 0; i < this._geometries.length; i++) if (!this._geometries[i].equalsExact(otherCollection._geometries[i], tolerance)) return false;
  3520. return true;
  3521. } else {
  3522. return super.equalsExact.apply(this, arguments);
  3523. }
  3524. }
  3525. normalize() {
  3526. for (let i = 0; i < this._geometries.length; i++) this._geometries[i].normalize();
  3527. Arrays.sort(this._geometries);
  3528. }
  3529. getCoordinate() {
  3530. if (this.isEmpty()) return null;
  3531. return this._geometries[0].getCoordinate();
  3532. }
  3533. getBoundaryDimension() {
  3534. let dimension = Dimension.FALSE;
  3535. for (let i = 0; i < this._geometries.length; i++) dimension = Math.max(dimension, this._geometries[i].getBoundaryDimension());
  3536. return dimension;
  3537. }
  3538. reverseInternal() {
  3539. const numGeometries = this._geometries.length;
  3540. const reversed = new ArrayList(numGeometries);
  3541. for (let i = 0; i < numGeometries; i++) reversed.add(this._geometries[i].reverse());
  3542. return this.getFactory().buildGeometry(reversed);
  3543. }
  3544. getTypeCode() {
  3545. return Geometry.TYPECODE_GEOMETRYCOLLECTION;
  3546. }
  3547. getDimension() {
  3548. let dimension = Dimension.FALSE;
  3549. for (let i = 0; i < this._geometries.length; i++) dimension = Math.max(dimension, this._geometries[i].getDimension());
  3550. return dimension;
  3551. }
  3552. getLength() {
  3553. let sum = 0.0;
  3554. for (let i = 0; i < this._geometries.length; i++) sum += this._geometries[i].getLength();
  3555. return sum;
  3556. }
  3557. getNumPoints() {
  3558. let numPoints = 0;
  3559. for (let i = 0; i < this._geometries.length; i++) numPoints += this._geometries[i].getNumPoints();
  3560. return numPoints;
  3561. }
  3562. getNumGeometries() {
  3563. return this._geometries.length;
  3564. }
  3565. compareToSameClass() {
  3566. if (arguments.length === 1) {
  3567. const o = arguments[0];
  3568. const theseElements = new TreeSet(Arrays.asList(this._geometries));
  3569. const otherElements = new TreeSet(Arrays.asList(o._geometries));
  3570. return this.compare(theseElements, otherElements);
  3571. } else if (arguments.length === 2) {
  3572. const o = arguments[0],
  3573. comp = arguments[1];
  3574. const gc = o;
  3575. const n1 = this.getNumGeometries();
  3576. const n2 = gc.getNumGeometries();
  3577. let i = 0;
  3578. while (i < n1 && i < n2) {
  3579. const thisGeom = this.getGeometryN(i);
  3580. const otherGeom = gc.getGeometryN(i);
  3581. const holeComp = thisGeom.compareToSameClass(otherGeom, comp);
  3582. if (holeComp !== 0) return holeComp;
  3583. i++;
  3584. }
  3585. if (i < n1) return 1;
  3586. if (i < n2) return -1;
  3587. return 0;
  3588. }
  3589. }
  3590. apply() {
  3591. if (hasInterface(arguments[0], CoordinateFilter)) {
  3592. const filter = arguments[0];
  3593. for (let i = 0; i < this._geometries.length; i++) this._geometries[i].apply(filter);
  3594. } else if (hasInterface(arguments[0], CoordinateSequenceFilter)) {
  3595. const filter = arguments[0];
  3596. if (this._geometries.length === 0) return null;
  3597. for (let i = 0; i < this._geometries.length; i++) {
  3598. this._geometries[i].apply(filter);
  3599. if (filter.isDone()) break;
  3600. }
  3601. if (filter.isGeometryChanged()) this.geometryChanged();
  3602. } else if (hasInterface(arguments[0], GeometryFilter)) {
  3603. const filter = arguments[0];
  3604. filter.filter(this);
  3605. for (let i = 0; i < this._geometries.length; i++) this._geometries[i].apply(filter);
  3606. } else if (hasInterface(arguments[0], GeometryComponentFilter)) {
  3607. const filter = arguments[0];
  3608. filter.filter(this);
  3609. for (let i = 0; i < this._geometries.length; i++) this._geometries[i].apply(filter);
  3610. }
  3611. }
  3612. getBoundary() {
  3613. Geometry.checkNotGeometryCollection(this);
  3614. Assert.shouldNeverReachHere();
  3615. return null;
  3616. }
  3617. getGeometryType() {
  3618. return Geometry.TYPENAME_GEOMETRYCOLLECTION;
  3619. }
  3620. isEmpty() {
  3621. for (let i = 0; i < this._geometries.length; i++) if (!this._geometries[i].isEmpty()) return false;
  3622. return true;
  3623. }
  3624. }
  3625. class MultiPoint extends GeometryCollection {
  3626. constructor() {
  3627. super();
  3628. MultiPoint.constructor_.apply(this, arguments);
  3629. }
  3630. static constructor_() {
  3631. const points = arguments[0],
  3632. factory = arguments[1];
  3633. GeometryCollection.constructor_.call(this, points, factory);
  3634. }
  3635. copyInternal() {
  3636. const points = new Array(this._geometries.length).fill(null);
  3637. for (let i = 0; i < points.length; i++) points[i] = this._geometries[i].copy();
  3638. return new MultiPoint(points, this._factory);
  3639. }
  3640. isValid() {
  3641. return true;
  3642. }
  3643. equalsExact() {
  3644. if (arguments.length === 2 && typeof arguments[1] === 'number' && arguments[0] instanceof Geometry) {
  3645. const other = arguments[0],
  3646. tolerance = arguments[1];
  3647. if (!this.isEquivalentClass(other)) return false;
  3648. return super.equalsExact.call(this, other, tolerance);
  3649. } else {
  3650. return super.equalsExact.apply(this, arguments);
  3651. }
  3652. }
  3653. getCoordinate() {
  3654. if (arguments.length === 1 && Number.isInteger(arguments[0])) {
  3655. const n = arguments[0];
  3656. return this._geometries[n].getCoordinate();
  3657. } else {
  3658. return super.getCoordinate.apply(this, arguments);
  3659. }
  3660. }
  3661. getBoundaryDimension() {
  3662. return Dimension.FALSE;
  3663. }
  3664. getTypeCode() {
  3665. return Geometry.TYPECODE_MULTIPOINT;
  3666. }
  3667. getDimension() {
  3668. return 0;
  3669. }
  3670. getBoundary() {
  3671. return this.getFactory().createGeometryCollection();
  3672. }
  3673. getGeometryType() {
  3674. return Geometry.TYPENAME_MULTIPOINT;
  3675. }
  3676. get interfaces_() {
  3677. return [Puntal];
  3678. }
  3679. }
  3680. class LinearRing extends LineString {
  3681. constructor() {
  3682. super();
  3683. LinearRing.constructor_.apply(this, arguments);
  3684. }
  3685. static constructor_() {
  3686. const points = arguments[0],
  3687. factory = arguments[1];
  3688. LineString.constructor_.call(this, points, factory);
  3689. this.validateConstruction();
  3690. }
  3691. copyInternal() {
  3692. return new LinearRing(this._points.copy(), this._factory);
  3693. }
  3694. getBoundaryDimension() {
  3695. return Dimension.FALSE;
  3696. }
  3697. isClosed() {
  3698. if (this.isEmpty()) return true;
  3699. return super.isClosed.call(this);
  3700. }
  3701. reverseInternal() {
  3702. const seq = this._points.copy();
  3703. CoordinateSequences.reverse(seq);
  3704. return this.getFactory().createLinearRing(seq);
  3705. }
  3706. getTypeCode() {
  3707. return Geometry.TYPECODE_LINEARRING;
  3708. }
  3709. validateConstruction() {
  3710. if (!this.isEmpty() && !super.isClosed.call(this)) throw new IllegalArgumentException('Points of LinearRing do not form a closed linestring');
  3711. if (this.getCoordinateSequence().size() >= 1 && this.getCoordinateSequence().size() < LinearRing.MINIMUM_VALID_SIZE) throw new IllegalArgumentException('Invalid number of points in LinearRing (found ' + this.getCoordinateSequence().size() + ' - must be 0 or >= 4)');
  3712. }
  3713. getGeometryType() {
  3714. return Geometry.TYPENAME_LINEARRING;
  3715. }
  3716. }
  3717. LinearRing.MINIMUM_VALID_SIZE = 4;
  3718. class Coordinates {
  3719. static measures(coordinate) {
  3720. if (coordinate instanceof CoordinateXY) return 0;else if (coordinate instanceof CoordinateXYM) return 1;else if (coordinate instanceof CoordinateXYZM) return 1;else if (coordinate instanceof Coordinate) return 0;
  3721. return 0;
  3722. }
  3723. static dimension(coordinate) {
  3724. if (coordinate instanceof CoordinateXY) return 2;else if (coordinate instanceof CoordinateXYM) return 3;else if (coordinate instanceof CoordinateXYZM) return 4;else if (coordinate instanceof Coordinate) return 3;
  3725. return 3;
  3726. }
  3727. static create() {
  3728. if (arguments.length === 1) {
  3729. const dimension = arguments[0];
  3730. return Coordinates.create(dimension, 0);
  3731. } else if (arguments.length === 2) {
  3732. const dimension = arguments[0],
  3733. measures = arguments[1];
  3734. if (dimension === 2) return new CoordinateXY();else if (dimension === 3 && measures === 0) return new Coordinate();else if (dimension === 3 && measures === 1) return new CoordinateXYM();else if (dimension === 4 && measures === 1) return new CoordinateXYZM();
  3735. return new Coordinate();
  3736. }
  3737. }
  3738. }
  3739. class CoordinateArrays {
  3740. static isRing(pts) {
  3741. if (pts.length < 4) return false;
  3742. if (!pts[0].equals2D(pts[pts.length - 1])) return false;
  3743. return true;
  3744. }
  3745. static ptNotInList(testPts, pts) {
  3746. for (let i = 0; i < testPts.length; i++) {
  3747. const testPt = testPts[i];
  3748. if (CoordinateArrays.indexOf(testPt, pts) < 0) return testPt;
  3749. }
  3750. return null;
  3751. }
  3752. static scroll(coordinates, firstCoordinate) {
  3753. const i = CoordinateArrays.indexOf(firstCoordinate, coordinates);
  3754. if (i < 0) return null;
  3755. const newCoordinates = new Array(coordinates.length).fill(null);
  3756. System.arraycopy(coordinates, i, newCoordinates, 0, coordinates.length - i);
  3757. System.arraycopy(coordinates, 0, newCoordinates, coordinates.length - i, i);
  3758. System.arraycopy(newCoordinates, 0, coordinates, 0, coordinates.length);
  3759. }
  3760. static equals() {
  3761. if (arguments.length === 2) {
  3762. const coord1 = arguments[0],
  3763. coord2 = arguments[1];
  3764. if (coord1 === coord2) return true;
  3765. if (coord1 === null || coord2 === null) return false;
  3766. if (coord1.length !== coord2.length) return false;
  3767. for (let i = 0; i < coord1.length; i++) if (!coord1[i].equals(coord2[i])) return false;
  3768. return true;
  3769. } else if (arguments.length === 3) {
  3770. const coord1 = arguments[0],
  3771. coord2 = arguments[1],
  3772. coordinateComparator = arguments[2];
  3773. if (coord1 === coord2) return true;
  3774. if (coord1 === null || coord2 === null) return false;
  3775. if (coord1.length !== coord2.length) return false;
  3776. for (let i = 0; i < coord1.length; i++) if (coordinateComparator.compare(coord1[i], coord2[i]) !== 0) return false;
  3777. return true;
  3778. }
  3779. }
  3780. static intersection(coordinates, env) {
  3781. const coordList = new CoordinateList();
  3782. for (let i = 0; i < coordinates.length; i++) if (env.intersects(coordinates[i])) coordList.add(coordinates[i], true);
  3783. return coordList.toCoordinateArray();
  3784. }
  3785. static measures(pts) {
  3786. if (pts === null || pts.length === 0) return 0;
  3787. let measures = 0;
  3788. for (const coordinate of pts) measures = Math.max(measures, Coordinates.measures(coordinate));
  3789. return measures;
  3790. }
  3791. static hasRepeatedPoints(coord) {
  3792. for (let i = 1; i < coord.length; i++) if (coord[i - 1].equals(coord[i])) return true;
  3793. return false;
  3794. }
  3795. static removeRepeatedPoints(coord) {
  3796. if (!CoordinateArrays.hasRepeatedPoints(coord)) return coord;
  3797. const coordList = new CoordinateList(coord, false);
  3798. return coordList.toCoordinateArray();
  3799. }
  3800. static reverse(coord) {
  3801. const last = coord.length - 1;
  3802. const mid = Math.trunc(last / 2);
  3803. for (let i = 0; i <= mid; i++) {
  3804. const tmp = coord[i];
  3805. coord[i] = coord[last - i];
  3806. coord[last - i] = tmp;
  3807. }
  3808. }
  3809. static removeNull(coord) {
  3810. let nonNull = 0;
  3811. for (let i = 0; i < coord.length; i++) if (coord[i] !== null) nonNull++;
  3812. const newCoord = new Array(nonNull).fill(null);
  3813. if (nonNull === 0) return newCoord;
  3814. let j = 0;
  3815. for (let i = 0; i < coord.length; i++) if (coord[i] !== null) newCoord[j++] = coord[i];
  3816. return newCoord;
  3817. }
  3818. static copyDeep() {
  3819. if (arguments.length === 1) {
  3820. const coordinates = arguments[0];
  3821. const copy = new Array(coordinates.length).fill(null);
  3822. for (let i = 0; i < coordinates.length; i++) copy[i] = coordinates[i].copy();
  3823. return copy;
  3824. } else if (arguments.length === 5) {
  3825. const src = arguments[0],
  3826. srcStart = arguments[1],
  3827. dest = arguments[2],
  3828. destStart = arguments[3],
  3829. length = arguments[4];
  3830. for (let i = 0; i < length; i++) dest[destStart + i] = src[srcStart + i].copy();
  3831. }
  3832. }
  3833. static isEqualReversed(pts1, pts2) {
  3834. for (let i = 0; i < pts1.length; i++) {
  3835. const p1 = pts1[i];
  3836. const p2 = pts2[pts1.length - i - 1];
  3837. if (p1.compareTo(p2) !== 0) return false;
  3838. }
  3839. return true;
  3840. }
  3841. static envelope(coordinates) {
  3842. const env = new Envelope();
  3843. for (let i = 0; i < coordinates.length; i++) env.expandToInclude(coordinates[i]);
  3844. return env;
  3845. }
  3846. static toCoordinateArray(coordList) {
  3847. return coordList.toArray(CoordinateArrays.coordArrayType);
  3848. }
  3849. static dimension(pts) {
  3850. if (pts === null || pts.length === 0) return 3;
  3851. let dimension = 0;
  3852. for (const coordinate of pts) dimension = Math.max(dimension, Coordinates.dimension(coordinate));
  3853. return dimension;
  3854. }
  3855. static atLeastNCoordinatesOrNothing(n, c) {
  3856. return c.length >= n ? c : [];
  3857. }
  3858. static indexOf(coordinate, coordinates) {
  3859. for (let i = 0; i < coordinates.length; i++) if (coordinate.equals(coordinates[i])) return i;
  3860. return -1;
  3861. }
  3862. static increasingDirection(pts) {
  3863. for (let i = 0; i < Math.trunc(pts.length / 2); i++) {
  3864. const j = pts.length - 1 - i;
  3865. const comp = pts[i].compareTo(pts[j]);
  3866. if (comp !== 0) return comp;
  3867. }
  3868. return 1;
  3869. }
  3870. static compare(pts1, pts2) {
  3871. let i = 0;
  3872. while (i < pts1.length && i < pts2.length) {
  3873. const compare = pts1[i].compareTo(pts2[i]);
  3874. if (compare !== 0) return compare;
  3875. i++;
  3876. }
  3877. if (i < pts2.length) return -1;
  3878. if (i < pts1.length) return 1;
  3879. return 0;
  3880. }
  3881. static minCoordinate(coordinates) {
  3882. let minCoord = null;
  3883. for (let i = 0; i < coordinates.length; i++) if (minCoord === null || minCoord.compareTo(coordinates[i]) > 0) minCoord = coordinates[i];
  3884. return minCoord;
  3885. }
  3886. static extract(pts, start, end) {
  3887. start = MathUtil.clamp(start, 0, pts.length);
  3888. end = MathUtil.clamp(end, -1, pts.length);
  3889. let npts = end - start + 1;
  3890. if (end < 0) npts = 0;
  3891. if (start >= pts.length) npts = 0;
  3892. if (end < start) npts = 0;
  3893. const extractPts = new Array(npts).fill(null);
  3894. if (npts === 0) return extractPts;
  3895. let iPts = 0;
  3896. for (let i = start; i <= end; i++) extractPts[iPts++] = pts[i];
  3897. return extractPts;
  3898. }
  3899. }
  3900. class ForwardComparator {
  3901. compare(o1, o2) {
  3902. const pts1 = o1;
  3903. const pts2 = o2;
  3904. return CoordinateArrays.compare(pts1, pts2);
  3905. }
  3906. get interfaces_() {
  3907. return [Comparator];
  3908. }
  3909. }
  3910. class BidirectionalComparator {
  3911. compare(o1, o2) {
  3912. const pts1 = o1;
  3913. const pts2 = o2;
  3914. if (pts1.length < pts2.length) return -1;
  3915. if (pts1.length > pts2.length) return 1;
  3916. if (pts1.length === 0) return 0;
  3917. const forwardComp = CoordinateArrays.compare(pts1, pts2);
  3918. const isEqualRev = CoordinateArrays.isEqualReversed(pts1, pts2);
  3919. if (isEqualRev) return 0;
  3920. return forwardComp;
  3921. }
  3922. OLDcompare(o1, o2) {
  3923. const pts1 = o1;
  3924. const pts2 = o2;
  3925. if (pts1.length < pts2.length) return -1;
  3926. if (pts1.length > pts2.length) return 1;
  3927. if (pts1.length === 0) return 0;
  3928. const dir1 = CoordinateArrays.increasingDirection(pts1);
  3929. const dir2 = CoordinateArrays.increasingDirection(pts2);
  3930. let i1 = dir1 > 0 ? 0 : pts1.length - 1;
  3931. let i2 = dir2 > 0 ? 0 : pts1.length - 1;
  3932. for (let i = 0; i < pts1.length; i++) {
  3933. const comparePt = pts1[i1].compareTo(pts2[i2]);
  3934. if (comparePt !== 0) return comparePt;
  3935. i1 += dir1;
  3936. i2 += dir2;
  3937. }
  3938. return 0;
  3939. }
  3940. get interfaces_() {
  3941. return [Comparator];
  3942. }
  3943. }
  3944. CoordinateArrays.ForwardComparator = ForwardComparator;
  3945. CoordinateArrays.BidirectionalComparator = BidirectionalComparator;
  3946. CoordinateArrays.coordArrayType = new Array(0).fill(null);
  3947. class StringBuilder {
  3948. constructor(str) {
  3949. this.str = str;
  3950. }
  3951. append(e) {
  3952. this.str += e;
  3953. }
  3954. setCharAt(i, c) {
  3955. this.str = this.str.substr(0, i) + c + this.str.substr(i + 1);
  3956. }
  3957. toString() {
  3958. return this.str;
  3959. }
  3960. }
  3961. class CoordinateArraySequence {
  3962. constructor() {
  3963. CoordinateArraySequence.constructor_.apply(this, arguments);
  3964. }
  3965. static constructor_() {
  3966. this._dimension = 3;
  3967. this._measures = 0;
  3968. this._coordinates = null;
  3969. if (arguments.length === 1) {
  3970. if (arguments[0] instanceof Array) {
  3971. const coordinates = arguments[0];
  3972. CoordinateArraySequence.constructor_.call(this, coordinates, CoordinateArrays.dimension(coordinates), CoordinateArrays.measures(coordinates));
  3973. } else if (Number.isInteger(arguments[0])) {
  3974. const size = arguments[0];
  3975. this._coordinates = new Array(size).fill(null);
  3976. for (let i = 0; i < size; i++) this._coordinates[i] = new Coordinate();
  3977. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  3978. const coordSeq = arguments[0];
  3979. if (coordSeq === null) {
  3980. this._coordinates = new Array(0).fill(null);
  3981. return null;
  3982. }
  3983. this._dimension = coordSeq.getDimension();
  3984. this._measures = coordSeq.getMeasures();
  3985. this._coordinates = new Array(coordSeq.size()).fill(null);
  3986. for (let i = 0; i < this._coordinates.length; i++) this._coordinates[i] = coordSeq.getCoordinateCopy(i);
  3987. }
  3988. } else if (arguments.length === 2) {
  3989. if (arguments[0] instanceof Array && Number.isInteger(arguments[1])) {
  3990. const coordinates = arguments[0],
  3991. dimension = arguments[1];
  3992. CoordinateArraySequence.constructor_.call(this, coordinates, dimension, CoordinateArrays.measures(coordinates));
  3993. } else if (Number.isInteger(arguments[0]) && Number.isInteger(arguments[1])) {
  3994. const size = arguments[0],
  3995. dimension = arguments[1];
  3996. this._coordinates = new Array(size).fill(null);
  3997. this._dimension = dimension;
  3998. for (let i = 0; i < size; i++) this._coordinates[i] = Coordinates.create(dimension);
  3999. }
  4000. } else if (arguments.length === 3) {
  4001. if (Number.isInteger(arguments[2]) && arguments[0] instanceof Array && Number.isInteger(arguments[1])) {
  4002. const coordinates = arguments[0],
  4003. dimension = arguments[1],
  4004. measures = arguments[2];
  4005. this._dimension = dimension;
  4006. this._measures = measures;
  4007. if (coordinates === null) this._coordinates = new Array(0).fill(null);else this._coordinates = coordinates;
  4008. } else if (Number.isInteger(arguments[2]) && Number.isInteger(arguments[0]) && Number.isInteger(arguments[1])) {
  4009. const size = arguments[0],
  4010. dimension = arguments[1],
  4011. measures = arguments[2];
  4012. this._coordinates = new Array(size).fill(null);
  4013. this._dimension = dimension;
  4014. this._measures = measures;
  4015. for (let i = 0; i < size; i++) this._coordinates[i] = this.createCoordinate();
  4016. }
  4017. }
  4018. }
  4019. getM(index) {
  4020. if (this.hasM()) return this._coordinates[index].getM();else return Double.NaN;
  4021. }
  4022. setOrdinate(index, ordinateIndex, value) {
  4023. switch (ordinateIndex) {
  4024. case CoordinateSequence.X:
  4025. this._coordinates[index].x = value;
  4026. break;
  4027. case CoordinateSequence.Y:
  4028. this._coordinates[index].y = value;
  4029. break;
  4030. default:
  4031. this._coordinates[index].setOrdinate(ordinateIndex, value);
  4032. }
  4033. }
  4034. getZ(index) {
  4035. if (this.hasZ()) return this._coordinates[index].getZ();else return Double.NaN;
  4036. }
  4037. size() {
  4038. return this._coordinates.length;
  4039. }
  4040. getOrdinate(index, ordinateIndex) {
  4041. switch (ordinateIndex) {
  4042. case CoordinateSequence.X:
  4043. return this._coordinates[index].x;
  4044. case CoordinateSequence.Y:
  4045. return this._coordinates[index].y;
  4046. default:
  4047. return this._coordinates[index].getOrdinate(ordinateIndex);
  4048. }
  4049. }
  4050. getCoordinate() {
  4051. if (arguments.length === 1) {
  4052. const i = arguments[0];
  4053. return this._coordinates[i];
  4054. } else if (arguments.length === 2) {
  4055. const index = arguments[0],
  4056. coord = arguments[1];
  4057. coord.setCoordinate(this._coordinates[index]);
  4058. }
  4059. }
  4060. getCoordinateCopy(i) {
  4061. const copy = this.createCoordinate();
  4062. copy.setCoordinate(this._coordinates[i]);
  4063. return copy;
  4064. }
  4065. createCoordinate() {
  4066. return Coordinates.create(this.getDimension(), this.getMeasures());
  4067. }
  4068. getDimension() {
  4069. return this._dimension;
  4070. }
  4071. getX(index) {
  4072. return this._coordinates[index].x;
  4073. }
  4074. getMeasures() {
  4075. return this._measures;
  4076. }
  4077. expandEnvelope(env) {
  4078. for (let i = 0; i < this._coordinates.length; i++) env.expandToInclude(this._coordinates[i]);
  4079. return env;
  4080. }
  4081. copy() {
  4082. const cloneCoordinates = new Array(this.size()).fill(null);
  4083. for (let i = 0; i < this._coordinates.length; i++) {
  4084. const duplicate = this.createCoordinate();
  4085. duplicate.setCoordinate(this._coordinates[i]);
  4086. cloneCoordinates[i] = duplicate;
  4087. }
  4088. return new CoordinateArraySequence(cloneCoordinates, this._dimension, this._measures);
  4089. }
  4090. toString() {
  4091. if (this._coordinates.length > 0) {
  4092. const strBuilder = new StringBuilder(17 * this._coordinates.length);
  4093. strBuilder.append('(');
  4094. strBuilder.append(this._coordinates[0]);
  4095. for (let i = 1; i < this._coordinates.length; i++) {
  4096. strBuilder.append(', ');
  4097. strBuilder.append(this._coordinates[i]);
  4098. }
  4099. strBuilder.append(')');
  4100. return strBuilder.toString();
  4101. } else {
  4102. return '()';
  4103. }
  4104. }
  4105. getY(index) {
  4106. return this._coordinates[index].y;
  4107. }
  4108. toCoordinateArray() {
  4109. return this._coordinates;
  4110. }
  4111. get interfaces_() {
  4112. return [CoordinateSequence, Serializable];
  4113. }
  4114. }
  4115. class CoordinateArraySequenceFactory {
  4116. static instance() {
  4117. return CoordinateArraySequenceFactory.instanceObject;
  4118. }
  4119. readResolve() {
  4120. return CoordinateArraySequenceFactory.instance();
  4121. }
  4122. create() {
  4123. if (arguments.length === 1) {
  4124. if (arguments[0] instanceof Array) {
  4125. const coordinates = arguments[0];
  4126. return new CoordinateArraySequence(coordinates);
  4127. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  4128. const coordSeq = arguments[0];
  4129. return new CoordinateArraySequence(coordSeq);
  4130. }
  4131. } else if (arguments.length === 2) {
  4132. let size = arguments[0],
  4133. dimension = arguments[1];
  4134. if (dimension > 3) dimension = 3;
  4135. if (dimension < 2) dimension = 2;
  4136. return new CoordinateArraySequence(size, dimension);
  4137. } else if (arguments.length === 3) {
  4138. let size = arguments[0],
  4139. dimension = arguments[1],
  4140. measures = arguments[2];
  4141. let spatial = dimension - measures;
  4142. if (measures > 1) measures = 1;
  4143. if (spatial > 3) spatial = 3;
  4144. if (spatial < 2) spatial = 2;
  4145. return new CoordinateArraySequence(size, spatial + measures, measures);
  4146. }
  4147. }
  4148. get interfaces_() {
  4149. return [CoordinateSequenceFactory, Serializable];
  4150. }
  4151. }
  4152. CoordinateArraySequenceFactory.instanceObject = new CoordinateArraySequenceFactory();
  4153. class MultiPolygon extends GeometryCollection {
  4154. constructor() {
  4155. super();
  4156. MultiPolygon.constructor_.apply(this, arguments);
  4157. }
  4158. static constructor_() {
  4159. const polygons = arguments[0],
  4160. factory = arguments[1];
  4161. GeometryCollection.constructor_.call(this, polygons, factory);
  4162. }
  4163. copyInternal() {
  4164. const polygons = new Array(this._geometries.length).fill(null);
  4165. for (let i = 0; i < polygons.length; i++) polygons[i] = this._geometries[i].copy();
  4166. return new MultiPolygon(polygons, this._factory);
  4167. }
  4168. equalsExact() {
  4169. if (arguments.length === 2 && typeof arguments[1] === 'number' && arguments[0] instanceof Geometry) {
  4170. const other = arguments[0],
  4171. tolerance = arguments[1];
  4172. if (!this.isEquivalentClass(other)) return false;
  4173. return super.equalsExact.call(this, other, tolerance);
  4174. } else {
  4175. return super.equalsExact.apply(this, arguments);
  4176. }
  4177. }
  4178. getBoundaryDimension() {
  4179. return 1;
  4180. }
  4181. getTypeCode() {
  4182. return Geometry.TYPECODE_MULTIPOLYGON;
  4183. }
  4184. getDimension() {
  4185. return 2;
  4186. }
  4187. getBoundary() {
  4188. if (this.isEmpty()) return this.getFactory().createMultiLineString();
  4189. const allRings = new ArrayList();
  4190. for (let i = 0; i < this._geometries.length; i++) {
  4191. const polygon = this._geometries[i];
  4192. const rings = polygon.getBoundary();
  4193. for (let j = 0; j < rings.getNumGeometries(); j++) allRings.add(rings.getGeometryN(j));
  4194. }
  4195. const allRingsArray = new Array(allRings.size()).fill(null);
  4196. return this.getFactory().createMultiLineString(allRings.toArray(allRingsArray));
  4197. }
  4198. getGeometryType() {
  4199. return Geometry.TYPENAME_MULTIPOLYGON;
  4200. }
  4201. get interfaces_() {
  4202. return [Polygonal];
  4203. }
  4204. }
  4205. /**
  4206. * @see http://download.oracle.com/javase/6/docs/api/java/util/Map.html
  4207. */
  4208. class Map$1 {
  4209. /**
  4210. * Returns the value to which the specified key is mapped, or null if this map
  4211. * contains no mapping for the key.
  4212. * @param {Object} key
  4213. * @return {Object}
  4214. */
  4215. get() {}
  4216. /**
  4217. * Associates the specified value with the specified key in this map (optional
  4218. * operation).
  4219. * @param {Object} key
  4220. * @param {Object} value
  4221. * @return {Object}
  4222. */
  4223. put() {}
  4224. /**
  4225. * Returns the number of key-value mappings in this map.
  4226. * @return {number}
  4227. */
  4228. size() {}
  4229. /**
  4230. * Returns a Collection view of the values contained in this map.
  4231. * @return {javascript.util.Collection}
  4232. */
  4233. values() {}
  4234. /**
  4235. * Returns a {@link Set} view of the mappings contained in this map.
  4236. * The set is backed by the map, so changes to the map are
  4237. * reflected in the set, and vice-versa. If the map is modified
  4238. * while an iteration over the set is in progress (except through
  4239. * the iterator's own <tt>remove</tt> operation, or through the
  4240. * <tt>setValue</tt> operation on a map entry returned by the
  4241. * iterator) the results of the iteration are undefined. The set
  4242. * supports element removal, which removes the corresponding
  4243. * mapping from the map, via the <tt>Iterator.remove</tt>,
  4244. * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
  4245. * <tt>clear</tt> operations. It does not support the
  4246. * <tt>add</tt> or <tt>addAll</tt> operations.
  4247. *
  4248. * @return {Set} a set view of the mappings contained in this map
  4249. */
  4250. entrySet() {}
  4251. }
  4252. /**
  4253. * @see http://docs.oracle.com/javase/6/docs/api/java/util/HashSet.html
  4254. */
  4255. class HashSet extends Set {
  4256. constructor(o) {
  4257. super();
  4258. this.map = new Map();
  4259. if (o instanceof Collection) this.addAll(o);
  4260. }
  4261. contains(o) {
  4262. const hashCode = o.hashCode ? o.hashCode() : o;
  4263. if (this.map.has(hashCode)) return true;
  4264. return false;
  4265. }
  4266. add(o) {
  4267. const hashCode = o.hashCode ? o.hashCode() : o;
  4268. if (this.map.has(hashCode)) return false;
  4269. return !!this.map.set(hashCode, o);
  4270. }
  4271. addAll(c) {
  4272. for (const e of c) this.add(e);
  4273. return true;
  4274. }
  4275. remove() {
  4276. throw new UnsupportedOperationException();
  4277. }
  4278. size() {
  4279. return this.map.size;
  4280. }
  4281. isEmpty() {
  4282. return this.map.size === 0;
  4283. }
  4284. toArray() {
  4285. return Array.from(this.map.values());
  4286. }
  4287. iterator() {
  4288. return new Iterator$1(this.map);
  4289. }
  4290. [Symbol.iterator]() {
  4291. return this.map;
  4292. }
  4293. }
  4294. class Iterator$1 {
  4295. constructor(map) {
  4296. this.iterator = map.values();
  4297. const {
  4298. done,
  4299. value
  4300. } = this.iterator.next();
  4301. this.done = done;
  4302. this.value = value;
  4303. }
  4304. next() {
  4305. if (this.done) throw new NoSuchElementException();
  4306. const current = this.value;
  4307. const {
  4308. done,
  4309. value
  4310. } = this.iterator.next();
  4311. this.done = done;
  4312. this.value = value;
  4313. return current;
  4314. }
  4315. hasNext() {
  4316. return !this.done;
  4317. }
  4318. remove() {
  4319. throw new UnsupportedOperationException();
  4320. }
  4321. }
  4322. /**
  4323. * @see http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html
  4324. */
  4325. class HashMap extends Map$1 {
  4326. constructor() {
  4327. super();
  4328. this.map = new Map();
  4329. }
  4330. get(key) {
  4331. return this.map.get(key) || null;
  4332. }
  4333. put(key, value) {
  4334. this.map.set(key, value);
  4335. return value;
  4336. }
  4337. values() {
  4338. const arrayList = new ArrayList();
  4339. const it = this.map.values();
  4340. let o = it.next();
  4341. while (!o.done) {
  4342. arrayList.add(o.value);
  4343. o = it.next();
  4344. }
  4345. return arrayList;
  4346. }
  4347. entrySet() {
  4348. const hashSet = new HashSet();
  4349. this.map.entries().forEach(entry => hashSet.add(entry));
  4350. return hashSet;
  4351. }
  4352. size() {
  4353. return this.map.size();
  4354. }
  4355. }
  4356. class PrecisionModel {
  4357. constructor() {
  4358. PrecisionModel.constructor_.apply(this, arguments);
  4359. }
  4360. static constructor_() {
  4361. this._modelType = null;
  4362. this._scale = null;
  4363. if (arguments.length === 0) this._modelType = PrecisionModel.FLOATING;else if (arguments.length === 1) if (arguments[0] instanceof Type) {
  4364. const modelType = arguments[0];
  4365. this._modelType = modelType;
  4366. if (modelType === PrecisionModel.FIXED) this.setScale(1.0);
  4367. } else if (typeof arguments[0] === 'number') {
  4368. const scale = arguments[0];
  4369. this._modelType = PrecisionModel.FIXED;
  4370. this.setScale(scale);
  4371. } else if (arguments[0] instanceof PrecisionModel) {
  4372. const pm = arguments[0];
  4373. this._modelType = pm._modelType;
  4374. this._scale = pm._scale;
  4375. }
  4376. }
  4377. static mostPrecise(pm1, pm2) {
  4378. if (pm1.compareTo(pm2) >= 0) return pm1;
  4379. return pm2;
  4380. }
  4381. equals(other) {
  4382. if (!(other instanceof PrecisionModel)) return false;
  4383. const otherPrecisionModel = other;
  4384. return this._modelType === otherPrecisionModel._modelType && this._scale === otherPrecisionModel._scale;
  4385. }
  4386. compareTo(o) {
  4387. const other = o;
  4388. const sigDigits = this.getMaximumSignificantDigits();
  4389. const otherSigDigits = other.getMaximumSignificantDigits();
  4390. return Integer.compare(sigDigits, otherSigDigits);
  4391. }
  4392. getScale() {
  4393. return this._scale;
  4394. }
  4395. isFloating() {
  4396. return this._modelType === PrecisionModel.FLOATING || this._modelType === PrecisionModel.FLOATING_SINGLE;
  4397. }
  4398. getType() {
  4399. return this._modelType;
  4400. }
  4401. toString() {
  4402. let description = 'UNKNOWN';
  4403. if (this._modelType === PrecisionModel.FLOATING) description = 'Floating';else if (this._modelType === PrecisionModel.FLOATING_SINGLE) description = 'Floating-Single';else if (this._modelType === PrecisionModel.FIXED) description = 'Fixed (Scale=' + this.getScale() + ')';
  4404. return description;
  4405. }
  4406. makePrecise() {
  4407. if (typeof arguments[0] === 'number') {
  4408. const val = arguments[0];
  4409. if (Double.isNaN(val)) return val;
  4410. if (this._modelType === PrecisionModel.FLOATING_SINGLE) {
  4411. const floatSingleVal = val;
  4412. return floatSingleVal;
  4413. }
  4414. if (this._modelType === PrecisionModel.FIXED) return Math.round(val * this._scale) / this._scale;
  4415. return val;
  4416. } else if (arguments[0] instanceof Coordinate) {
  4417. const coord = arguments[0];
  4418. if (this._modelType === PrecisionModel.FLOATING) return null;
  4419. coord.x = this.makePrecise(coord.x);
  4420. coord.y = this.makePrecise(coord.y);
  4421. }
  4422. }
  4423. getMaximumSignificantDigits() {
  4424. let maxSigDigits = 16;
  4425. if (this._modelType === PrecisionModel.FLOATING) maxSigDigits = 16;else if (this._modelType === PrecisionModel.FLOATING_SINGLE) maxSigDigits = 6;else if (this._modelType === PrecisionModel.FIXED) maxSigDigits = 1 + Math.trunc(Math.ceil(Math.log(this.getScale()) / Math.log(10)));
  4426. return maxSigDigits;
  4427. }
  4428. setScale(scale) {
  4429. this._scale = Math.abs(scale);
  4430. }
  4431. get interfaces_() {
  4432. return [Serializable, Comparable];
  4433. }
  4434. }
  4435. class Type {
  4436. constructor() {
  4437. Type.constructor_.apply(this, arguments);
  4438. }
  4439. static constructor_() {
  4440. this._name = null;
  4441. const name = arguments[0];
  4442. this._name = name;
  4443. Type.nameToTypeMap.put(name, this);
  4444. }
  4445. readResolve() {
  4446. return Type.nameToTypeMap.get(this._name);
  4447. }
  4448. toString() {
  4449. return this._name;
  4450. }
  4451. get interfaces_() {
  4452. return [Serializable];
  4453. }
  4454. }
  4455. Type.nameToTypeMap = new HashMap();
  4456. PrecisionModel.Type = Type;
  4457. PrecisionModel.FIXED = new Type('FIXED');
  4458. PrecisionModel.FLOATING = new Type('FLOATING');
  4459. PrecisionModel.FLOATING_SINGLE = new Type('FLOATING SINGLE');
  4460. PrecisionModel.maximumPreciseValue = 9007199254740992.0;
  4461. class MultiLineString extends GeometryCollection {
  4462. constructor() {
  4463. super();
  4464. MultiLineString.constructor_.apply(this, arguments);
  4465. }
  4466. static constructor_() {
  4467. const lineStrings = arguments[0],
  4468. factory = arguments[1];
  4469. GeometryCollection.constructor_.call(this, lineStrings, factory);
  4470. }
  4471. copyInternal() {
  4472. const lineStrings = new Array(this._geometries.length).fill(null);
  4473. for (let i = 0; i < lineStrings.length; i++) lineStrings[i] = this._geometries[i].copy();
  4474. return new MultiLineString(lineStrings, this._factory);
  4475. }
  4476. equalsExact() {
  4477. if (arguments.length === 2 && typeof arguments[1] === 'number' && arguments[0] instanceof Geometry) {
  4478. const other = arguments[0],
  4479. tolerance = arguments[1];
  4480. if (!this.isEquivalentClass(other)) return false;
  4481. return super.equalsExact.call(this, other, tolerance);
  4482. } else {
  4483. return super.equalsExact.apply(this, arguments);
  4484. }
  4485. }
  4486. getBoundaryDimension() {
  4487. if (this.isClosed()) return Dimension.FALSE;
  4488. return 0;
  4489. }
  4490. isClosed() {
  4491. if (this.isEmpty()) return false;
  4492. for (let i = 0; i < this._geometries.length; i++) if (!this._geometries[i].isClosed()) return false;
  4493. return true;
  4494. }
  4495. getTypeCode() {
  4496. return Geometry.TYPECODE_MULTILINESTRING;
  4497. }
  4498. getDimension() {
  4499. return 1;
  4500. }
  4501. getBoundary() {
  4502. throw new UnsupportedOperationException();
  4503. }
  4504. getGeometryType() {
  4505. return Geometry.TYPENAME_MULTILINESTRING;
  4506. }
  4507. get interfaces_() {
  4508. return [Lineal];
  4509. }
  4510. }
  4511. class GeometryFactory {
  4512. constructor() {
  4513. GeometryFactory.constructor_.apply(this, arguments);
  4514. }
  4515. static constructor_() {
  4516. this._precisionModel = null;
  4517. this._coordinateSequenceFactory = null;
  4518. this._SRID = null;
  4519. if (arguments.length === 0) {
  4520. GeometryFactory.constructor_.call(this, new PrecisionModel(), 0);
  4521. } else if (arguments.length === 1) {
  4522. if (hasInterface(arguments[0], CoordinateSequenceFactory)) {
  4523. const coordinateSequenceFactory = arguments[0];
  4524. GeometryFactory.constructor_.call(this, new PrecisionModel(), 0, coordinateSequenceFactory);
  4525. } else if (arguments[0] instanceof PrecisionModel) {
  4526. const precisionModel = arguments[0];
  4527. GeometryFactory.constructor_.call(this, precisionModel, 0, GeometryFactory.getDefaultCoordinateSequenceFactory());
  4528. }
  4529. } else if (arguments.length === 2) {
  4530. const precisionModel = arguments[0],
  4531. SRID = arguments[1];
  4532. GeometryFactory.constructor_.call(this, precisionModel, SRID, GeometryFactory.getDefaultCoordinateSequenceFactory());
  4533. } else if (arguments.length === 3) {
  4534. const precisionModel = arguments[0],
  4535. SRID = arguments[1],
  4536. coordinateSequenceFactory = arguments[2];
  4537. this._precisionModel = precisionModel;
  4538. this._coordinateSequenceFactory = coordinateSequenceFactory;
  4539. this._SRID = SRID;
  4540. }
  4541. }
  4542. static toMultiPolygonArray(multiPolygons) {
  4543. const multiPolygonArray = new Array(multiPolygons.size()).fill(null);
  4544. return multiPolygons.toArray(multiPolygonArray);
  4545. }
  4546. static toGeometryArray(geometries) {
  4547. if (geometries === null) return null;
  4548. const geometryArray = new Array(geometries.size()).fill(null);
  4549. return geometries.toArray(geometryArray);
  4550. }
  4551. static getDefaultCoordinateSequenceFactory() {
  4552. return CoordinateArraySequenceFactory.instance();
  4553. }
  4554. static toMultiLineStringArray(multiLineStrings) {
  4555. const multiLineStringArray = new Array(multiLineStrings.size()).fill(null);
  4556. return multiLineStrings.toArray(multiLineStringArray);
  4557. }
  4558. static toLineStringArray(lineStrings) {
  4559. const lineStringArray = new Array(lineStrings.size()).fill(null);
  4560. return lineStrings.toArray(lineStringArray);
  4561. }
  4562. static toMultiPointArray(multiPoints) {
  4563. const multiPointArray = new Array(multiPoints.size()).fill(null);
  4564. return multiPoints.toArray(multiPointArray);
  4565. }
  4566. static toLinearRingArray(linearRings) {
  4567. const linearRingArray = new Array(linearRings.size()).fill(null);
  4568. return linearRings.toArray(linearRingArray);
  4569. }
  4570. static toPointArray(points) {
  4571. const pointArray = new Array(points.size()).fill(null);
  4572. return points.toArray(pointArray);
  4573. }
  4574. static toPolygonArray(polygons) {
  4575. const polygonArray = new Array(polygons.size()).fill(null);
  4576. return polygons.toArray(polygonArray);
  4577. }
  4578. static createPointFromInternalCoord(coord, exemplar) {
  4579. exemplar.getPrecisionModel().makePrecise(coord);
  4580. return exemplar.getFactory().createPoint(coord);
  4581. }
  4582. createEmpty(dimension) {
  4583. switch (dimension) {
  4584. case -1:
  4585. return this.createGeometryCollection();
  4586. case 0:
  4587. return this.createPoint();
  4588. case 1:
  4589. return this.createLineString();
  4590. case 2:
  4591. return this.createPolygon();
  4592. default:
  4593. throw new IllegalArgumentException('Invalid dimension: ' + dimension);
  4594. }
  4595. }
  4596. toGeometry(envelope) {
  4597. if (envelope.isNull()) return this.createPoint();
  4598. if (envelope.getMinX() === envelope.getMaxX() && envelope.getMinY() === envelope.getMaxY()) return this.createPoint(new Coordinate(envelope.getMinX(), envelope.getMinY()));
  4599. if (envelope.getMinX() === envelope.getMaxX() || envelope.getMinY() === envelope.getMaxY()) return this.createLineString([new Coordinate(envelope.getMinX(), envelope.getMinY()), new Coordinate(envelope.getMaxX(), envelope.getMaxY())]);
  4600. 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);
  4601. }
  4602. createLineString() {
  4603. if (arguments.length === 0) return this.createLineString(this.getCoordinateSequenceFactory().create([]));else if (arguments.length === 1) if (arguments[0] instanceof Array) {
  4604. const coordinates = arguments[0];
  4605. return this.createLineString(coordinates !== null ? this.getCoordinateSequenceFactory().create(coordinates) : null);
  4606. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  4607. const coordinates = arguments[0];
  4608. return new LineString(coordinates, this);
  4609. }
  4610. }
  4611. createMultiLineString() {
  4612. if (arguments.length === 0) {
  4613. return new MultiLineString(null, this);
  4614. } else if (arguments.length === 1) {
  4615. const lineStrings = arguments[0];
  4616. return new MultiLineString(lineStrings, this);
  4617. }
  4618. }
  4619. buildGeometry(geomList) {
  4620. let geomType = null;
  4621. let isHeterogeneous = false;
  4622. let hasGeometryCollection = false;
  4623. for (let i = geomList.iterator(); i.hasNext();) {
  4624. const geom = i.next();
  4625. const partType = geom.getTypeCode();
  4626. if (geomType === null) geomType = partType;
  4627. if (partType !== geomType) isHeterogeneous = true;
  4628. if (geom instanceof GeometryCollection) hasGeometryCollection = true;
  4629. }
  4630. if (geomType === null) return this.createGeometryCollection();
  4631. if (isHeterogeneous || hasGeometryCollection) return this.createGeometryCollection(GeometryFactory.toGeometryArray(geomList));
  4632. const geom0 = geomList.iterator().next();
  4633. const isCollection = geomList.size() > 1;
  4634. if (isCollection) {
  4635. if (geom0 instanceof Polygon) return this.createMultiPolygon(GeometryFactory.toPolygonArray(geomList));else if (geom0 instanceof LineString) return this.createMultiLineString(GeometryFactory.toLineStringArray(geomList));else if (geom0 instanceof Point) return this.createMultiPoint(GeometryFactory.toPointArray(geomList));
  4636. Assert.shouldNeverReachHere('Unhandled geometry type: ' + geom0.getGeometryType());
  4637. }
  4638. return geom0;
  4639. }
  4640. createMultiPointFromCoords(coordinates) {
  4641. return this.createMultiPoint(coordinates !== null ? this.getCoordinateSequenceFactory().create(coordinates) : null);
  4642. }
  4643. createPoint() {
  4644. if (arguments.length === 0) return this.createPoint(this.getCoordinateSequenceFactory().create([]));else if (arguments.length === 1) if (arguments[0] instanceof Coordinate) {
  4645. const coordinate = arguments[0];
  4646. return this.createPoint(coordinate !== null ? this.getCoordinateSequenceFactory().create([coordinate]) : null);
  4647. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  4648. const coordinates = arguments[0];
  4649. return new Point(coordinates, this);
  4650. }
  4651. }
  4652. getCoordinateSequenceFactory() {
  4653. return this._coordinateSequenceFactory;
  4654. }
  4655. createPolygon() {
  4656. if (arguments.length === 0) {
  4657. return this.createPolygon(null, null);
  4658. } else if (arguments.length === 1) {
  4659. if (hasInterface(arguments[0], CoordinateSequence)) {
  4660. const shell = arguments[0];
  4661. return this.createPolygon(this.createLinearRing(shell));
  4662. } else if (arguments[0] instanceof Array) {
  4663. const shell = arguments[0];
  4664. return this.createPolygon(this.createLinearRing(shell));
  4665. } else if (arguments[0] instanceof LinearRing) {
  4666. const shell = arguments[0];
  4667. return this.createPolygon(shell, null);
  4668. }
  4669. } else if (arguments.length === 2) {
  4670. const shell = arguments[0],
  4671. holes = arguments[1];
  4672. return new Polygon(shell, holes, this);
  4673. }
  4674. }
  4675. getSRID() {
  4676. return this._SRID;
  4677. }
  4678. createGeometryCollection() {
  4679. if (arguments.length === 0) {
  4680. return new GeometryCollection(null, this);
  4681. } else if (arguments.length === 1) {
  4682. const geometries = arguments[0];
  4683. return new GeometryCollection(geometries, this);
  4684. }
  4685. }
  4686. getPrecisionModel() {
  4687. return this._precisionModel;
  4688. }
  4689. createLinearRing() {
  4690. if (arguments.length === 0) return this.createLinearRing(this.getCoordinateSequenceFactory().create([]));else if (arguments.length === 1) if (arguments[0] instanceof Array) {
  4691. const coordinates = arguments[0];
  4692. return this.createLinearRing(coordinates !== null ? this.getCoordinateSequenceFactory().create(coordinates) : null);
  4693. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  4694. const coordinates = arguments[0];
  4695. return new LinearRing(coordinates, this);
  4696. }
  4697. }
  4698. createMultiPolygon() {
  4699. if (arguments.length === 0) {
  4700. return new MultiPolygon(null, this);
  4701. } else if (arguments.length === 1) {
  4702. const polygons = arguments[0];
  4703. return new MultiPolygon(polygons, this);
  4704. }
  4705. }
  4706. createMultiPoint() {
  4707. if (arguments.length === 0) return new MultiPoint(null, this);else if (arguments.length === 1) if (arguments[0] instanceof Array) {
  4708. const point = arguments[0];
  4709. return new MultiPoint(point, this);
  4710. } else if (hasInterface(arguments[0], CoordinateSequence)) {
  4711. const coordinates = arguments[0];
  4712. if (coordinates === null) return this.createMultiPoint(new Array(0).fill(null));
  4713. const points = new Array(coordinates.size()).fill(null);
  4714. for (let i = 0; i < coordinates.size(); i++) {
  4715. const ptSeq = this.getCoordinateSequenceFactory().create(1, coordinates.getDimension(), coordinates.getMeasures());
  4716. CoordinateSequences.copy(coordinates, i, ptSeq, 0, 1);
  4717. points[i] = this.createPoint(ptSeq);
  4718. }
  4719. return this.createMultiPoint(points);
  4720. }
  4721. }
  4722. get interfaces_() {
  4723. return [Serializable];
  4724. }
  4725. }
  4726. /**
  4727. * The coordinate layout for geometries, indicating whether a 3rd or 4th z ('Z')
  4728. * or measure ('M') coordinate is available. Supported values are `'XY'`,
  4729. * `'XYZ'`, `'XYM'`, `'XYZM'`.
  4730. * @enum {string}
  4731. */
  4732. const GeometryLayout = {
  4733. XY: 'XY',
  4734. XYZ: 'XYZ',
  4735. XYM: 'XYM',
  4736. XYZM: 'XYZM'
  4737. };
  4738. /**
  4739. * The geometry type. One of `'Point'`, `'LineString'`, `'LinearRing'`,
  4740. * `'Polygon'`, `'MultiPoint'`, `'MultiLineString'`, `'MultiPolygon'`,
  4741. * `'GeometryCollection'`, `'Circle'`.
  4742. * @enum {string}
  4743. */
  4744. const GeometryType = {
  4745. POINT: 'Point',
  4746. LINE_STRING: 'LineString',
  4747. LINEAR_RING: 'LinearRing',
  4748. POLYGON: 'Polygon',
  4749. MULTI_POINT: 'MultiPoint',
  4750. MULTI_LINE_STRING: 'MultiLineString',
  4751. MULTI_POLYGON: 'MultiPolygon',
  4752. GEOMETRY_COLLECTION: 'GeometryCollection',
  4753. CIRCLE: 'Circle'
  4754. };
  4755. /**
  4756. * @typedef {Object} Options
  4757. * @property {boolean} [splitCollection=false] Whether to split GeometryCollections into
  4758. * multiple features on reading.
  4759. */
  4760. /**
  4761. * @typedef {Object} Token
  4762. * @property {number} type
  4763. * @property {number|string} [value]
  4764. * @property {number} position
  4765. */
  4766. /**
  4767. * @const
  4768. * @type {string}
  4769. */
  4770. const EMPTY = 'EMPTY';
  4771. /**
  4772. * @const
  4773. * @type {string}
  4774. */
  4775. const Z = 'Z';
  4776. /**
  4777. * @const
  4778. * @type {string}
  4779. */
  4780. const M = 'M';
  4781. /**
  4782. * @const
  4783. * @type {string}
  4784. */
  4785. const ZM = 'ZM';
  4786. /**
  4787. * @const
  4788. * @enum {number}
  4789. */
  4790. const TokenType = {
  4791. TEXT: 1,
  4792. LEFT_PAREN: 2,
  4793. RIGHT_PAREN: 3,
  4794. NUMBER: 4,
  4795. COMMA: 5,
  4796. EOF: 6
  4797. };
  4798. /**
  4799. * @const
  4800. * @type {Object<string, string>}
  4801. */
  4802. const WKTGeometryType = {};
  4803. for (const type in GeometryType) WKTGeometryType[type] = GeometryType[type].toUpperCase();
  4804. /**
  4805. * Class to tokenize a WKT string.
  4806. */
  4807. class Lexer {
  4808. /**
  4809. * @param {string} wkt WKT string.
  4810. */
  4811. constructor(wkt) {
  4812. /**
  4813. * @type {string}
  4814. */
  4815. this.wkt = wkt;
  4816. /**
  4817. * @type {number}
  4818. * @private
  4819. */
  4820. this.index_ = -1;
  4821. }
  4822. /**
  4823. * @param {string} c Character.
  4824. * @return {boolean} Whether the character is alphabetic.
  4825. * @private
  4826. */
  4827. isAlpha_(c) {
  4828. return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
  4829. }
  4830. /**
  4831. * @param {string} c Character.
  4832. * @param {boolean=} opt_decimal Whether the string number
  4833. * contains a dot, i.e. is a decimal number.
  4834. * @return {boolean} Whether the character is numeric.
  4835. * @private
  4836. */
  4837. isNumeric_(c, opt_decimal) {
  4838. const decimal = opt_decimal !== undefined ? opt_decimal : false;
  4839. return c >= '0' && c <= '9' || c == '.' && !decimal;
  4840. }
  4841. /**
  4842. * @param {string} c Character.
  4843. * @return {boolean} Whether the character is whitespace.
  4844. * @private
  4845. */
  4846. isWhiteSpace_(c) {
  4847. return c == ' ' || c == '\t' || c == '\r' || c == '\n';
  4848. }
  4849. /**
  4850. * @return {string} Next string character.
  4851. * @private
  4852. */
  4853. nextChar_() {
  4854. return this.wkt.charAt(++this.index_);
  4855. }
  4856. /**
  4857. * Fetch and return the next token.
  4858. * @return {!Token} Next string token.
  4859. */
  4860. nextToken() {
  4861. const c = this.nextChar_();
  4862. const position = this.index_;
  4863. /** @type {number|string} */
  4864. let value = c;
  4865. let type;
  4866. if (c == '(') {
  4867. type = TokenType.LEFT_PAREN;
  4868. } else if (c == ',') {
  4869. type = TokenType.COMMA;
  4870. } else if (c == ')') {
  4871. type = TokenType.RIGHT_PAREN;
  4872. } else if (this.isNumeric_(c) || c == '-') {
  4873. type = TokenType.NUMBER;
  4874. value = this.readNumber_();
  4875. } else if (this.isAlpha_(c)) {
  4876. type = TokenType.TEXT;
  4877. value = this.readText_();
  4878. } else if (this.isWhiteSpace_(c)) {
  4879. return this.nextToken();
  4880. } else if (c === '') {
  4881. type = TokenType.EOF;
  4882. } else {
  4883. throw new Error('Unexpected character: ' + c);
  4884. }
  4885. return {
  4886. position: position,
  4887. value: value,
  4888. type: type
  4889. };
  4890. }
  4891. /**
  4892. * @return {number} Numeric token value.
  4893. * @private
  4894. */
  4895. readNumber_() {
  4896. let c;
  4897. const index = this.index_;
  4898. let decimal = false;
  4899. let scientificNotation = false;
  4900. do {
  4901. if (c == '.') decimal = true;else if (c == 'e' || c == 'E') scientificNotation = true;
  4902. c = this.nextChar_();
  4903. } while (this.isNumeric_(c, decimal) || // if we haven't detected a scientific number before, 'e' or 'E'
  4904. // hint that we should continue to read
  4905. !scientificNotation && (c == 'e' || c == 'E') || // once we know that we have a scientific number, both '-' and '+'
  4906. // are allowed
  4907. scientificNotation && (c == '-' || c == '+'));
  4908. return parseFloat(this.wkt.substring(index, this.index_--));
  4909. }
  4910. /**
  4911. * @return {string} String token value.
  4912. * @private
  4913. */
  4914. readText_() {
  4915. let c;
  4916. const index = this.index_;
  4917. do c = this.nextChar_(); while (this.isAlpha_(c));
  4918. return this.wkt.substring(index, this.index_--).toUpperCase();
  4919. }
  4920. }
  4921. /**
  4922. * Class to parse the tokens from the WKT string.
  4923. */
  4924. class Parser {
  4925. /**
  4926. * @param {Lexer} lexer The lexer.
  4927. */
  4928. constructor(lexer, factory) {
  4929. /**
  4930. * @type {Lexer}
  4931. * @private
  4932. */
  4933. this.lexer_ = lexer;
  4934. /**
  4935. * @type {Token}
  4936. * @private
  4937. */
  4938. this.token_;
  4939. /**
  4940. * @type {import("../geom/GeometryLayout.js").default}
  4941. * @private
  4942. */
  4943. this.layout_ = GeometryLayout.XY;
  4944. this.factory = factory;
  4945. }
  4946. /**
  4947. * Fetch the next token form the lexer and replace the active token.
  4948. * @private
  4949. */
  4950. consume_() {
  4951. this.token_ = this.lexer_.nextToken();
  4952. }
  4953. /**
  4954. * Tests if the given type matches the type of the current token.
  4955. * @param {TokenType} type Token type.
  4956. * @return {boolean} Whether the token matches the given type.
  4957. */
  4958. isTokenType(type) {
  4959. const isMatch = this.token_.type == type;
  4960. return isMatch;
  4961. }
  4962. /**
  4963. * If the given type matches the current token, consume it.
  4964. * @param {TokenType} type Token type.
  4965. * @return {boolean} Whether the token matches the given type.
  4966. */
  4967. match(type) {
  4968. const isMatch = this.isTokenType(type);
  4969. if (isMatch) this.consume_();
  4970. return isMatch;
  4971. }
  4972. /**
  4973. * Try to parse the tokens provided by the lexer.
  4974. * @return {import("../geom/Geometry.js").default} The geometry.
  4975. */
  4976. parse() {
  4977. this.consume_();
  4978. const geometry = this.parseGeometry_();
  4979. return geometry;
  4980. }
  4981. /**
  4982. * Try to parse the dimensional info.
  4983. * @return {import("../geom/GeometryLayout.js").default} The layout.
  4984. * @private
  4985. */
  4986. parseGeometryLayout_() {
  4987. let layout = GeometryLayout.XY;
  4988. const dimToken = this.token_;
  4989. if (this.isTokenType(TokenType.TEXT)) {
  4990. const dimInfo = dimToken.value;
  4991. if (dimInfo === Z) layout = GeometryLayout.XYZ;else if (dimInfo === M) layout = GeometryLayout.XYM;else if (dimInfo === ZM) layout = GeometryLayout.XYZM;
  4992. if (layout !== GeometryLayout.XY) this.consume_();
  4993. }
  4994. return layout;
  4995. }
  4996. /**
  4997. * @return {!Array<import("../geom/Geometry.js").default>} A collection of geometries.
  4998. * @private
  4999. */
  5000. parseGeometryCollectionText_() {
  5001. if (this.match(TokenType.LEFT_PAREN)) {
  5002. const geometries = [];
  5003. do geometries.push(this.parseGeometry_()); while (this.match(TokenType.COMMA));
  5004. if (this.match(TokenType.RIGHT_PAREN)) return geometries;
  5005. } else if (this.isEmptyGeometry_()) {
  5006. return [];
  5007. }
  5008. throw new Error(this.formatErrorMessage_());
  5009. }
  5010. /**
  5011. * @return {Array<number>} All values in a point.
  5012. * @private
  5013. */
  5014. parsePointText_() {
  5015. if (this.match(TokenType.LEFT_PAREN)) {
  5016. const coordinates = this.parsePoint_();
  5017. if (this.match(TokenType.RIGHT_PAREN)) return coordinates;
  5018. } else if (this.isEmptyGeometry_()) {
  5019. return null;
  5020. }
  5021. throw new Error(this.formatErrorMessage_());
  5022. }
  5023. /**
  5024. * @return {!Array<!Array<number>>} All points in a linestring.
  5025. * @private
  5026. */
  5027. parseLineStringText_() {
  5028. if (this.match(TokenType.LEFT_PAREN)) {
  5029. const coordinates = this.parsePointList_();
  5030. if (this.match(TokenType.RIGHT_PAREN)) return coordinates;
  5031. } else if (this.isEmptyGeometry_()) {
  5032. return [];
  5033. }
  5034. throw new Error(this.formatErrorMessage_());
  5035. }
  5036. /**
  5037. * @return {!Array<!Array<!Array<number>>>} All points in a polygon.
  5038. * @private
  5039. */
  5040. parsePolygonText_() {
  5041. if (this.match(TokenType.LEFT_PAREN)) {
  5042. const coordinates = this.parseLineStringTextList_();
  5043. if (this.match(TokenType.RIGHT_PAREN)) return coordinates;
  5044. } else if (this.isEmptyGeometry_()) {
  5045. return [];
  5046. }
  5047. throw new Error(this.formatErrorMessage_());
  5048. }
  5049. /**
  5050. * @return {!Array<!Array<number>>} All points in a multipoint.
  5051. * @private
  5052. */
  5053. parseMultiPointText_() {
  5054. if (this.match(TokenType.LEFT_PAREN)) {
  5055. let coordinates;
  5056. if (this.token_.type == TokenType.LEFT_PAREN) coordinates = this.parsePointTextList_();else coordinates = this.parsePointList_();
  5057. if (this.match(TokenType.RIGHT_PAREN)) return coordinates;
  5058. } else if (this.isEmptyGeometry_()) {
  5059. return [];
  5060. }
  5061. throw new Error(this.formatErrorMessage_());
  5062. }
  5063. /**
  5064. * @return {!Array<!Array<!Array<number>>>} All linestring points
  5065. * in a multilinestring.
  5066. * @private
  5067. */
  5068. parseMultiLineStringText_() {
  5069. if (this.match(TokenType.LEFT_PAREN)) {
  5070. const coordinates = this.parseLineStringTextList_();
  5071. if (this.match(TokenType.RIGHT_PAREN)) return coordinates;
  5072. } else if (this.isEmptyGeometry_()) {
  5073. return [];
  5074. }
  5075. throw new Error(this.formatErrorMessage_());
  5076. }
  5077. /**
  5078. * @return {!Array<!Array<!Array<!Array<number>>>>} All polygon points in a multipolygon.
  5079. * @private
  5080. */
  5081. parseMultiPolygonText_() {
  5082. if (this.match(TokenType.LEFT_PAREN)) {
  5083. const coordinates = this.parsePolygonTextList_();
  5084. if (this.match(TokenType.RIGHT_PAREN)) return coordinates;
  5085. } else if (this.isEmptyGeometry_()) {
  5086. return [];
  5087. }
  5088. throw new Error(this.formatErrorMessage_());
  5089. }
  5090. /**
  5091. * @return {!Array<number>} A point.
  5092. * @private
  5093. */
  5094. parsePoint_() {
  5095. const coordinates = [];
  5096. const dimensions = this.layout_.length;
  5097. for (let i = 0; i < dimensions; ++i) {
  5098. const token = this.token_;
  5099. if (this.match(TokenType.NUMBER)) coordinates.push(
  5100. /** @type {number} */
  5101. token.value);else break;
  5102. }
  5103. if (coordinates.length == dimensions) return coordinates;
  5104. throw new Error(this.formatErrorMessage_());
  5105. }
  5106. /**
  5107. * @return {!Array<!Array<number>>} An array of points.
  5108. * @private
  5109. */
  5110. parsePointList_() {
  5111. const coordinates = [this.parsePoint_()];
  5112. while (this.match(TokenType.COMMA)) coordinates.push(this.parsePoint_());
  5113. return coordinates;
  5114. }
  5115. /**
  5116. * @return {!Array<!Array<number>>} An array of points.
  5117. * @private
  5118. */
  5119. parsePointTextList_() {
  5120. const coordinates = [this.parsePointText_()];
  5121. while (this.match(TokenType.COMMA)) coordinates.push(this.parsePointText_());
  5122. return coordinates;
  5123. }
  5124. /**
  5125. * @return {!Array<!Array<!Array<number>>>} An array of points.
  5126. * @private
  5127. */
  5128. parseLineStringTextList_() {
  5129. const coordinates = [this.parseLineStringText_()];
  5130. while (this.match(TokenType.COMMA)) coordinates.push(this.parseLineStringText_());
  5131. return coordinates;
  5132. }
  5133. /**
  5134. * @return {!Array<!Array<!Array<!Array<number>>>>} An array of points.
  5135. * @private
  5136. */
  5137. parsePolygonTextList_() {
  5138. const coordinates = [this.parsePolygonText_()];
  5139. while (this.match(TokenType.COMMA)) coordinates.push(this.parsePolygonText_());
  5140. return coordinates;
  5141. }
  5142. /**
  5143. * @return {boolean} Whether the token implies an empty geometry.
  5144. * @private
  5145. */
  5146. isEmptyGeometry_() {
  5147. const isEmpty = this.isTokenType(TokenType.TEXT) && this.token_.value == EMPTY;
  5148. if (isEmpty) this.consume_();
  5149. return isEmpty;
  5150. }
  5151. /**
  5152. * Create an error message for an unexpected token error.
  5153. * @return {string} Error message.
  5154. * @private
  5155. */
  5156. formatErrorMessage_() {
  5157. return 'Unexpected `' + this.token_.value + '` at position ' + this.token_.position + ' in `' + this.lexer_.wkt + '`';
  5158. }
  5159. /**
  5160. * @return {!import("../geom/Geometry.js").default} The geometry.
  5161. * @private
  5162. */
  5163. parseGeometry_() {
  5164. const factory = this.factory;
  5165. const o2c = ordinates => new Coordinate(...ordinates);
  5166. const ca2p = coordinates => {
  5167. const rings = coordinates.map(a => factory.createLinearRing(a.map(o2c)));
  5168. if (rings.length > 1) return factory.createPolygon(rings[0], rings.slice(1));else return factory.createPolygon(rings[0]);
  5169. };
  5170. const token = this.token_;
  5171. if (this.match(TokenType.TEXT)) {
  5172. const geomType = token.value;
  5173. this.layout_ = this.parseGeometryLayout_();
  5174. if (geomType == 'GEOMETRYCOLLECTION') {
  5175. const geometries = this.parseGeometryCollectionText_();
  5176. return factory.createGeometryCollection(geometries);
  5177. } else {
  5178. switch (geomType) {
  5179. case 'POINT':
  5180. {
  5181. const ordinates = this.parsePointText_();
  5182. if (!ordinates) return factory.createPoint();
  5183. return factory.createPoint(new Coordinate(...ordinates));
  5184. }
  5185. case 'LINESTRING':
  5186. {
  5187. const coordinates = this.parseLineStringText_();
  5188. const components = coordinates.map(o2c);
  5189. return factory.createLineString(components);
  5190. }
  5191. case 'LINEARRING':
  5192. {
  5193. const coordinates = this.parseLineStringText_();
  5194. const components = coordinates.map(o2c);
  5195. return factory.createLinearRing(components);
  5196. }
  5197. case 'POLYGON':
  5198. {
  5199. const coordinates = this.parsePolygonText_();
  5200. if (!coordinates || coordinates.length === 0) return factory.createPolygon();
  5201. return ca2p(coordinates);
  5202. }
  5203. case 'MULTIPOINT':
  5204. {
  5205. const coordinates = this.parseMultiPointText_();
  5206. if (!coordinates || coordinates.length === 0) return factory.createMultiPoint();
  5207. const components = coordinates.map(o2c).map(c => factory.createPoint(c));
  5208. return factory.createMultiPoint(components);
  5209. }
  5210. case 'MULTILINESTRING':
  5211. {
  5212. const coordinates = this.parseMultiLineStringText_();
  5213. const components = coordinates.map(a => factory.createLineString(a.map(o2c)));
  5214. return factory.createMultiLineString(components);
  5215. }
  5216. case 'MULTIPOLYGON':
  5217. {
  5218. const coordinates = this.parseMultiPolygonText_();
  5219. if (!coordinates || coordinates.length === 0) return factory.createMultiPolygon();
  5220. const polygons = coordinates.map(ca2p);
  5221. return factory.createMultiPolygon(polygons);
  5222. }
  5223. default:
  5224. {
  5225. throw new Error('Invalid geometry type: ' + geomType);
  5226. }
  5227. }
  5228. }
  5229. }
  5230. throw new Error(this.formatErrorMessage_());
  5231. }
  5232. }
  5233. /**
  5234. * @param {Point} geom Point geometry.
  5235. * @return {string} Coordinates part of Point as WKT.
  5236. */
  5237. function encodePointGeometry(geom) {
  5238. if (geom.isEmpty()) return '';
  5239. const c = geom.getCoordinate();
  5240. const cs = [c.x, c.y];
  5241. if (c.z !== undefined && !Number.isNaN(c.z)) cs.push(c.z);
  5242. if (c.m !== undefined && !Number.isNaN(c.m)) cs.push(c.m);
  5243. return cs.join(' ');
  5244. }
  5245. /**
  5246. * @param {MultiPoint} geom MultiPoint geometry.
  5247. * @return {string} Coordinates part of MultiPoint as WKT.
  5248. */
  5249. function encodeMultiPointGeometry(geom) {
  5250. const array = [];
  5251. for (let i = 0, ii = geom.getNumGeometries(); i < ii; ++i) array.push('(' + encodePointGeometry(geom.getGeometryN(i)) + ')');
  5252. return array.join(', ');
  5253. }
  5254. /**
  5255. * @param {GeometryCollection} geom GeometryCollection geometry.
  5256. * @return {string} Coordinates part of GeometryCollection as WKT.
  5257. */
  5258. function encodeGeometryCollectionGeometry(geom) {
  5259. const array = [];
  5260. for (let i = 0, ii = geom.getNumGeometries(); i < ii; ++i) array.push(encode(geom.getGeometryN(i)));
  5261. return array.join(', ');
  5262. }
  5263. /**
  5264. * @param {LineString|import("../geom/LinearRing.js").default} geom LineString geometry.
  5265. * @return {string} Coordinates part of LineString as WKT.
  5266. */
  5267. function encodeLineStringGeometry(geom) {
  5268. const coordinates = geom.getCoordinates().map(c => {
  5269. const a = [c.x, c.y];
  5270. if (c.z !== undefined && !Number.isNaN(c.z)) a.push(c.z);
  5271. if (c.m !== undefined && !Number.isNaN(c.m)) a.push(c.m);
  5272. return a;
  5273. });
  5274. const array = [];
  5275. for (let i = 0, ii = coordinates.length; i < ii; ++i) array.push(coordinates[i].join(' '));
  5276. return array.join(', ');
  5277. }
  5278. /**
  5279. * @param {MultiLineString} geom MultiLineString geometry.
  5280. * @return {string} Coordinates part of MultiLineString as WKT.
  5281. */
  5282. function encodeMultiLineStringGeometry(geom) {
  5283. const array = [];
  5284. for (let i = 0, ii = geom.getNumGeometries(); i < ii; ++i) array.push('(' + encodeLineStringGeometry(geom.getGeometryN(i)) + ')');
  5285. return array.join(', ');
  5286. }
  5287. /**
  5288. * @param {Polygon} geom Polygon geometry.
  5289. * @return {string} Coordinates part of Polygon as WKT.
  5290. */
  5291. function encodePolygonGeometry(geom) {
  5292. const array = [];
  5293. array.push('(' + encodeLineStringGeometry(geom.getExteriorRing()) + ')');
  5294. for (let i = 0, ii = geom.getNumInteriorRing(); i < ii; ++i) array.push('(' + encodeLineStringGeometry(geom.getInteriorRingN(i)) + ')');
  5295. return array.join(', ');
  5296. }
  5297. /**
  5298. * @param {MultiPolygon} geom MultiPolygon geometry.
  5299. * @return {string} Coordinates part of MultiPolygon as WKT.
  5300. */
  5301. function encodeMultiPolygonGeometry(geom) {
  5302. const array = [];
  5303. for (let i = 0, ii = geom.getNumGeometries(); i < ii; ++i) array.push('(' + encodePolygonGeometry(geom.getGeometryN(i)) + ')');
  5304. return array.join(', ');
  5305. }
  5306. /**
  5307. * @param {Geometry} geom Geometry geometry.
  5308. * @return {string} Potential dimensional information for WKT type.
  5309. */
  5310. function encodeGeometryLayout(geom) {
  5311. let dimInfo = '';
  5312. if (geom.isEmpty()) return dimInfo;
  5313. const c = geom.getCoordinate();
  5314. if (c.z !== undefined && !Number.isNaN(c.z)) dimInfo += Z;
  5315. if (c.m !== undefined && !Number.isNaN(c.m)) dimInfo += M;
  5316. return dimInfo;
  5317. }
  5318. /**
  5319. * @const
  5320. * @type {Object<string, function(import("../geom/Geometry.js").default): string>}
  5321. */
  5322. const GeometryEncoder = {
  5323. 'Point': encodePointGeometry,
  5324. 'LineString': encodeLineStringGeometry,
  5325. 'LinearRing': encodeLineStringGeometry,
  5326. 'Polygon': encodePolygonGeometry,
  5327. 'MultiPoint': encodeMultiPointGeometry,
  5328. 'MultiLineString': encodeMultiLineStringGeometry,
  5329. 'MultiPolygon': encodeMultiPolygonGeometry,
  5330. 'GeometryCollection': encodeGeometryCollectionGeometry
  5331. };
  5332. /**
  5333. * Encode a geometry as WKT.
  5334. * @param {!import("../geom/Geometry.js").default} geom The geometry to encode.
  5335. * @return {string} WKT string for the geometry.
  5336. */
  5337. function encode(geom) {
  5338. let type = geom.getGeometryType();
  5339. const geometryEncoder = GeometryEncoder[type];
  5340. type = type.toUpperCase();
  5341. const dimInfo = encodeGeometryLayout(geom);
  5342. if (dimInfo.length > 0) type += ' ' + dimInfo;
  5343. if (geom.isEmpty()) return type + ' ' + EMPTY;
  5344. const enc = geometryEncoder(geom);
  5345. return type + ' (' + enc + ')';
  5346. }
  5347. /**
  5348. * Class for reading and writing Well-Known Text.
  5349. *
  5350. * NOTE: Adapted from OpenLayers.
  5351. */
  5352. class WKTParser {
  5353. /** Create a new parser for WKT
  5354. *
  5355. * @param {GeometryFactory} geometryFactory
  5356. * @return An instance of WKTParser.
  5357. * @private
  5358. */
  5359. constructor(geometryFactory) {
  5360. this.geometryFactory = geometryFactory || new GeometryFactory();
  5361. this.precisionModel = this.geometryFactory.getPrecisionModel();
  5362. }
  5363. /**
  5364. * Deserialize a WKT string and return a geometry. Supports WKT for POINT,
  5365. * MULTIPOINT, LINESTRING, LINEARRING, MULTILINESTRING, POLYGON, MULTIPOLYGON,
  5366. * and GEOMETRYCOLLECTION.
  5367. *
  5368. * @param {String} wkt A WKT string.
  5369. * @return {Geometry} A geometry instance.
  5370. * @private
  5371. */
  5372. read(wkt) {
  5373. const lexer = new Lexer(wkt);
  5374. const parser = new Parser(lexer, this.geometryFactory);
  5375. const geometry = parser.parse();
  5376. return geometry;
  5377. }
  5378. /**
  5379. * Serialize a geometry into a WKT string.
  5380. *
  5381. * @param {Geometry} geometry A feature or array of features.
  5382. * @return {String} The WKT string representation of the input geometries.
  5383. * @private
  5384. */
  5385. write(geometry) {
  5386. return encode(geometry);
  5387. }
  5388. }
  5389. /**
  5390. * @module org/locationtech/jts/io/WKTWriter
  5391. */
  5392. /**
  5393. * Writes the Well-Known Text representation of a {@link Geometry}. The
  5394. * Well-Known Text format is defined in the <A
  5395. * HREF="http://www.opengis.org/techno/specs.htm"> OGC Simple Features
  5396. * Specification for SQL</A>.
  5397. * <p>
  5398. * The <code>WKTWriter</code> outputs coordinates rounded to the precision
  5399. * model. Only the maximum number of decimal places necessary to represent the
  5400. * ordinates to the required precision will be output.
  5401. * <p>
  5402. * The SFS WKT spec does not define a special tag for {@link LinearRing}s.
  5403. * Under the spec, rings are output as <code>LINESTRING</code>s.
  5404. */
  5405. class WKTWriter {
  5406. /**
  5407. * @param {GeometryFactory} geometryFactory
  5408. */
  5409. constructor(geometryFactory) {
  5410. this.parser = new WKTParser(geometryFactory);
  5411. }
  5412. /**
  5413. * Converts a <code>Geometry</code> to its Well-known Text representation.
  5414. *
  5415. * @param {Geometry} geometry a <code>Geometry</code> to process.
  5416. * @return {string} a <Geometry Tagged Text> string (see the OpenGIS Simple
  5417. * Features Specification).
  5418. * @memberof module:org/locationtech/jts/io/WKTWriter#
  5419. */
  5420. write(geometry) {
  5421. return this.parser.write(geometry);
  5422. }
  5423. /**
  5424. * Generates the WKT for a <tt>LINESTRING</tt> specified by two
  5425. * {@link Coordinate}s.
  5426. *
  5427. * @param p0 the first coordinate.
  5428. * @param p1 the second coordinate.
  5429. *
  5430. * @return the WKT.
  5431. * @private
  5432. */
  5433. static toLineString(p0, p1) {
  5434. if (arguments.length !== 2) throw new Error('Not implemented');
  5435. return 'LINESTRING ( ' + p0.x + ' ' + p0.y + ', ' + p1.x + ' ' + p1.y + ' )';
  5436. }
  5437. }
  5438. class LineIntersector {
  5439. constructor() {
  5440. LineIntersector.constructor_.apply(this, arguments);
  5441. }
  5442. static constructor_() {
  5443. this._result = null;
  5444. this._inputLines = Array(2).fill().map(() => Array(2));
  5445. this._intPt = new Array(2).fill(null);
  5446. this._intLineIndex = null;
  5447. this._isProper = null;
  5448. this._pa = null;
  5449. this._pb = null;
  5450. this._precisionModel = null;
  5451. this._intPt[0] = new Coordinate();
  5452. this._intPt[1] = new Coordinate();
  5453. this._pa = this._intPt[0];
  5454. this._pb = this._intPt[1];
  5455. this._result = 0;
  5456. }
  5457. static computeEdgeDistance(p, p0, p1) {
  5458. const dx = Math.abs(p1.x - p0.x);
  5459. const dy = Math.abs(p1.y - p0.y);
  5460. let dist = -1.0;
  5461. if (p.equals(p0)) {
  5462. dist = 0.0;
  5463. } else if (p.equals(p1)) {
  5464. if (dx > dy) dist = dx;else dist = dy;
  5465. } else {
  5466. const pdx = Math.abs(p.x - p0.x);
  5467. const pdy = Math.abs(p.y - p0.y);
  5468. if (dx > dy) dist = pdx;else dist = pdy;
  5469. if (dist === 0.0 && !p.equals(p0)) dist = Math.max(pdx, pdy);
  5470. }
  5471. Assert.isTrue(!(dist === 0.0 && !p.equals(p0)), 'Bad distance calculation');
  5472. return dist;
  5473. }
  5474. static nonRobustComputeEdgeDistance(p, p1, p2) {
  5475. const dx = p.x - p1.x;
  5476. const dy = p.y - p1.y;
  5477. const dist = Math.sqrt(dx * dx + dy * dy);
  5478. Assert.isTrue(!(dist === 0.0 && !p.equals(p1)), 'Invalid distance calculation');
  5479. return dist;
  5480. }
  5481. getIndexAlongSegment(segmentIndex, intIndex) {
  5482. this.computeIntLineIndex();
  5483. return this._intLineIndex[segmentIndex][intIndex];
  5484. }
  5485. getTopologySummary() {
  5486. const catBuilder = new StringBuilder();
  5487. if (this.isEndPoint()) catBuilder.append(' endpoint');
  5488. if (this._isProper) catBuilder.append(' proper');
  5489. if (this.isCollinear()) catBuilder.append(' collinear');
  5490. return catBuilder.toString();
  5491. }
  5492. computeIntersection(p1, p2, p3, p4) {
  5493. this._inputLines[0][0] = p1;
  5494. this._inputLines[0][1] = p2;
  5495. this._inputLines[1][0] = p3;
  5496. this._inputLines[1][1] = p4;
  5497. this._result = this.computeIntersect(p1, p2, p3, p4);
  5498. }
  5499. getIntersectionNum() {
  5500. return this._result;
  5501. }
  5502. computeIntLineIndex() {
  5503. if (arguments.length === 0) {
  5504. if (this._intLineIndex === null) {
  5505. this._intLineIndex = Array(2).fill().map(() => Array(2));
  5506. this.computeIntLineIndex(0);
  5507. this.computeIntLineIndex(1);
  5508. }
  5509. } else if (arguments.length === 1) {
  5510. const segmentIndex = arguments[0];
  5511. const dist0 = this.getEdgeDistance(segmentIndex, 0);
  5512. const dist1 = this.getEdgeDistance(segmentIndex, 1);
  5513. if (dist0 > dist1) {
  5514. this._intLineIndex[segmentIndex][0] = 0;
  5515. this._intLineIndex[segmentIndex][1] = 1;
  5516. } else {
  5517. this._intLineIndex[segmentIndex][0] = 1;
  5518. this._intLineIndex[segmentIndex][1] = 0;
  5519. }
  5520. }
  5521. }
  5522. isProper() {
  5523. return this.hasIntersection() && this._isProper;
  5524. }
  5525. setPrecisionModel(precisionModel) {
  5526. this._precisionModel = precisionModel;
  5527. }
  5528. isInteriorIntersection() {
  5529. if (arguments.length === 0) {
  5530. if (this.isInteriorIntersection(0)) return true;
  5531. if (this.isInteriorIntersection(1)) return true;
  5532. return false;
  5533. } else if (arguments.length === 1) {
  5534. const inputLineIndex = arguments[0];
  5535. for (let i = 0; i < this._result; i++) if (!(this._intPt[i].equals2D(this._inputLines[inputLineIndex][0]) || this._intPt[i].equals2D(this._inputLines[inputLineIndex][1]))) return true;
  5536. return false;
  5537. }
  5538. }
  5539. getIntersection(intIndex) {
  5540. return this._intPt[intIndex];
  5541. }
  5542. isEndPoint() {
  5543. return this.hasIntersection() && !this._isProper;
  5544. }
  5545. hasIntersection() {
  5546. return this._result !== LineIntersector.NO_INTERSECTION;
  5547. }
  5548. getEdgeDistance(segmentIndex, intIndex) {
  5549. const dist = LineIntersector.computeEdgeDistance(this._intPt[intIndex], this._inputLines[segmentIndex][0], this._inputLines[segmentIndex][1]);
  5550. return dist;
  5551. }
  5552. isCollinear() {
  5553. return this._result === LineIntersector.COLLINEAR_INTERSECTION;
  5554. }
  5555. toString() {
  5556. return WKTWriter.toLineString(this._inputLines[0][0], this._inputLines[0][1]) + ' - ' + WKTWriter.toLineString(this._inputLines[1][0], this._inputLines[1][1]) + this.getTopologySummary();
  5557. }
  5558. getEndpoint(segmentIndex, ptIndex) {
  5559. return this._inputLines[segmentIndex][ptIndex];
  5560. }
  5561. isIntersection(pt) {
  5562. for (let i = 0; i < this._result; i++) if (this._intPt[i].equals2D(pt)) return true;
  5563. return false;
  5564. }
  5565. getIntersectionAlongSegment(segmentIndex, intIndex) {
  5566. this.computeIntLineIndex();
  5567. return this._intPt[this._intLineIndex[segmentIndex][intIndex]];
  5568. }
  5569. }
  5570. LineIntersector.DONT_INTERSECT = 0;
  5571. LineIntersector.DO_INTERSECT = 1;
  5572. LineIntersector.COLLINEAR = 2;
  5573. LineIntersector.NO_INTERSECTION = 0;
  5574. LineIntersector.POINT_INTERSECTION = 1;
  5575. LineIntersector.COLLINEAR_INTERSECTION = 2;
  5576. class RobustLineIntersector extends LineIntersector {
  5577. constructor() {
  5578. super();
  5579. }
  5580. static nearestEndpoint(p1, p2, q1, q2) {
  5581. let nearestPt = p1;
  5582. let minDist = Distance.pointToSegment(p1, q1, q2);
  5583. let dist = Distance.pointToSegment(p2, q1, q2);
  5584. if (dist < minDist) {
  5585. minDist = dist;
  5586. nearestPt = p2;
  5587. }
  5588. dist = Distance.pointToSegment(q1, p1, p2);
  5589. if (dist < minDist) {
  5590. minDist = dist;
  5591. nearestPt = q1;
  5592. }
  5593. dist = Distance.pointToSegment(q2, p1, p2);
  5594. if (dist < minDist) {
  5595. minDist = dist;
  5596. nearestPt = q2;
  5597. }
  5598. return nearestPt;
  5599. }
  5600. isInSegmentEnvelopes(intPt) {
  5601. const env0 = new Envelope(this._inputLines[0][0], this._inputLines[0][1]);
  5602. const env1 = new Envelope(this._inputLines[1][0], this._inputLines[1][1]);
  5603. return env0.contains(intPt) && env1.contains(intPt);
  5604. }
  5605. computeIntersection() {
  5606. if (arguments.length === 3) {
  5607. const p = arguments[0],
  5608. p1 = arguments[1],
  5609. p2 = arguments[2];
  5610. this._isProper = false;
  5611. if (Envelope.intersects(p1, p2, p)) if (Orientation.index(p1, p2, p) === 0 && Orientation.index(p2, p1, p) === 0) {
  5612. this._isProper = true;
  5613. if (p.equals(p1) || p.equals(p2)) this._isProper = false;
  5614. this._result = LineIntersector.POINT_INTERSECTION;
  5615. return null;
  5616. }
  5617. this._result = LineIntersector.NO_INTERSECTION;
  5618. } else {
  5619. return super.computeIntersection.apply(this, arguments);
  5620. }
  5621. }
  5622. intersection(p1, p2, q1, q2) {
  5623. let intPt = this.intersectionSafe(p1, p2, q1, q2);
  5624. if (!this.isInSegmentEnvelopes(intPt)) intPt = new Coordinate(RobustLineIntersector.nearestEndpoint(p1, p2, q1, q2));
  5625. if (this._precisionModel !== null) this._precisionModel.makePrecise(intPt);
  5626. return intPt;
  5627. }
  5628. checkDD(p1, p2, q1, q2, intPt) {
  5629. const intPtDD = CGAlgorithmsDD.intersection(p1, p2, q1, q2);
  5630. const isIn = this.isInSegmentEnvelopes(intPtDD);
  5631. System.out.println('DD in env = ' + isIn + ' --------------------- ' + intPtDD);
  5632. if (intPt.distance(intPtDD) > 0.0001) System.out.println('Distance = ' + intPt.distance(intPtDD));
  5633. }
  5634. intersectionSafe(p1, p2, q1, q2) {
  5635. let intPt = Intersection.intersection(p1, p2, q1, q2);
  5636. if (intPt === null) intPt = RobustLineIntersector.nearestEndpoint(p1, p2, q1, q2);
  5637. return intPt;
  5638. }
  5639. computeCollinearIntersection(p1, p2, q1, q2) {
  5640. const p1q1p2 = Envelope.intersects(p1, p2, q1);
  5641. const p1q2p2 = Envelope.intersects(p1, p2, q2);
  5642. const q1p1q2 = Envelope.intersects(q1, q2, p1);
  5643. const q1p2q2 = Envelope.intersects(q1, q2, p2);
  5644. if (p1q1p2 && p1q2p2) {
  5645. this._intPt[0] = q1;
  5646. this._intPt[1] = q2;
  5647. return LineIntersector.COLLINEAR_INTERSECTION;
  5648. }
  5649. if (q1p1q2 && q1p2q2) {
  5650. this._intPt[0] = p1;
  5651. this._intPt[1] = p2;
  5652. return LineIntersector.COLLINEAR_INTERSECTION;
  5653. }
  5654. if (p1q1p2 && q1p1q2) {
  5655. this._intPt[0] = q1;
  5656. this._intPt[1] = p1;
  5657. return q1.equals(p1) && !p1q2p2 && !q1p2q2 ? LineIntersector.POINT_INTERSECTION : LineIntersector.COLLINEAR_INTERSECTION;
  5658. }
  5659. if (p1q1p2 && q1p2q2) {
  5660. this._intPt[0] = q1;
  5661. this._intPt[1] = p2;
  5662. return q1.equals(p2) && !p1q2p2 && !q1p1q2 ? LineIntersector.POINT_INTERSECTION : LineIntersector.COLLINEAR_INTERSECTION;
  5663. }
  5664. if (p1q2p2 && q1p1q2) {
  5665. this._intPt[0] = q2;
  5666. this._intPt[1] = p1;
  5667. return q2.equals(p1) && !p1q1p2 && !q1p2q2 ? LineIntersector.POINT_INTERSECTION : LineIntersector.COLLINEAR_INTERSECTION;
  5668. }
  5669. if (p1q2p2 && q1p2q2) {
  5670. this._intPt[0] = q2;
  5671. this._intPt[1] = p2;
  5672. return q2.equals(p2) && !p1q1p2 && !q1p1q2 ? LineIntersector.POINT_INTERSECTION : LineIntersector.COLLINEAR_INTERSECTION;
  5673. }
  5674. return LineIntersector.NO_INTERSECTION;
  5675. }
  5676. computeIntersect(p1, p2, q1, q2) {
  5677. this._isProper = false;
  5678. if (!Envelope.intersects(p1, p2, q1, q2)) return LineIntersector.NO_INTERSECTION;
  5679. const Pq1 = Orientation.index(p1, p2, q1);
  5680. const Pq2 = Orientation.index(p1, p2, q2);
  5681. if (Pq1 > 0 && Pq2 > 0 || Pq1 < 0 && Pq2 < 0) return LineIntersector.NO_INTERSECTION;
  5682. const Qp1 = Orientation.index(q1, q2, p1);
  5683. const Qp2 = Orientation.index(q1, q2, p2);
  5684. if (Qp1 > 0 && Qp2 > 0 || Qp1 < 0 && Qp2 < 0) return LineIntersector.NO_INTERSECTION;
  5685. const collinear = Pq1 === 0 && Pq2 === 0 && Qp1 === 0 && Qp2 === 0;
  5686. if (collinear) return this.computeCollinearIntersection(p1, p2, q1, q2);
  5687. if (Pq1 === 0 || Pq2 === 0 || Qp1 === 0 || Qp2 === 0) {
  5688. this._isProper = false;
  5689. if (p1.equals2D(q1) || p1.equals2D(q2)) this._intPt[0] = p1;else if (p2.equals2D(q1) || p2.equals2D(q2)) this._intPt[0] = p2;else if (Pq1 === 0) this._intPt[0] = new Coordinate(q1);else if (Pq2 === 0) this._intPt[0] = new Coordinate(q2);else if (Qp1 === 0) this._intPt[0] = new Coordinate(p1);else if (Qp2 === 0) this._intPt[0] = new Coordinate(p2);
  5690. } else {
  5691. this._isProper = true;
  5692. this._intPt[0] = this.intersection(p1, p2, q1, q2);
  5693. }
  5694. return LineIntersector.POINT_INTERSECTION;
  5695. }
  5696. }
  5697. class LineSegment {
  5698. constructor() {
  5699. LineSegment.constructor_.apply(this, arguments);
  5700. }
  5701. static constructor_() {
  5702. this.p0 = null;
  5703. this.p1 = null;
  5704. if (arguments.length === 0) {
  5705. LineSegment.constructor_.call(this, new Coordinate(), new Coordinate());
  5706. } else if (arguments.length === 1) {
  5707. const ls = arguments[0];
  5708. LineSegment.constructor_.call(this, ls.p0, ls.p1);
  5709. } else if (arguments.length === 2) {
  5710. const p0 = arguments[0],
  5711. p1 = arguments[1];
  5712. this.p0 = p0;
  5713. this.p1 = p1;
  5714. } else if (arguments.length === 4) {
  5715. const x0 = arguments[0],
  5716. y0 = arguments[1],
  5717. x1 = arguments[2],
  5718. y1 = arguments[3];
  5719. LineSegment.constructor_.call(this, new Coordinate(x0, y0), new Coordinate(x1, y1));
  5720. }
  5721. }
  5722. static midPoint(p0, p1) {
  5723. return new Coordinate((p0.x + p1.x) / 2, (p0.y + p1.y) / 2);
  5724. }
  5725. minX() {
  5726. return Math.min(this.p0.x, this.p1.x);
  5727. }
  5728. orientationIndex() {
  5729. if (arguments[0] instanceof LineSegment) {
  5730. const seg = arguments[0];
  5731. const orient0 = Orientation.index(this.p0, this.p1, seg.p0);
  5732. const orient1 = Orientation.index(this.p0, this.p1, seg.p1);
  5733. if (orient0 >= 0 && orient1 >= 0) return Math.max(orient0, orient1);
  5734. if (orient0 <= 0 && orient1 <= 0) return Math.max(orient0, orient1);
  5735. return 0;
  5736. } else if (arguments[0] instanceof Coordinate) {
  5737. const p = arguments[0];
  5738. return Orientation.index(this.p0, this.p1, p);
  5739. }
  5740. }
  5741. toGeometry(geomFactory) {
  5742. return geomFactory.createLineString([this.p0, this.p1]);
  5743. }
  5744. isVertical() {
  5745. return this.p0.x === this.p1.x;
  5746. }
  5747. equals(o) {
  5748. if (!(o instanceof LineSegment)) return false;
  5749. const other = o;
  5750. return this.p0.equals(other.p0) && this.p1.equals(other.p1);
  5751. }
  5752. intersection(line) {
  5753. const li = new RobustLineIntersector();
  5754. li.computeIntersection(this.p0, this.p1, line.p0, line.p1);
  5755. if (li.hasIntersection()) return li.getIntersection(0);
  5756. return null;
  5757. }
  5758. project() {
  5759. if (arguments[0] instanceof Coordinate) {
  5760. const p = arguments[0];
  5761. if (p.equals(this.p0) || p.equals(this.p1)) return new Coordinate(p);
  5762. const r = this.projectionFactor(p);
  5763. const coord = new Coordinate();
  5764. coord.x = this.p0.x + r * (this.p1.x - this.p0.x);
  5765. coord.y = this.p0.y + r * (this.p1.y - this.p0.y);
  5766. return coord;
  5767. } else if (arguments[0] instanceof LineSegment) {
  5768. const seg = arguments[0];
  5769. const pf0 = this.projectionFactor(seg.p0);
  5770. const pf1 = this.projectionFactor(seg.p1);
  5771. if (pf0 >= 1.0 && pf1 >= 1.0) return null;
  5772. if (pf0 <= 0.0 && pf1 <= 0.0) return null;
  5773. let newp0 = this.project(seg.p0);
  5774. if (pf0 < 0.0) newp0 = this.p0;
  5775. if (pf0 > 1.0) newp0 = this.p1;
  5776. let newp1 = this.project(seg.p1);
  5777. if (pf1 < 0.0) newp1 = this.p0;
  5778. if (pf1 > 1.0) newp1 = this.p1;
  5779. return new LineSegment(newp0, newp1);
  5780. }
  5781. }
  5782. normalize() {
  5783. if (this.p1.compareTo(this.p0) < 0) this.reverse();
  5784. }
  5785. angle() {
  5786. return Math.atan2(this.p1.y - this.p0.y, this.p1.x - this.p0.x);
  5787. }
  5788. getCoordinate(i) {
  5789. if (i === 0) return this.p0;
  5790. return this.p1;
  5791. }
  5792. distancePerpendicular(p) {
  5793. return Distance.pointToLinePerpendicular(p, this.p0, this.p1);
  5794. }
  5795. minY() {
  5796. return Math.min(this.p0.y, this.p1.y);
  5797. }
  5798. midPoint() {
  5799. return LineSegment.midPoint(this.p0, this.p1);
  5800. }
  5801. projectionFactor(p) {
  5802. if (p.equals(this.p0)) return 0.0;
  5803. if (p.equals(this.p1)) return 1.0;
  5804. const dx = this.p1.x - this.p0.x;
  5805. const dy = this.p1.y - this.p0.y;
  5806. const len = dx * dx + dy * dy;
  5807. if (len <= 0.0) return Double.NaN;
  5808. const r = ((p.x - this.p0.x) * dx + (p.y - this.p0.y) * dy) / len;
  5809. return r;
  5810. }
  5811. closestPoints(line) {
  5812. const intPt = this.intersection(line);
  5813. if (intPt !== null) return [intPt, intPt];
  5814. const closestPt = new Array(2).fill(null);
  5815. let minDistance = Double.MAX_VALUE;
  5816. let dist = null;
  5817. const close00 = this.closestPoint(line.p0);
  5818. minDistance = close00.distance(line.p0);
  5819. closestPt[0] = close00;
  5820. closestPt[1] = line.p0;
  5821. const close01 = this.closestPoint(line.p1);
  5822. dist = close01.distance(line.p1);
  5823. if (dist < minDistance) {
  5824. minDistance = dist;
  5825. closestPt[0] = close01;
  5826. closestPt[1] = line.p1;
  5827. }
  5828. const close10 = line.closestPoint(this.p0);
  5829. dist = close10.distance(this.p0);
  5830. if (dist < minDistance) {
  5831. minDistance = dist;
  5832. closestPt[0] = this.p0;
  5833. closestPt[1] = close10;
  5834. }
  5835. const close11 = line.closestPoint(this.p1);
  5836. dist = close11.distance(this.p1);
  5837. if (dist < minDistance) {
  5838. minDistance = dist;
  5839. closestPt[0] = this.p1;
  5840. closestPt[1] = close11;
  5841. }
  5842. return closestPt;
  5843. }
  5844. closestPoint(p) {
  5845. const factor = this.projectionFactor(p);
  5846. if (factor > 0 && factor < 1) return this.project(p);
  5847. const dist0 = this.p0.distance(p);
  5848. const dist1 = this.p1.distance(p);
  5849. if (dist0 < dist1) return this.p0;
  5850. return this.p1;
  5851. }
  5852. maxX() {
  5853. return Math.max(this.p0.x, this.p1.x);
  5854. }
  5855. getLength() {
  5856. return this.p0.distance(this.p1);
  5857. }
  5858. compareTo(o) {
  5859. const other = o;
  5860. const comp0 = this.p0.compareTo(other.p0);
  5861. if (comp0 !== 0) return comp0;
  5862. return this.p1.compareTo(other.p1);
  5863. }
  5864. reverse() {
  5865. const temp = this.p0;
  5866. this.p0 = this.p1;
  5867. this.p1 = temp;
  5868. }
  5869. equalsTopo(other) {
  5870. return this.p0.equals(other.p0) && this.p1.equals(other.p1) || this.p0.equals(other.p1) && this.p1.equals(other.p0);
  5871. }
  5872. lineIntersection(line) {
  5873. const intPt = Intersection.intersection(this.p0, this.p1, line.p0, line.p1);
  5874. return intPt;
  5875. }
  5876. maxY() {
  5877. return Math.max(this.p0.y, this.p1.y);
  5878. }
  5879. pointAlongOffset(segmentLengthFraction, offsetDistance) {
  5880. const segx = this.p0.x + segmentLengthFraction * (this.p1.x - this.p0.x);
  5881. const segy = this.p0.y + segmentLengthFraction * (this.p1.y - this.p0.y);
  5882. const dx = this.p1.x - this.p0.x;
  5883. const dy = this.p1.y - this.p0.y;
  5884. const len = Math.sqrt(dx * dx + dy * dy);
  5885. let ux = 0.0;
  5886. let uy = 0.0;
  5887. if (offsetDistance !== 0.0) {
  5888. if (len <= 0.0) throw new IllegalStateException('Cannot compute offset from zero-length line segment');
  5889. ux = offsetDistance * dx / len;
  5890. uy = offsetDistance * dy / len;
  5891. }
  5892. const offsetx = segx - uy;
  5893. const offsety = segy + ux;
  5894. const coord = new Coordinate(offsetx, offsety);
  5895. return coord;
  5896. }
  5897. setCoordinates() {
  5898. if (arguments.length === 1) {
  5899. const ls = arguments[0];
  5900. this.setCoordinates(ls.p0, ls.p1);
  5901. } else if (arguments.length === 2) {
  5902. const p0 = arguments[0],
  5903. p1 = arguments[1];
  5904. this.p0.x = p0.x;
  5905. this.p0.y = p0.y;
  5906. this.p1.x = p1.x;
  5907. this.p1.y = p1.y;
  5908. }
  5909. }
  5910. segmentFraction(inputPt) {
  5911. let segFrac = this.projectionFactor(inputPt);
  5912. if (segFrac < 0.0) segFrac = 0.0;else if (segFrac > 1.0 || Double.isNaN(segFrac)) segFrac = 1.0;
  5913. return segFrac;
  5914. }
  5915. toString() {
  5916. return 'LINESTRING( ' + this.p0.x + ' ' + this.p0.y + ', ' + this.p1.x + ' ' + this.p1.y + ')';
  5917. }
  5918. isHorizontal() {
  5919. return this.p0.y === this.p1.y;
  5920. }
  5921. reflect(p) {
  5922. const A = this.p1.getY() - this.p0.getY();
  5923. const B = this.p0.getX() - this.p1.getX();
  5924. const C = this.p0.getY() * (this.p1.getX() - this.p0.getX()) - this.p0.getX() * (this.p1.getY() - this.p0.getY());
  5925. const A2plusB2 = A * A + B * B;
  5926. const A2subB2 = A * A - B * B;
  5927. const x = p.getX();
  5928. const y = p.getY();
  5929. const rx = (-A2subB2 * x - 2 * A * B * y - 2 * A * C) / A2plusB2;
  5930. const ry = (A2subB2 * y - 2 * A * B * x - 2 * B * C) / A2plusB2;
  5931. return new Coordinate(rx, ry);
  5932. }
  5933. distance() {
  5934. if (arguments[0] instanceof LineSegment) {
  5935. const ls = arguments[0];
  5936. return Distance.segmentToSegment(this.p0, this.p1, ls.p0, ls.p1);
  5937. } else if (arguments[0] instanceof Coordinate) {
  5938. const p = arguments[0];
  5939. return Distance.pointToSegment(p, this.p0, this.p1);
  5940. }
  5941. }
  5942. pointAlong(segmentLengthFraction) {
  5943. const coord = new Coordinate();
  5944. coord.x = this.p0.x + segmentLengthFraction * (this.p1.x - this.p0.x);
  5945. coord.y = this.p0.y + segmentLengthFraction * (this.p1.y - this.p0.y);
  5946. return coord;
  5947. }
  5948. hashCode() {
  5949. let bits0 = Double.doubleToLongBits(this.p0.x);
  5950. bits0 ^= Double.doubleToLongBits(this.p0.y) * 31;
  5951. const hash0 = Math.trunc(bits0) ^ Math.trunc(bits0 >> 32);
  5952. let bits1 = Double.doubleToLongBits(this.p1.x);
  5953. bits1 ^= Double.doubleToLongBits(this.p1.y) * 31;
  5954. const hash1 = Math.trunc(bits1) ^ Math.trunc(bits1 >> 32);
  5955. return hash0 ^ hash1;
  5956. }
  5957. get interfaces_() {
  5958. return [Comparable, Serializable];
  5959. }
  5960. }
  5961. class Location {
  5962. static toLocationSymbol(locationValue) {
  5963. switch (locationValue) {
  5964. case Location.EXTERIOR:
  5965. return 'e';
  5966. case Location.BOUNDARY:
  5967. return 'b';
  5968. case Location.INTERIOR:
  5969. return 'i';
  5970. case Location.NONE:
  5971. return '-';
  5972. }
  5973. throw new IllegalArgumentException('Unknown location value: ' + locationValue);
  5974. }
  5975. }
  5976. Location.INTERIOR = 0;
  5977. Location.BOUNDARY = 1;
  5978. Location.EXTERIOR = 2;
  5979. Location.NONE = -1;
  5980. class IntersectionMatrix {
  5981. constructor() {
  5982. IntersectionMatrix.constructor_.apply(this, arguments);
  5983. }
  5984. static constructor_() {
  5985. this._matrix = null;
  5986. if (arguments.length === 0) {
  5987. this._matrix = Array(3).fill().map(() => Array(3));
  5988. this.setAll(Dimension.FALSE);
  5989. } else if (arguments.length === 1) {
  5990. if (typeof arguments[0] === 'string') {
  5991. const elements = arguments[0];
  5992. IntersectionMatrix.constructor_.call(this);
  5993. this.set(elements);
  5994. } else if (arguments[0] instanceof IntersectionMatrix) {
  5995. const other = arguments[0];
  5996. IntersectionMatrix.constructor_.call(this);
  5997. this._matrix[Location.INTERIOR][Location.INTERIOR] = other._matrix[Location.INTERIOR][Location.INTERIOR];
  5998. this._matrix[Location.INTERIOR][Location.BOUNDARY] = other._matrix[Location.INTERIOR][Location.BOUNDARY];
  5999. this._matrix[Location.INTERIOR][Location.EXTERIOR] = other._matrix[Location.INTERIOR][Location.EXTERIOR];
  6000. this._matrix[Location.BOUNDARY][Location.INTERIOR] = other._matrix[Location.BOUNDARY][Location.INTERIOR];
  6001. this._matrix[Location.BOUNDARY][Location.BOUNDARY] = other._matrix[Location.BOUNDARY][Location.BOUNDARY];
  6002. this._matrix[Location.BOUNDARY][Location.EXTERIOR] = other._matrix[Location.BOUNDARY][Location.EXTERIOR];
  6003. this._matrix[Location.EXTERIOR][Location.INTERIOR] = other._matrix[Location.EXTERIOR][Location.INTERIOR];
  6004. this._matrix[Location.EXTERIOR][Location.BOUNDARY] = other._matrix[Location.EXTERIOR][Location.BOUNDARY];
  6005. this._matrix[Location.EXTERIOR][Location.EXTERIOR] = other._matrix[Location.EXTERIOR][Location.EXTERIOR];
  6006. }
  6007. }
  6008. }
  6009. static matches() {
  6010. if (Number.isInteger(arguments[0]) && typeof arguments[1] === 'string') {
  6011. const actualDimensionValue = arguments[0],
  6012. requiredDimensionSymbol = arguments[1];
  6013. if (requiredDimensionSymbol === Dimension.SYM_DONTCARE) return true;
  6014. if (requiredDimensionSymbol === Dimension.SYM_TRUE && (actualDimensionValue >= 0 || actualDimensionValue === Dimension.TRUE)) return true;
  6015. if (requiredDimensionSymbol === Dimension.SYM_FALSE && actualDimensionValue === Dimension.FALSE) return true;
  6016. if (requiredDimensionSymbol === Dimension.SYM_P && actualDimensionValue === Dimension.P) return true;
  6017. if (requiredDimensionSymbol === Dimension.SYM_L && actualDimensionValue === Dimension.L) return true;
  6018. if (requiredDimensionSymbol === Dimension.SYM_A && actualDimensionValue === Dimension.A) return true;
  6019. return false;
  6020. } else if (typeof arguments[0] === 'string' && typeof arguments[1] === 'string') {
  6021. const actualDimensionSymbols = arguments[0],
  6022. requiredDimensionSymbols = arguments[1];
  6023. const m = new IntersectionMatrix(actualDimensionSymbols);
  6024. return m.matches(requiredDimensionSymbols);
  6025. }
  6026. }
  6027. static isTrue(actualDimensionValue) {
  6028. if (actualDimensionValue >= 0 || actualDimensionValue === Dimension.TRUE) return true;
  6029. return false;
  6030. }
  6031. isIntersects() {
  6032. return !this.isDisjoint();
  6033. }
  6034. isCovers() {
  6035. const hasPointInCommon = IntersectionMatrix.isTrue(this._matrix[Location.INTERIOR][Location.INTERIOR]) || IntersectionMatrix.isTrue(this._matrix[Location.INTERIOR][Location.BOUNDARY]) || IntersectionMatrix.isTrue(this._matrix[Location.BOUNDARY][Location.INTERIOR]) || IntersectionMatrix.isTrue(this._matrix[Location.BOUNDARY][Location.BOUNDARY]);
  6036. return hasPointInCommon && this._matrix[Location.EXTERIOR][Location.INTERIOR] === Dimension.FALSE && this._matrix[Location.EXTERIOR][Location.BOUNDARY] === Dimension.FALSE;
  6037. }
  6038. isCoveredBy() {
  6039. const hasPointInCommon = IntersectionMatrix.isTrue(this._matrix[Location.INTERIOR][Location.INTERIOR]) || IntersectionMatrix.isTrue(this._matrix[Location.INTERIOR][Location.BOUNDARY]) || IntersectionMatrix.isTrue(this._matrix[Location.BOUNDARY][Location.INTERIOR]) || IntersectionMatrix.isTrue(this._matrix[Location.BOUNDARY][Location.BOUNDARY]);
  6040. return hasPointInCommon && this._matrix[Location.INTERIOR][Location.EXTERIOR] === Dimension.FALSE && this._matrix[Location.BOUNDARY][Location.EXTERIOR] === Dimension.FALSE;
  6041. }
  6042. set() {
  6043. if (arguments.length === 1) {
  6044. const dimensionSymbols = arguments[0];
  6045. for (let i = 0; i < dimensionSymbols.length; i++) {
  6046. const row = Math.trunc(i / 3);
  6047. const col = i % 3;
  6048. this._matrix[row][col] = Dimension.toDimensionValue(dimensionSymbols.charAt(i));
  6049. }
  6050. } else if (arguments.length === 3) {
  6051. const row = arguments[0],
  6052. column = arguments[1],
  6053. dimensionValue = arguments[2];
  6054. this._matrix[row][column] = dimensionValue;
  6055. }
  6056. }
  6057. isContains() {
  6058. return IntersectionMatrix.isTrue(this._matrix[Location.INTERIOR][Location.INTERIOR]) && this._matrix[Location.EXTERIOR][Location.INTERIOR] === Dimension.FALSE && this._matrix[Location.EXTERIOR][Location.BOUNDARY] === Dimension.FALSE;
  6059. }
  6060. setAtLeast() {
  6061. if (arguments.length === 1) {
  6062. const minimumDimensionSymbols = arguments[0];
  6063. for (let i = 0; i < minimumDimensionSymbols.length; i++) {
  6064. const row = Math.trunc(i / 3);
  6065. const col = i % 3;
  6066. this.setAtLeast(row, col, Dimension.toDimensionValue(minimumDimensionSymbols.charAt(i)));
  6067. }
  6068. } else if (arguments.length === 3) {
  6069. const row = arguments[0],
  6070. column = arguments[1],
  6071. minimumDimensionValue = arguments[2];
  6072. if (this._matrix[row][column] < minimumDimensionValue) this._matrix[row][column] = minimumDimensionValue;
  6073. }
  6074. }
  6075. setAtLeastIfValid(row, column, minimumDimensionValue) {
  6076. if (row >= 0 && column >= 0) this.setAtLeast(row, column, minimumDimensionValue);
  6077. }
  6078. isWithin() {
  6079. return IntersectionMatrix.isTrue(this._matrix[Location.INTERIOR][Location.INTERIOR]) && this._matrix[Location.INTERIOR][Location.EXTERIOR] === Dimension.FALSE && this._matrix[Location.BOUNDARY][Location.EXTERIOR] === Dimension.FALSE;
  6080. }
  6081. isTouches(dimensionOfGeometryA, dimensionOfGeometryB) {
  6082. if (dimensionOfGeometryA > dimensionOfGeometryB) return this.isTouches(dimensionOfGeometryB, dimensionOfGeometryA);
  6083. if (dimensionOfGeometryA === Dimension.A && dimensionOfGeometryB === Dimension.A || dimensionOfGeometryA === Dimension.L && dimensionOfGeometryB === Dimension.L || dimensionOfGeometryA === Dimension.L && dimensionOfGeometryB === Dimension.A || dimensionOfGeometryA === Dimension.P && dimensionOfGeometryB === Dimension.A || dimensionOfGeometryA === Dimension.P && dimensionOfGeometryB === Dimension.L) return this._matrix[Location.INTERIOR][Location.INTERIOR] === Dimension.FALSE && (IntersectionMatrix.isTrue(this._matrix[Location.INTERIOR][Location.BOUNDARY]) || IntersectionMatrix.isTrue(this._matrix[Location.BOUNDARY][Location.INTERIOR]) || IntersectionMatrix.isTrue(this._matrix[Location.BOUNDARY][Location.BOUNDARY]));
  6084. return false;
  6085. }
  6086. isOverlaps(dimensionOfGeometryA, dimensionOfGeometryB) {
  6087. if (dimensionOfGeometryA === Dimension.P && dimensionOfGeometryB === Dimension.P || dimensionOfGeometryA === Dimension.A && dimensionOfGeometryB === Dimension.A) return IntersectionMatrix.isTrue(this._matrix[Location.INTERIOR][Location.INTERIOR]) && IntersectionMatrix.isTrue(this._matrix[Location.INTERIOR][Location.EXTERIOR]) && IntersectionMatrix.isTrue(this._matrix[Location.EXTERIOR][Location.INTERIOR]);
  6088. if (dimensionOfGeometryA === Dimension.L && dimensionOfGeometryB === Dimension.L) return this._matrix[Location.INTERIOR][Location.INTERIOR] === 1 && IntersectionMatrix.isTrue(this._matrix[Location.INTERIOR][Location.EXTERIOR]) && IntersectionMatrix.isTrue(this._matrix[Location.EXTERIOR][Location.INTERIOR]);
  6089. return false;
  6090. }
  6091. isEquals(dimensionOfGeometryA, dimensionOfGeometryB) {
  6092. if (dimensionOfGeometryA !== dimensionOfGeometryB) return false;
  6093. return IntersectionMatrix.isTrue(this._matrix[Location.INTERIOR][Location.INTERIOR]) && this._matrix[Location.INTERIOR][Location.EXTERIOR] === Dimension.FALSE && this._matrix[Location.BOUNDARY][Location.EXTERIOR] === Dimension.FALSE && this._matrix[Location.EXTERIOR][Location.INTERIOR] === Dimension.FALSE && this._matrix[Location.EXTERIOR][Location.BOUNDARY] === Dimension.FALSE;
  6094. }
  6095. toString() {
  6096. const builder = new StringBuilder('123456789');
  6097. for (let ai = 0; ai < 3; ai++) for (let bi = 0; bi < 3; bi++) builder.setCharAt(3 * ai + bi, Dimension.toDimensionSymbol(this._matrix[ai][bi]));
  6098. return builder.toString();
  6099. }
  6100. setAll(dimensionValue) {
  6101. for (let ai = 0; ai < 3; ai++) for (let bi = 0; bi < 3; bi++) this._matrix[ai][bi] = dimensionValue;
  6102. }
  6103. get(row, column) {
  6104. return this._matrix[row][column];
  6105. }
  6106. transpose() {
  6107. let temp = this._matrix[1][0];
  6108. this._matrix[1][0] = this._matrix[0][1];
  6109. this._matrix[0][1] = temp;
  6110. temp = this._matrix[2][0];
  6111. this._matrix[2][0] = this._matrix[0][2];
  6112. this._matrix[0][2] = temp;
  6113. temp = this._matrix[2][1];
  6114. this._matrix[2][1] = this._matrix[1][2];
  6115. this._matrix[1][2] = temp;
  6116. return this;
  6117. }
  6118. matches(requiredDimensionSymbols) {
  6119. if (requiredDimensionSymbols.length !== 9) throw new IllegalArgumentException('Should be length 9: ' + requiredDimensionSymbols);
  6120. for (let ai = 0; ai < 3; ai++) for (let bi = 0; bi < 3; bi++) if (!IntersectionMatrix.matches(this._matrix[ai][bi], requiredDimensionSymbols.charAt(3 * ai + bi))) return false;
  6121. return true;
  6122. }
  6123. add(im) {
  6124. for (let i = 0; i < 3; i++) for (let j = 0; j < 3; j++) this.setAtLeast(i, j, im.get(i, j));
  6125. }
  6126. isDisjoint() {
  6127. return this._matrix[Location.INTERIOR][Location.INTERIOR] === Dimension.FALSE && this._matrix[Location.INTERIOR][Location.BOUNDARY] === Dimension.FALSE && this._matrix[Location.BOUNDARY][Location.INTERIOR] === Dimension.FALSE && this._matrix[Location.BOUNDARY][Location.BOUNDARY] === Dimension.FALSE;
  6128. }
  6129. isCrosses(dimensionOfGeometryA, dimensionOfGeometryB) {
  6130. if (dimensionOfGeometryA === Dimension.P && dimensionOfGeometryB === Dimension.L || dimensionOfGeometryA === Dimension.P && dimensionOfGeometryB === Dimension.A || dimensionOfGeometryA === Dimension.L && dimensionOfGeometryB === Dimension.A) return IntersectionMatrix.isTrue(this._matrix[Location.INTERIOR][Location.INTERIOR]) && IntersectionMatrix.isTrue(this._matrix[Location.INTERIOR][Location.EXTERIOR]);
  6131. if (dimensionOfGeometryA === Dimension.L && dimensionOfGeometryB === Dimension.P || dimensionOfGeometryA === Dimension.A && dimensionOfGeometryB === Dimension.P || dimensionOfGeometryA === Dimension.A && dimensionOfGeometryB === Dimension.L) return IntersectionMatrix.isTrue(this._matrix[Location.INTERIOR][Location.INTERIOR]) && IntersectionMatrix.isTrue(this._matrix[Location.EXTERIOR][Location.INTERIOR]);
  6132. if (dimensionOfGeometryA === Dimension.L && dimensionOfGeometryB === Dimension.L) return this._matrix[Location.INTERIOR][Location.INTERIOR] === 0;
  6133. return false;
  6134. }
  6135. get interfaces_() {
  6136. return [Clonable];
  6137. }
  6138. }
  6139. class Angle {
  6140. static toDegrees(radians) {
  6141. return radians * 180 / Math.PI;
  6142. }
  6143. static normalize(angle) {
  6144. while (angle > Math.PI) angle -= Angle.PI_TIMES_2;
  6145. while (angle <= -Math.PI) angle += Angle.PI_TIMES_2;
  6146. return angle;
  6147. }
  6148. static angle() {
  6149. if (arguments.length === 1) {
  6150. const p = arguments[0];
  6151. return Math.atan2(p.y, p.x);
  6152. } else if (arguments.length === 2) {
  6153. const p0 = arguments[0],
  6154. p1 = arguments[1];
  6155. const dx = p1.x - p0.x;
  6156. const dy = p1.y - p0.y;
  6157. return Math.atan2(dy, dx);
  6158. }
  6159. }
  6160. static isAcute(p0, p1, p2) {
  6161. const dx0 = p0.x - p1.x;
  6162. const dy0 = p0.y - p1.y;
  6163. const dx1 = p2.x - p1.x;
  6164. const dy1 = p2.y - p1.y;
  6165. const dotprod = dx0 * dx1 + dy0 * dy1;
  6166. return dotprod > 0;
  6167. }
  6168. static isObtuse(p0, p1, p2) {
  6169. const dx0 = p0.x - p1.x;
  6170. const dy0 = p0.y - p1.y;
  6171. const dx1 = p2.x - p1.x;
  6172. const dy1 = p2.y - p1.y;
  6173. const dotprod = dx0 * dx1 + dy0 * dy1;
  6174. return dotprod < 0;
  6175. }
  6176. static interiorAngle(p0, p1, p2) {
  6177. const anglePrev = Angle.angle(p1, p0);
  6178. const angleNext = Angle.angle(p1, p2);
  6179. return Math.abs(angleNext - anglePrev);
  6180. }
  6181. static normalizePositive(angle) {
  6182. if (angle < 0.0) {
  6183. while (angle < 0.0) angle += Angle.PI_TIMES_2;
  6184. if (angle >= Angle.PI_TIMES_2) angle = 0.0;
  6185. } else {
  6186. while (angle >= Angle.PI_TIMES_2) angle -= Angle.PI_TIMES_2;
  6187. if (angle < 0.0) angle = 0.0;
  6188. }
  6189. return angle;
  6190. }
  6191. static angleBetween(tip1, tail, tip2) {
  6192. const a1 = Angle.angle(tail, tip1);
  6193. const a2 = Angle.angle(tail, tip2);
  6194. return Angle.diff(a1, a2);
  6195. }
  6196. static diff(ang1, ang2) {
  6197. let delAngle = null;
  6198. if (ang1 < ang2) delAngle = ang2 - ang1;else delAngle = ang1 - ang2;
  6199. if (delAngle > Math.PI) delAngle = 2 * Math.PI - delAngle;
  6200. return delAngle;
  6201. }
  6202. static toRadians(angleDegrees) {
  6203. return angleDegrees * Math.PI / 180.0;
  6204. }
  6205. static getTurn(ang1, ang2) {
  6206. const crossproduct = Math.sin(ang2 - ang1);
  6207. if (crossproduct > 0) return Angle.COUNTERCLOCKWISE;
  6208. if (crossproduct < 0) return Angle.CLOCKWISE;
  6209. return Angle.NONE;
  6210. }
  6211. static angleBetweenOriented(tip1, tail, tip2) {
  6212. const a1 = Angle.angle(tail, tip1);
  6213. const a2 = Angle.angle(tail, tip2);
  6214. const angDel = a2 - a1;
  6215. if (angDel <= -Math.PI) return angDel + Angle.PI_TIMES_2;
  6216. if (angDel > Math.PI) return angDel - Angle.PI_TIMES_2;
  6217. return angDel;
  6218. }
  6219. }
  6220. Angle.PI_TIMES_2 = 2.0 * Math.PI;
  6221. Angle.PI_OVER_2 = Math.PI / 2.0;
  6222. Angle.PI_OVER_4 = Math.PI / 4.0;
  6223. Angle.COUNTERCLOCKWISE = Orientation.COUNTERCLOCKWISE;
  6224. Angle.CLOCKWISE = Orientation.CLOCKWISE;
  6225. Angle.NONE = Orientation.COLLINEAR;
  6226. class NotRepresentableException extends Exception {
  6227. constructor() {
  6228. super();
  6229. NotRepresentableException.constructor_.apply(this, arguments);
  6230. }
  6231. static constructor_() {
  6232. Exception.constructor_.call(this, 'Projective point not representable on the Cartesian plane.');
  6233. }
  6234. }
  6235. class HCoordinate {
  6236. constructor() {
  6237. HCoordinate.constructor_.apply(this, arguments);
  6238. }
  6239. static constructor_() {
  6240. this.x = null;
  6241. this.y = null;
  6242. this.w = null;
  6243. if (arguments.length === 0) {
  6244. this.x = 0.0;
  6245. this.y = 0.0;
  6246. this.w = 1.0;
  6247. } else if (arguments.length === 1) {
  6248. const p = arguments[0];
  6249. this.x = p.x;
  6250. this.y = p.y;
  6251. this.w = 1.0;
  6252. } else if (arguments.length === 2) {
  6253. if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') {
  6254. const _x = arguments[0],
  6255. _y = arguments[1];
  6256. this.x = _x;
  6257. this.y = _y;
  6258. this.w = 1.0;
  6259. } else if (arguments[0] instanceof HCoordinate && arguments[1] instanceof HCoordinate) {
  6260. const p1 = arguments[0],
  6261. p2 = arguments[1];
  6262. this.x = p1.y * p2.w - p2.y * p1.w;
  6263. this.y = p2.x * p1.w - p1.x * p2.w;
  6264. this.w = p1.x * p2.y - p2.x * p1.y;
  6265. } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Coordinate) {
  6266. const p1 = arguments[0],
  6267. p2 = arguments[1];
  6268. this.x = p1.y - p2.y;
  6269. this.y = p2.x - p1.x;
  6270. this.w = p1.x * p2.y - p2.x * p1.y;
  6271. }
  6272. } else if (arguments.length === 3) {
  6273. const _x = arguments[0],
  6274. _y = arguments[1],
  6275. _w = arguments[2];
  6276. this.x = _x;
  6277. this.y = _y;
  6278. this.w = _w;
  6279. } else if (arguments.length === 4) {
  6280. const p1 = arguments[0],
  6281. p2 = arguments[1],
  6282. q1 = arguments[2],
  6283. q2 = arguments[3];
  6284. const px = p1.y - p2.y;
  6285. const py = p2.x - p1.x;
  6286. const pw = p1.x * p2.y - p2.x * p1.y;
  6287. const qx = q1.y - q2.y;
  6288. const qy = q2.x - q1.x;
  6289. const qw = q1.x * q2.y - q2.x * q1.y;
  6290. this.x = py * qw - qy * pw;
  6291. this.y = qx * pw - px * qw;
  6292. this.w = px * qy - qx * py;
  6293. }
  6294. }
  6295. getY() {
  6296. const a = this.y / this.w;
  6297. if (Double.isNaN(a) || Double.isInfinite(a)) throw new NotRepresentableException();
  6298. return a;
  6299. }
  6300. getX() {
  6301. const a = this.x / this.w;
  6302. if (Double.isNaN(a) || Double.isInfinite(a)) throw new NotRepresentableException();
  6303. return a;
  6304. }
  6305. getCoordinate() {
  6306. const p = new Coordinate();
  6307. p.x = this.getX();
  6308. p.y = this.getY();
  6309. return p;
  6310. }
  6311. }
  6312. class Triangle {
  6313. constructor() {
  6314. Triangle.constructor_.apply(this, arguments);
  6315. }
  6316. static constructor_() {
  6317. this.p0 = null;
  6318. this.p1 = null;
  6319. this.p2 = null;
  6320. const p0 = arguments[0],
  6321. p1 = arguments[1],
  6322. p2 = arguments[2];
  6323. this.p0 = p0;
  6324. this.p1 = p1;
  6325. this.p2 = p2;
  6326. }
  6327. static area(a, b, c) {
  6328. return Math.abs(((c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y)) / 2);
  6329. }
  6330. static signedArea(a, b, c) {
  6331. return ((c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y)) / 2;
  6332. }
  6333. static det(m00, m01, m10, m11) {
  6334. return m00 * m11 - m01 * m10;
  6335. }
  6336. static interpolateZ(p, v0, v1, v2) {
  6337. const x0 = v0.x;
  6338. const y0 = v0.y;
  6339. const a = v1.x - x0;
  6340. const b = v2.x - x0;
  6341. const c = v1.y - y0;
  6342. const d = v2.y - y0;
  6343. const det = a * d - b * c;
  6344. const dx = p.x - x0;
  6345. const dy = p.y - y0;
  6346. const t = (d * dx - b * dy) / det;
  6347. const u = (-c * dx + a * dy) / det;
  6348. const z = v0.getZ() + t * (v1.getZ() - v0.getZ()) + u * (v2.getZ() - v0.getZ());
  6349. return z;
  6350. }
  6351. static longestSideLength(a, b, c) {
  6352. const lenAB = a.distance(b);
  6353. const lenBC = b.distance(c);
  6354. const lenCA = c.distance(a);
  6355. let maxLen = lenAB;
  6356. if (lenBC > maxLen) maxLen = lenBC;
  6357. if (lenCA > maxLen) maxLen = lenCA;
  6358. return maxLen;
  6359. }
  6360. static circumcentreDD(a, b, c) {
  6361. const ax = DD.valueOf(a.x).subtract(c.x);
  6362. const ay = DD.valueOf(a.y).subtract(c.y);
  6363. const bx = DD.valueOf(b.x).subtract(c.x);
  6364. const by = DD.valueOf(b.y).subtract(c.y);
  6365. const denom = DD.determinant(ax, ay, bx, by).multiply(2);
  6366. const asqr = ax.sqr().add(ay.sqr());
  6367. const bsqr = bx.sqr().add(by.sqr());
  6368. const numx = DD.determinant(ay, asqr, by, bsqr);
  6369. const numy = DD.determinant(ax, asqr, bx, bsqr);
  6370. const ccx = DD.valueOf(c.x).subtract(numx.divide(denom)).doubleValue();
  6371. const ccy = DD.valueOf(c.y).add(numy.divide(denom)).doubleValue();
  6372. return new Coordinate(ccx, ccy);
  6373. }
  6374. static isAcute(a, b, c) {
  6375. if (!Angle.isAcute(a, b, c)) return false;
  6376. if (!Angle.isAcute(b, c, a)) return false;
  6377. if (!Angle.isAcute(c, a, b)) return false;
  6378. return true;
  6379. }
  6380. static circumcentre(a, b, c) {
  6381. const cx = c.x;
  6382. const cy = c.y;
  6383. const ax = a.x - cx;
  6384. const ay = a.y - cy;
  6385. const bx = b.x - cx;
  6386. const by = b.y - cy;
  6387. const denom = 2 * Triangle.det(ax, ay, bx, by);
  6388. const numx = Triangle.det(ay, ax * ax + ay * ay, by, bx * bx + by * by);
  6389. const numy = Triangle.det(ax, ax * ax + ay * ay, bx, bx * bx + by * by);
  6390. const ccx = cx - numx / denom;
  6391. const ccy = cy + numy / denom;
  6392. return new Coordinate(ccx, ccy);
  6393. }
  6394. static perpendicularBisector(a, b) {
  6395. const dx = b.x - a.x;
  6396. const dy = b.y - a.y;
  6397. const l1 = new HCoordinate(a.x + dx / 2.0, a.y + dy / 2.0, 1.0);
  6398. const l2 = new HCoordinate(a.x - dy + dx / 2.0, a.y + dx + dy / 2.0, 1.0);
  6399. return new HCoordinate(l1, l2);
  6400. }
  6401. static angleBisector(a, b, c) {
  6402. const len0 = b.distance(a);
  6403. const len2 = b.distance(c);
  6404. const frac = len0 / (len0 + len2);
  6405. const dx = c.x - a.x;
  6406. const dy = c.y - a.y;
  6407. const splitPt = new Coordinate(a.x + frac * dx, a.y + frac * dy);
  6408. return splitPt;
  6409. }
  6410. static area3D(a, b, c) {
  6411. const ux = b.x - a.x;
  6412. const uy = b.y - a.y;
  6413. const uz = b.getZ() - a.getZ();
  6414. const vx = c.x - a.x;
  6415. const vy = c.y - a.y;
  6416. const vz = c.getZ() - a.getZ();
  6417. const crossx = uy * vz - uz * vy;
  6418. const crossy = uz * vx - ux * vz;
  6419. const crossz = ux * vy - uy * vx;
  6420. const absSq = crossx * crossx + crossy * crossy + crossz * crossz;
  6421. const area3D = Math.sqrt(absSq) / 2;
  6422. return area3D;
  6423. }
  6424. static centroid(a, b, c) {
  6425. const x = (a.x + b.x + c.x) / 3;
  6426. const y = (a.y + b.y + c.y) / 3;
  6427. return new Coordinate(x, y);
  6428. }
  6429. static inCentre(a, b, c) {
  6430. const len0 = b.distance(c);
  6431. const len1 = a.distance(c);
  6432. const len2 = a.distance(b);
  6433. const circum = len0 + len1 + len2;
  6434. const inCentreX = (len0 * a.x + len1 * b.x + len2 * c.x) / circum;
  6435. const inCentreY = (len0 * a.y + len1 * b.y + len2 * c.y) / circum;
  6436. return new Coordinate(inCentreX, inCentreY);
  6437. }
  6438. area() {
  6439. return Triangle.area(this.p0, this.p1, this.p2);
  6440. }
  6441. signedArea() {
  6442. return Triangle.signedArea(this.p0, this.p1, this.p2);
  6443. }
  6444. interpolateZ(p) {
  6445. if (p === null) throw new IllegalArgumentException('Supplied point is null.');
  6446. return Triangle.interpolateZ(p, this.p0, this.p1, this.p2);
  6447. }
  6448. longestSideLength() {
  6449. return Triangle.longestSideLength(this.p0, this.p1, this.p2);
  6450. }
  6451. isAcute() {
  6452. return Triangle.isAcute(this.p0, this.p1, this.p2);
  6453. }
  6454. circumcentre() {
  6455. return Triangle.circumcentre(this.p0, this.p1, this.p2);
  6456. }
  6457. area3D() {
  6458. return Triangle.area3D(this.p0, this.p1, this.p2);
  6459. }
  6460. centroid() {
  6461. return Triangle.centroid(this.p0, this.p1, this.p2);
  6462. }
  6463. inCentre() {
  6464. return Triangle.inCentre(this.p0, this.p1, this.p2);
  6465. }
  6466. }
  6467. class NoninvertibleTransformationException extends Exception {
  6468. constructor() {
  6469. super();
  6470. NoninvertibleTransformationException.constructor_.apply(this, arguments);
  6471. }
  6472. static constructor_() {
  6473. if (arguments.length === 0) {
  6474. Exception.constructor_.call(this);
  6475. } else if (arguments.length === 1) {
  6476. const msg = arguments[0];
  6477. Exception.constructor_.call(this, msg);
  6478. }
  6479. }
  6480. }
  6481. class AffineTransformation {
  6482. constructor() {
  6483. AffineTransformation.constructor_.apply(this, arguments);
  6484. }
  6485. static constructor_() {
  6486. this._m00 = null;
  6487. this._m01 = null;
  6488. this._m02 = null;
  6489. this._m10 = null;
  6490. this._m11 = null;
  6491. this._m12 = null;
  6492. if (arguments.length === 0) {
  6493. this.setToIdentity();
  6494. } else if (arguments.length === 1) {
  6495. if (arguments[0] instanceof Array) {
  6496. const matrix = arguments[0];
  6497. this._m00 = matrix[0];
  6498. this._m01 = matrix[1];
  6499. this._m02 = matrix[2];
  6500. this._m10 = matrix[3];
  6501. this._m11 = matrix[4];
  6502. this._m12 = matrix[5];
  6503. } else if (arguments[0] instanceof AffineTransformation) {
  6504. const trans = arguments[0];
  6505. this.setTransformation(trans);
  6506. }
  6507. } else if (arguments.length === 6) {
  6508. if (typeof arguments[5] === 'number' && typeof arguments[4] === 'number' && typeof arguments[3] === 'number' && typeof arguments[2] === 'number' && typeof arguments[0] === 'number' && typeof arguments[1] === 'number') {
  6509. const m00 = arguments[0],
  6510. m01 = arguments[1],
  6511. m02 = arguments[2],
  6512. m10 = arguments[3],
  6513. m11 = arguments[4],
  6514. m12 = arguments[5];
  6515. this.setTransformation(m00, m01, m02, m10, m11, m12);
  6516. }
  6517. }
  6518. }
  6519. static translationInstance(x, y) {
  6520. const trans = new AffineTransformation();
  6521. trans.setToTranslation(x, y);
  6522. return trans;
  6523. }
  6524. static shearInstance(xShear, yShear) {
  6525. const trans = new AffineTransformation();
  6526. trans.setToShear(xShear, yShear);
  6527. return trans;
  6528. }
  6529. static reflectionInstance() {
  6530. if (arguments.length === 2) {
  6531. const x = arguments[0],
  6532. y = arguments[1];
  6533. const trans = new AffineTransformation();
  6534. trans.setToReflection(x, y);
  6535. return trans;
  6536. } else if (arguments.length === 4) {
  6537. const x0 = arguments[0],
  6538. y0 = arguments[1],
  6539. x1 = arguments[2],
  6540. y1 = arguments[3];
  6541. const trans = new AffineTransformation();
  6542. trans.setToReflection(x0, y0, x1, y1);
  6543. return trans;
  6544. }
  6545. }
  6546. static rotationInstance() {
  6547. if (arguments.length === 1) {
  6548. const theta = arguments[0];
  6549. return AffineTransformation.rotationInstance(Math.sin(theta), Math.cos(theta));
  6550. } else if (arguments.length === 2) {
  6551. const sinTheta = arguments[0],
  6552. cosTheta = arguments[1];
  6553. const trans = new AffineTransformation();
  6554. trans.setToRotation(sinTheta, cosTheta);
  6555. return trans;
  6556. } else if (arguments.length === 3) {
  6557. const theta = arguments[0],
  6558. x = arguments[1],
  6559. y = arguments[2];
  6560. return AffineTransformation.rotationInstance(Math.sin(theta), Math.cos(theta), x, y);
  6561. } else if (arguments.length === 4) {
  6562. const sinTheta = arguments[0],
  6563. cosTheta = arguments[1],
  6564. x = arguments[2],
  6565. y = arguments[3];
  6566. const trans = new AffineTransformation();
  6567. trans.setToRotation(sinTheta, cosTheta, x, y);
  6568. return trans;
  6569. }
  6570. }
  6571. static scaleInstance() {
  6572. if (arguments.length === 2) {
  6573. const xScale = arguments[0],
  6574. yScale = arguments[1];
  6575. const trans = new AffineTransformation();
  6576. trans.setToScale(xScale, yScale);
  6577. return trans;
  6578. } else if (arguments.length === 4) {
  6579. const xScale = arguments[0],
  6580. yScale = arguments[1],
  6581. x = arguments[2],
  6582. y = arguments[3];
  6583. const trans = new AffineTransformation();
  6584. trans.translate(-x, -y);
  6585. trans.scale(xScale, yScale);
  6586. trans.translate(x, y);
  6587. return trans;
  6588. }
  6589. }
  6590. setToReflectionBasic(x0, y0, x1, y1) {
  6591. if (x0 === x1 && y0 === y1) throw new IllegalArgumentException('Reflection line points must be distinct');
  6592. const dx = x1 - x0;
  6593. const dy = y1 - y0;
  6594. const d = Math.sqrt(dx * dx + dy * dy);
  6595. const sin = dy / d;
  6596. const cos = dx / d;
  6597. const cs2 = 2 * sin * cos;
  6598. const c2s2 = cos * cos - sin * sin;
  6599. this._m00 = c2s2;
  6600. this._m01 = cs2;
  6601. this._m02 = 0.0;
  6602. this._m10 = cs2;
  6603. this._m11 = -c2s2;
  6604. this._m12 = 0.0;
  6605. return this;
  6606. }
  6607. getInverse() {
  6608. const det = this.getDeterminant();
  6609. if (det === 0) throw new NoninvertibleTransformationException('Transformation is non-invertible');
  6610. const im00 = this._m11 / det;
  6611. const im10 = -this._m10 / det;
  6612. const im01 = -this._m01 / det;
  6613. const im11 = this._m00 / det;
  6614. const im02 = (this._m01 * this._m12 - this._m02 * this._m11) / det;
  6615. const im12 = (-this._m00 * this._m12 + this._m10 * this._m02) / det;
  6616. return new AffineTransformation(im00, im01, im02, im10, im11, im12);
  6617. }
  6618. compose(trans) {
  6619. const mp00 = trans._m00 * this._m00 + trans._m01 * this._m10;
  6620. const mp01 = trans._m00 * this._m01 + trans._m01 * this._m11;
  6621. const mp02 = trans._m00 * this._m02 + trans._m01 * this._m12 + trans._m02;
  6622. const mp10 = trans._m10 * this._m00 + trans._m11 * this._m10;
  6623. const mp11 = trans._m10 * this._m01 + trans._m11 * this._m11;
  6624. const mp12 = trans._m10 * this._m02 + trans._m11 * this._m12 + trans._m12;
  6625. this._m00 = mp00;
  6626. this._m01 = mp01;
  6627. this._m02 = mp02;
  6628. this._m10 = mp10;
  6629. this._m11 = mp11;
  6630. this._m12 = mp12;
  6631. return this;
  6632. }
  6633. equals(obj) {
  6634. if (obj === null) return false;
  6635. if (!(obj instanceof AffineTransformation)) return false;
  6636. const trans = obj;
  6637. return this._m00 === trans._m00 && this._m01 === trans._m01 && this._m02 === trans._m02 && this._m10 === trans._m10 && this._m11 === trans._m11 && this._m12 === trans._m12;
  6638. }
  6639. setToScale(xScale, yScale) {
  6640. this._m00 = xScale;
  6641. this._m01 = 0.0;
  6642. this._m02 = 0.0;
  6643. this._m10 = 0.0;
  6644. this._m11 = yScale;
  6645. this._m12 = 0.0;
  6646. return this;
  6647. }
  6648. isIdentity() {
  6649. return this._m00 === 1 && this._m01 === 0 && this._m02 === 0 && this._m10 === 0 && this._m11 === 1 && this._m12 === 0;
  6650. }
  6651. scale(xScale, yScale) {
  6652. this.compose(AffineTransformation.scaleInstance(xScale, yScale));
  6653. return this;
  6654. }
  6655. setToIdentity() {
  6656. this._m00 = 1.0;
  6657. this._m01 = 0.0;
  6658. this._m02 = 0.0;
  6659. this._m10 = 0.0;
  6660. this._m11 = 1.0;
  6661. this._m12 = 0.0;
  6662. return this;
  6663. }
  6664. isGeometryChanged() {
  6665. return true;
  6666. }
  6667. setTransformation() {
  6668. if (arguments.length === 1) {
  6669. const trans = arguments[0];
  6670. this._m00 = trans._m00;
  6671. this._m01 = trans._m01;
  6672. this._m02 = trans._m02;
  6673. this._m10 = trans._m10;
  6674. this._m11 = trans._m11;
  6675. this._m12 = trans._m12;
  6676. return this;
  6677. } else if (arguments.length === 6) {
  6678. const m00 = arguments[0],
  6679. m01 = arguments[1],
  6680. m02 = arguments[2],
  6681. m10 = arguments[3],
  6682. m11 = arguments[4],
  6683. m12 = arguments[5];
  6684. this._m00 = m00;
  6685. this._m01 = m01;
  6686. this._m02 = m02;
  6687. this._m10 = m10;
  6688. this._m11 = m11;
  6689. this._m12 = m12;
  6690. return this;
  6691. }
  6692. }
  6693. setToRotation() {
  6694. if (arguments.length === 1) {
  6695. const theta = arguments[0];
  6696. this.setToRotation(Math.sin(theta), Math.cos(theta));
  6697. return this;
  6698. } else if (arguments.length === 2) {
  6699. const sinTheta = arguments[0],
  6700. cosTheta = arguments[1];
  6701. this._m00 = cosTheta;
  6702. this._m01 = -sinTheta;
  6703. this._m02 = 0.0;
  6704. this._m10 = sinTheta;
  6705. this._m11 = cosTheta;
  6706. this._m12 = 0.0;
  6707. return this;
  6708. } else if (arguments.length === 3) {
  6709. const theta = arguments[0],
  6710. x = arguments[1],
  6711. y = arguments[2];
  6712. this.setToRotation(Math.sin(theta), Math.cos(theta), x, y);
  6713. return this;
  6714. } else if (arguments.length === 4) {
  6715. const sinTheta = arguments[0],
  6716. cosTheta = arguments[1],
  6717. x = arguments[2],
  6718. y = arguments[3];
  6719. this._m00 = cosTheta;
  6720. this._m01 = -sinTheta;
  6721. this._m02 = x - x * cosTheta + y * sinTheta;
  6722. this._m10 = sinTheta;
  6723. this._m11 = cosTheta;
  6724. this._m12 = y - x * sinTheta - y * cosTheta;
  6725. return this;
  6726. }
  6727. }
  6728. getMatrixEntries() {
  6729. return [this._m00, this._m01, this._m02, this._m10, this._m11, this._m12];
  6730. }
  6731. filter(seq, i) {
  6732. this.transform(seq, i);
  6733. }
  6734. rotate() {
  6735. if (arguments.length === 1) {
  6736. const theta = arguments[0];
  6737. this.compose(AffineTransformation.rotationInstance(theta));
  6738. return this;
  6739. } else if (arguments.length === 2) {
  6740. const sinTheta = arguments[0],
  6741. cosTheta = arguments[1];
  6742. this.compose(AffineTransformation.rotationInstance(sinTheta, cosTheta));
  6743. return this;
  6744. } else if (arguments.length === 3) {
  6745. const theta = arguments[0],
  6746. x = arguments[1],
  6747. y = arguments[2];
  6748. this.compose(AffineTransformation.rotationInstance(theta, x, y));
  6749. return this;
  6750. } else if (arguments.length === 4) {
  6751. const sinTheta = arguments[0],
  6752. cosTheta = arguments[1],
  6753. x = arguments[2],
  6754. y = arguments[3];
  6755. this.compose(AffineTransformation.rotationInstance(sinTheta, cosTheta, x, y));
  6756. return this;
  6757. }
  6758. }
  6759. getDeterminant() {
  6760. return this._m00 * this._m11 - this._m01 * this._m10;
  6761. }
  6762. composeBefore(trans) {
  6763. const mp00 = this._m00 * trans._m00 + this._m01 * trans._m10;
  6764. const mp01 = this._m00 * trans._m01 + this._m01 * trans._m11;
  6765. const mp02 = this._m00 * trans._m02 + this._m01 * trans._m12 + this._m02;
  6766. const mp10 = this._m10 * trans._m00 + this._m11 * trans._m10;
  6767. const mp11 = this._m10 * trans._m01 + this._m11 * trans._m11;
  6768. const mp12 = this._m10 * trans._m02 + this._m11 * trans._m12 + this._m12;
  6769. this._m00 = mp00;
  6770. this._m01 = mp01;
  6771. this._m02 = mp02;
  6772. this._m10 = mp10;
  6773. this._m11 = mp11;
  6774. this._m12 = mp12;
  6775. return this;
  6776. }
  6777. setToShear(xShear, yShear) {
  6778. this._m00 = 1.0;
  6779. this._m01 = xShear;
  6780. this._m02 = 0.0;
  6781. this._m10 = yShear;
  6782. this._m11 = 1.0;
  6783. this._m12 = 0.0;
  6784. return this;
  6785. }
  6786. isDone() {
  6787. return false;
  6788. }
  6789. clone() {
  6790. try {
  6791. return null;
  6792. } catch (ex) {
  6793. if (ex instanceof Exception) Assert.shouldNeverReachHere();else throw ex;
  6794. } finally {}
  6795. return null;
  6796. }
  6797. translate(x, y) {
  6798. this.compose(AffineTransformation.translationInstance(x, y));
  6799. return this;
  6800. }
  6801. setToReflection() {
  6802. if (arguments.length === 2) {
  6803. const x = arguments[0],
  6804. y = arguments[1];
  6805. if (x === 0.0 && y === 0.0) throw new IllegalArgumentException('Reflection vector must be non-zero');
  6806. if (x === y) {
  6807. this._m00 = 0.0;
  6808. this._m01 = 1.0;
  6809. this._m02 = 0.0;
  6810. this._m10 = 1.0;
  6811. this._m11 = 0.0;
  6812. this._m12 = 0.0;
  6813. return this;
  6814. }
  6815. const d = Math.sqrt(x * x + y * y);
  6816. const sin = y / d;
  6817. const cos = x / d;
  6818. this.rotate(-sin, cos);
  6819. this.scale(1, -1);
  6820. this.rotate(sin, cos);
  6821. return this;
  6822. } else if (arguments.length === 4) {
  6823. const x0 = arguments[0],
  6824. y0 = arguments[1],
  6825. x1 = arguments[2],
  6826. y1 = arguments[3];
  6827. if (x0 === x1 && y0 === y1) throw new IllegalArgumentException('Reflection line points must be distinct');
  6828. this.setToTranslation(-x0, -y0);
  6829. const dx = x1 - x0;
  6830. const dy = y1 - y0;
  6831. const d = Math.sqrt(dx * dx + dy * dy);
  6832. const sin = dy / d;
  6833. const cos = dx / d;
  6834. this.rotate(-sin, cos);
  6835. this.scale(1, -1);
  6836. this.rotate(sin, cos);
  6837. this.translate(x0, y0);
  6838. return this;
  6839. }
  6840. }
  6841. toString() {
  6842. return 'AffineTransformation[[' + this._m00 + ', ' + this._m01 + ', ' + this._m02 + '], [' + this._m10 + ', ' + this._m11 + ', ' + this._m12 + ']]';
  6843. }
  6844. setToTranslation(dx, dy) {
  6845. this._m00 = 1.0;
  6846. this._m01 = 0.0;
  6847. this._m02 = dx;
  6848. this._m10 = 0.0;
  6849. this._m11 = 1.0;
  6850. this._m12 = dy;
  6851. return this;
  6852. }
  6853. shear(xShear, yShear) {
  6854. this.compose(AffineTransformation.shearInstance(xShear, yShear));
  6855. return this;
  6856. }
  6857. transform() {
  6858. if (arguments.length === 1) {
  6859. const g = arguments[0];
  6860. const g2 = g.copy();
  6861. g2.apply(this);
  6862. return g2;
  6863. } else if (arguments.length === 2) {
  6864. if (arguments[0] instanceof Coordinate && arguments[1] instanceof Coordinate) {
  6865. const src = arguments[0],
  6866. dest = arguments[1];
  6867. const xp = this._m00 * src.x + this._m01 * src.y + this._m02;
  6868. const yp = this._m10 * src.x + this._m11 * src.y + this._m12;
  6869. dest.x = xp;
  6870. dest.y = yp;
  6871. return dest;
  6872. } else if (hasInterface(arguments[0], CoordinateSequence) && Number.isInteger(arguments[1])) {
  6873. const seq = arguments[0],
  6874. i = arguments[1];
  6875. const xp = this._m00 * seq.getOrdinate(i, 0) + this._m01 * seq.getOrdinate(i, 1) + this._m02;
  6876. const yp = this._m10 * seq.getOrdinate(i, 0) + this._m11 * seq.getOrdinate(i, 1) + this._m12;
  6877. seq.setOrdinate(i, 0, xp);
  6878. seq.setOrdinate(i, 1, yp);
  6879. }
  6880. }
  6881. }
  6882. reflect() {
  6883. if (arguments.length === 2) {
  6884. const x = arguments[0],
  6885. y = arguments[1];
  6886. this.compose(AffineTransformation.reflectionInstance(x, y));
  6887. return this;
  6888. } else if (arguments.length === 4) {
  6889. const x0 = arguments[0],
  6890. y0 = arguments[1],
  6891. x1 = arguments[2],
  6892. y1 = arguments[3];
  6893. this.compose(AffineTransformation.reflectionInstance(x0, y0, x1, y1));
  6894. return this;
  6895. }
  6896. }
  6897. get interfaces_() {
  6898. return [Clonable, CoordinateSequenceFilter];
  6899. }
  6900. }
  6901. class Matrix {
  6902. static solve(a, b) {
  6903. const n = b.length;
  6904. if (a.length !== n || a[0].length !== n) throw new IllegalArgumentException('Matrix A is incorrectly sized');
  6905. for (let i = 0; i < n; i++) {
  6906. let maxElementRow = i;
  6907. for (let j = i + 1; j < n; j++) if (Math.abs(a[j][i]) > Math.abs(a[maxElementRow][i])) maxElementRow = j;
  6908. if (a[maxElementRow][i] === 0.0) return null;
  6909. Matrix.swapRows(a, i, maxElementRow);
  6910. Matrix.swapRows(b, i, maxElementRow);
  6911. for (let j = i + 1; j < n; j++) {
  6912. const rowFactor = a[j][i] / a[i][i];
  6913. for (let k = n - 1; k >= i; k--) a[j][k] -= a[i][k] * rowFactor;
  6914. b[j] -= b[i] * rowFactor;
  6915. }
  6916. }
  6917. const solution = new Array(n).fill(null);
  6918. for (let j = n - 1; j >= 0; j--) {
  6919. let t = 0.0;
  6920. for (let k = j + 1; k < n; k++) t += a[j][k] * solution[k];
  6921. solution[j] = (b[j] - t) / a[j][j];
  6922. }
  6923. return solution;
  6924. }
  6925. static swapRows() {
  6926. if (Number.isInteger(arguments[2]) && arguments[0] instanceof Array && Number.isInteger(arguments[1])) {
  6927. const m = arguments[0],
  6928. i = arguments[1],
  6929. j = arguments[2];
  6930. if (i === j) return null;
  6931. for (let col = 0; col < m[0].length; col++) {
  6932. const temp = m[i][col];
  6933. m[i][col] = m[j][col];
  6934. m[j][col] = temp;
  6935. }
  6936. } else if (Number.isInteger(arguments[2]) && arguments[0] instanceof Array && Number.isInteger(arguments[1])) {
  6937. const m = arguments[0],
  6938. i = arguments[1],
  6939. j = arguments[2];
  6940. if (i === j) return null;
  6941. const temp = m[i];
  6942. m[i] = m[j];
  6943. m[j] = temp;
  6944. }
  6945. }
  6946. }
  6947. class AffineTransformationBuilder {
  6948. constructor() {
  6949. AffineTransformationBuilder.constructor_.apply(this, arguments);
  6950. }
  6951. static constructor_() {
  6952. this._src0 = null;
  6953. this._src1 = null;
  6954. this._src2 = null;
  6955. this._dest0 = null;
  6956. this._dest1 = null;
  6957. this._dest2 = null;
  6958. this._m00 = null;
  6959. this._m01 = null;
  6960. this._m02 = null;
  6961. this._m10 = null;
  6962. this._m11 = null;
  6963. this._m12 = null;
  6964. const src0 = arguments[0],
  6965. src1 = arguments[1],
  6966. src2 = arguments[2],
  6967. dest0 = arguments[3],
  6968. dest1 = arguments[4],
  6969. dest2 = arguments[5];
  6970. this._src0 = src0;
  6971. this._src1 = src1;
  6972. this._src2 = src2;
  6973. this._dest0 = dest0;
  6974. this._dest1 = dest1;
  6975. this._dest2 = dest2;
  6976. }
  6977. solve(b) {
  6978. const a = [[this._src0.x, this._src0.y, 1], [this._src1.x, this._src1.y, 1], [this._src2.x, this._src2.y, 1]];
  6979. return Matrix.solve(a, b);
  6980. }
  6981. compute() {
  6982. const bx = [this._dest0.x, this._dest1.x, this._dest2.x];
  6983. const row0 = this.solve(bx);
  6984. if (row0 === null) return false;
  6985. this._m00 = row0[0];
  6986. this._m01 = row0[1];
  6987. this._m02 = row0[2];
  6988. const by = [this._dest0.y, this._dest1.y, this._dest2.y];
  6989. const row1 = this.solve(by);
  6990. if (row1 === null) return false;
  6991. this._m10 = row1[0];
  6992. this._m11 = row1[1];
  6993. this._m12 = row1[2];
  6994. return true;
  6995. }
  6996. getTransformation() {
  6997. const isSolvable = this.compute();
  6998. if (isSolvable) return new AffineTransformation(this._m00, this._m01, this._m02, this._m10, this._m11, this._m12);
  6999. return null;
  7000. }
  7001. }
  7002. class AffineTransformationFactory {
  7003. static createFromBaseLines(src0, src1, dest0, dest1) {
  7004. const rotPt = new Coordinate(src0.x + dest1.x - dest0.x, src0.y + dest1.y - dest0.y);
  7005. const ang = Angle.angleBetweenOriented(src1, src0, rotPt);
  7006. const srcDist = src1.distance(src0);
  7007. const destDist = dest1.distance(dest0);
  7008. if (srcDist === 0.0) return new AffineTransformation();
  7009. const scale = destDist / srcDist;
  7010. const trans = AffineTransformation.translationInstance(-src0.x, -src0.y);
  7011. trans.rotate(ang);
  7012. trans.scale(scale, scale);
  7013. trans.translate(dest0.x, dest0.y);
  7014. return trans;
  7015. }
  7016. static createFromControlVectors() {
  7017. if (arguments.length === 2) {
  7018. if (arguments[0] instanceof Coordinate && arguments[1] instanceof Coordinate) {
  7019. const src0 = arguments[0],
  7020. dest0 = arguments[1];
  7021. const dx = dest0.x - src0.x;
  7022. const dy = dest0.y - src0.y;
  7023. return AffineTransformation.translationInstance(dx, dy);
  7024. } else if (arguments[0] instanceof Array && arguments[1] instanceof Array) {
  7025. const src = arguments[0],
  7026. dest = arguments[1];
  7027. if (src.length !== dest.length) throw new IllegalArgumentException('Src and Dest arrays are not the same length');
  7028. if (src.length <= 0) throw new IllegalArgumentException('Too few control points');
  7029. if (src.length > 3) throw new IllegalArgumentException('Too many control points');
  7030. if (src.length === 1) return AffineTransformationFactory.createFromControlVectors(src[0], dest[0]);
  7031. if (src.length === 2) return AffineTransformationFactory.createFromControlVectors(src[0], src[1], dest[0], dest[1]);
  7032. return AffineTransformationFactory.createFromControlVectors(src[0], src[1], src[2], dest[0], dest[1], dest[2]);
  7033. }
  7034. } else if (arguments.length === 4) {
  7035. const src0 = arguments[0],
  7036. src1 = arguments[1],
  7037. dest0 = arguments[2],
  7038. dest1 = arguments[3];
  7039. const rotPt = new Coordinate(dest1.x - dest0.x, dest1.y - dest0.y);
  7040. const ang = Angle.angleBetweenOriented(src1, src0, rotPt);
  7041. const srcDist = src1.distance(src0);
  7042. const destDist = dest1.distance(dest0);
  7043. if (srcDist === 0.0) return null;
  7044. const scale = destDist / srcDist;
  7045. const trans = AffineTransformation.translationInstance(-src0.x, -src0.y);
  7046. trans.rotate(ang);
  7047. trans.scale(scale, scale);
  7048. trans.translate(dest0.x, dest0.y);
  7049. return trans;
  7050. } else if (arguments.length === 6) {
  7051. const src0 = arguments[0],
  7052. src1 = arguments[1],
  7053. src2 = arguments[2],
  7054. dest0 = arguments[3],
  7055. dest1 = arguments[4],
  7056. dest2 = arguments[5];
  7057. const builder = new AffineTransformationBuilder(src0, src1, src2, dest0, dest1, dest2);
  7058. return builder.getTransformation();
  7059. }
  7060. }
  7061. }
  7062. class ComponentCoordinateExtracter {
  7063. constructor() {
  7064. ComponentCoordinateExtracter.constructor_.apply(this, arguments);
  7065. }
  7066. static constructor_() {
  7067. this._coords = null;
  7068. const coords = arguments[0];
  7069. this._coords = coords;
  7070. }
  7071. static getCoordinates(geom) {
  7072. const coords = new ArrayList();
  7073. geom.apply(new ComponentCoordinateExtracter(coords));
  7074. return coords;
  7075. }
  7076. filter(geom) {
  7077. if (geom instanceof LineString || geom instanceof Point) this._coords.add(geom.getCoordinate());
  7078. }
  7079. get interfaces_() {
  7080. return [GeometryComponentFilter];
  7081. }
  7082. }
  7083. class GeometryCollectionMapper {
  7084. constructor() {
  7085. GeometryCollectionMapper.constructor_.apply(this, arguments);
  7086. }
  7087. static constructor_() {
  7088. this._mapOp = null;
  7089. const mapOp = arguments[0];
  7090. this._mapOp = mapOp;
  7091. }
  7092. static map(gc, op) {
  7093. const mapper = new GeometryCollectionMapper(op);
  7094. return mapper.map(gc);
  7095. }
  7096. map(gc) {
  7097. const mapped = new ArrayList();
  7098. for (let i = 0; i < gc.getNumGeometries(); i++) {
  7099. const g = this._mapOp.map(gc.getGeometryN(i));
  7100. if (!g.isEmpty()) mapped.add(g);
  7101. }
  7102. return gc.getFactory().createGeometryCollection(GeometryFactory.toGeometryArray(mapped));
  7103. }
  7104. }
  7105. class GeometryCombiner {
  7106. constructor() {
  7107. GeometryCombiner.constructor_.apply(this, arguments);
  7108. }
  7109. static constructor_() {
  7110. this._geomFactory = null;
  7111. this._skipEmpty = false;
  7112. this._inputGeoms = null;
  7113. const geoms = arguments[0];
  7114. this._geomFactory = GeometryCombiner.extractFactory(geoms);
  7115. this._inputGeoms = geoms;
  7116. }
  7117. static combine() {
  7118. if (arguments.length === 1) {
  7119. const geoms = arguments[0];
  7120. const combiner = new GeometryCombiner(geoms);
  7121. return combiner.combine();
  7122. } else if (arguments.length === 2) {
  7123. const g0 = arguments[0],
  7124. g1 = arguments[1];
  7125. const combiner = new GeometryCombiner(GeometryCombiner.createList(g0, g1));
  7126. return combiner.combine();
  7127. } else if (arguments.length === 3) {
  7128. const g0 = arguments[0],
  7129. g1 = arguments[1],
  7130. g2 = arguments[2];
  7131. const combiner = new GeometryCombiner(GeometryCombiner.createList(g0, g1, g2));
  7132. return combiner.combine();
  7133. }
  7134. }
  7135. static extractFactory(geoms) {
  7136. if (geoms.isEmpty()) return null;
  7137. return geoms.iterator().next().getFactory();
  7138. }
  7139. static createList() {
  7140. if (arguments.length === 2) {
  7141. const obj0 = arguments[0],
  7142. obj1 = arguments[1];
  7143. const list = new ArrayList();
  7144. list.add(obj0);
  7145. list.add(obj1);
  7146. return list;
  7147. } else if (arguments.length === 3) {
  7148. const obj0 = arguments[0],
  7149. obj1 = arguments[1],
  7150. obj2 = arguments[2];
  7151. const list = new ArrayList();
  7152. list.add(obj0);
  7153. list.add(obj1);
  7154. list.add(obj2);
  7155. return list;
  7156. }
  7157. }
  7158. extractElements(geom, elems) {
  7159. if (geom === null) return null;
  7160. for (let i = 0; i < geom.getNumGeometries(); i++) {
  7161. const elemGeom = geom.getGeometryN(i);
  7162. if (this._skipEmpty && elemGeom.isEmpty()) continue;
  7163. elems.add(elemGeom);
  7164. }
  7165. }
  7166. combine() {
  7167. const elems = new ArrayList();
  7168. for (let i = this._inputGeoms.iterator(); i.hasNext();) {
  7169. const g = i.next();
  7170. this.extractElements(g, elems);
  7171. }
  7172. if (elems.size() === 0) {
  7173. if (this._geomFactory !== null) return this._geomFactory.createGeometryCollection();
  7174. return null;
  7175. }
  7176. return this._geomFactory.buildGeometry(elems);
  7177. }
  7178. }
  7179. class GeometryEditor {
  7180. constructor() {
  7181. GeometryEditor.constructor_.apply(this, arguments);
  7182. }
  7183. static constructor_() {
  7184. this._factory = null;
  7185. this._isUserDataCopied = false;
  7186. if (arguments.length === 0) ; else if (arguments.length === 1) {
  7187. const factory = arguments[0];
  7188. this._factory = factory;
  7189. }
  7190. }
  7191. setCopyUserData(isUserDataCopied) {
  7192. this._isUserDataCopied = isUserDataCopied;
  7193. }
  7194. edit(geometry, operation) {
  7195. if (geometry === null) return null;
  7196. const result = this.editInternal(geometry, operation);
  7197. if (this._isUserDataCopied) result.setUserData(geometry.getUserData());
  7198. return result;
  7199. }
  7200. editInternal(geometry, operation) {
  7201. if (this._factory === null) this._factory = geometry.getFactory();
  7202. if (geometry instanceof GeometryCollection) return this.editGeometryCollection(geometry, operation);
  7203. if (geometry instanceof Polygon) return this.editPolygon(geometry, operation);
  7204. if (geometry instanceof Point) return operation.edit(geometry, this._factory);
  7205. if (geometry instanceof LineString) return operation.edit(geometry, this._factory);
  7206. Assert.shouldNeverReachHere('Unsupported Geometry type: ' + geometry.getGeometryType());
  7207. return null;
  7208. }
  7209. editGeometryCollection(collection, operation) {
  7210. const collectionForType = operation.edit(collection, this._factory);
  7211. const geometries = new ArrayList();
  7212. for (let i = 0; i < collectionForType.getNumGeometries(); i++) {
  7213. const geometry = this.edit(collectionForType.getGeometryN(i), operation);
  7214. if (geometry === null || geometry.isEmpty()) continue;
  7215. geometries.add(geometry);
  7216. }
  7217. if (collectionForType.getGeometryType() === Geometry.TYPENAME_MULTIPOINT) return this._factory.createMultiPoint(geometries.toArray([]));
  7218. if (collectionForType.getGeometryType() === Geometry.TYPENAME_MULTILINESTRING) return this._factory.createMultiLineString(geometries.toArray([]));
  7219. if (collectionForType.getGeometryType() === Geometry.TYPENAME_MULTIPOLYGON) return this._factory.createMultiPolygon(geometries.toArray([]));
  7220. return this._factory.createGeometryCollection(geometries.toArray([]));
  7221. }
  7222. editPolygon(polygon, operation) {
  7223. let newPolygon = operation.edit(polygon, this._factory);
  7224. if (newPolygon === null) newPolygon = this._factory.createPolygon();
  7225. if (newPolygon.isEmpty()) return newPolygon;
  7226. const shell = this.edit(newPolygon.getExteriorRing(), operation);
  7227. if (shell === null || shell.isEmpty()) return this._factory.createPolygon();
  7228. const holes = new ArrayList();
  7229. for (let i = 0; i < newPolygon.getNumInteriorRing(); i++) {
  7230. const hole = this.edit(newPolygon.getInteriorRingN(i), operation);
  7231. if (hole === null || hole.isEmpty()) continue;
  7232. holes.add(hole);
  7233. }
  7234. return this._factory.createPolygon(shell, holes.toArray([]));
  7235. }
  7236. }
  7237. function GeometryEditorOperation() {}
  7238. GeometryEditor.GeometryEditorOperation = GeometryEditorOperation;
  7239. class NoOpGeometryOperation {
  7240. edit(geometry, factory) {
  7241. return geometry;
  7242. }
  7243. get interfaces_() {
  7244. return [GeometryEditorOperation];
  7245. }
  7246. }
  7247. class CoordinateOperation {
  7248. edit(geometry, factory) {
  7249. const coordinates = this.edit(geometry.getCoordinates(), geometry);
  7250. if (geometry instanceof LinearRing) if (coordinates === null) return factory.createLinearRing();else return factory.createLinearRing(coordinates);
  7251. if (geometry instanceof LineString) if (coordinates === null) return factory.createLineString();else return factory.createLineString(coordinates);
  7252. if (geometry instanceof Point) if (coordinates === null || coordinates.length === 0) return factory.createPoint();else return factory.createPoint(coordinates[0]);
  7253. return geometry;
  7254. }
  7255. get interfaces_() {
  7256. return [GeometryEditorOperation];
  7257. }
  7258. }
  7259. class CoordinateSequenceOperation {
  7260. edit(geometry, factory) {
  7261. if (geometry instanceof LinearRing) return factory.createLinearRing(this.edit(geometry.getCoordinateSequence(), geometry));
  7262. if (geometry instanceof LineString) return factory.createLineString(this.edit(geometry.getCoordinateSequence(), geometry));
  7263. if (geometry instanceof Point) return factory.createPoint(this.edit(geometry.getCoordinateSequence(), geometry));
  7264. return geometry;
  7265. }
  7266. get interfaces_() {
  7267. return [GeometryEditorOperation];
  7268. }
  7269. }
  7270. GeometryEditor.NoOpGeometryOperation = NoOpGeometryOperation;
  7271. GeometryEditor.CoordinateOperation = CoordinateOperation;
  7272. GeometryEditor.CoordinateSequenceOperation = CoordinateSequenceOperation;
  7273. class GeometryExtracter {
  7274. constructor() {
  7275. GeometryExtracter.constructor_.apply(this, arguments);
  7276. }
  7277. static constructor_() {
  7278. this._geometryType = null;
  7279. this._comps = null;
  7280. const geometryType = arguments[0],
  7281. comps = arguments[1];
  7282. this._geometryType = geometryType;
  7283. this._comps = comps;
  7284. }
  7285. static isOfType(geom, geometryType) {
  7286. if (geom.getGeometryType() === geometryType) return true;
  7287. if (geometryType === Geometry.TYPENAME_LINESTRING && geom.getGeometryType() === Geometry.TYPENAME_LINEARRING) return true;
  7288. return false;
  7289. }
  7290. static extract() {
  7291. if (arguments.length === 2) {
  7292. const geom = arguments[0],
  7293. geometryType = arguments[1];
  7294. return GeometryExtracter.extract(geom, geometryType, new ArrayList());
  7295. } else if (arguments.length === 3) {
  7296. const geom = arguments[0],
  7297. geometryType = arguments[1],
  7298. list = arguments[2];
  7299. if (geom.getGeometryType() === geometryType) list.add(geom);else if (geom instanceof GeometryCollection) geom.apply(new GeometryExtracter(geometryType, list));
  7300. return list;
  7301. }
  7302. }
  7303. filter(geom) {
  7304. if (this._geometryType === null || GeometryExtracter.isOfType(geom, this._geometryType)) this._comps.add(geom);
  7305. }
  7306. get interfaces_() {
  7307. return [GeometryFilter];
  7308. }
  7309. }
  7310. class GeometryMapper {
  7311. static map() {
  7312. if (arguments[0] instanceof Geometry && hasInterface(arguments[1], MapOp$1)) {
  7313. const geom = arguments[0],
  7314. op = arguments[1];
  7315. const mapped = new ArrayList();
  7316. for (let i = 0; i < geom.getNumGeometries(); i++) {
  7317. const g = op.map(geom.getGeometryN(i));
  7318. if (g !== null) mapped.add(g);
  7319. }
  7320. return geom.getFactory().buildGeometry(mapped);
  7321. } else if (hasInterface(arguments[0], Collection) && hasInterface(arguments[1], MapOp$1)) {
  7322. const geoms = arguments[0],
  7323. op = arguments[1];
  7324. const mapped = new ArrayList();
  7325. for (let i = geoms.iterator(); i.hasNext();) {
  7326. const g = i.next();
  7327. const gr = op.map(g);
  7328. if (gr !== null) mapped.add(gr);
  7329. }
  7330. return mapped;
  7331. }
  7332. }
  7333. }
  7334. function MapOp$1() {}
  7335. GeometryMapper.MapOp = MapOp$1;
  7336. class GeometryTransformer {
  7337. constructor() {
  7338. GeometryTransformer.constructor_.apply(this, arguments);
  7339. }
  7340. static constructor_() {
  7341. this._inputGeom = null;
  7342. this._factory = null;
  7343. this._pruneEmptyGeometry = true;
  7344. this._preserveGeometryCollectionType = true;
  7345. this._preserveCollections = false;
  7346. this._preserveType = false;
  7347. }
  7348. transformPoint(geom, parent) {
  7349. return this._factory.createPoint(this.transformCoordinates(geom.getCoordinateSequence(), geom));
  7350. }
  7351. transformPolygon(geom, parent) {
  7352. let isAllValidLinearRings = true;
  7353. const shell = this.transformLinearRing(geom.getExteriorRing(), geom);
  7354. if (shell === null || !(shell instanceof LinearRing) || shell.isEmpty()) isAllValidLinearRings = false;
  7355. const holes = new ArrayList();
  7356. for (let i = 0; i < geom.getNumInteriorRing(); i++) {
  7357. const hole = this.transformLinearRing(geom.getInteriorRingN(i), geom);
  7358. if (hole === null || hole.isEmpty()) continue;
  7359. if (!(hole instanceof LinearRing)) isAllValidLinearRings = false;
  7360. holes.add(hole);
  7361. }
  7362. if (isAllValidLinearRings) {
  7363. return this._factory.createPolygon(shell, holes.toArray([]));
  7364. } else {
  7365. const components = new ArrayList();
  7366. if (shell !== null) components.add(shell);
  7367. components.addAll(holes);
  7368. return this._factory.buildGeometry(components);
  7369. }
  7370. }
  7371. createCoordinateSequence(coords) {
  7372. return this._factory.getCoordinateSequenceFactory().create(coords);
  7373. }
  7374. getInputGeometry() {
  7375. return this._inputGeom;
  7376. }
  7377. transformMultiLineString(geom, parent) {
  7378. const transGeomList = new ArrayList();
  7379. for (let i = 0; i < geom.getNumGeometries(); i++) {
  7380. const transformGeom = this.transformLineString(geom.getGeometryN(i), geom);
  7381. if (transformGeom === null) continue;
  7382. if (transformGeom.isEmpty()) continue;
  7383. transGeomList.add(transformGeom);
  7384. }
  7385. return this._factory.buildGeometry(transGeomList);
  7386. }
  7387. transformCoordinates(coords, parent) {
  7388. return this.copy(coords);
  7389. }
  7390. transformLineString(geom, parent) {
  7391. return this._factory.createLineString(this.transformCoordinates(geom.getCoordinateSequence(), geom));
  7392. }
  7393. transformMultiPoint(geom, parent) {
  7394. const transGeomList = new ArrayList();
  7395. for (let i = 0; i < geom.getNumGeometries(); i++) {
  7396. const transformGeom = this.transformPoint(geom.getGeometryN(i), geom);
  7397. if (transformGeom === null) continue;
  7398. if (transformGeom.isEmpty()) continue;
  7399. transGeomList.add(transformGeom);
  7400. }
  7401. return this._factory.buildGeometry(transGeomList);
  7402. }
  7403. transformMultiPolygon(geom, parent) {
  7404. const transGeomList = new ArrayList();
  7405. for (let i = 0; i < geom.getNumGeometries(); i++) {
  7406. const transformGeom = this.transformPolygon(geom.getGeometryN(i), geom);
  7407. if (transformGeom === null) continue;
  7408. if (transformGeom.isEmpty()) continue;
  7409. transGeomList.add(transformGeom);
  7410. }
  7411. return this._factory.buildGeometry(transGeomList);
  7412. }
  7413. copy(seq) {
  7414. return seq.copy();
  7415. }
  7416. transformGeometryCollection(geom, parent) {
  7417. const transGeomList = new ArrayList();
  7418. for (let i = 0; i < geom.getNumGeometries(); i++) {
  7419. const transformGeom = this.transform(geom.getGeometryN(i));
  7420. if (transformGeom === null) continue;
  7421. if (this._pruneEmptyGeometry && transformGeom.isEmpty()) continue;
  7422. transGeomList.add(transformGeom);
  7423. }
  7424. if (this._preserveGeometryCollectionType) return this._factory.createGeometryCollection(GeometryFactory.toGeometryArray(transGeomList));
  7425. return this._factory.buildGeometry(transGeomList);
  7426. }
  7427. transform(inputGeom) {
  7428. this._inputGeom = inputGeom;
  7429. this._factory = inputGeom.getFactory();
  7430. if (inputGeom instanceof Point) return this.transformPoint(inputGeom, null);
  7431. if (inputGeom instanceof MultiPoint) return this.transformMultiPoint(inputGeom, null);
  7432. if (inputGeom instanceof LinearRing) return this.transformLinearRing(inputGeom, null);
  7433. if (inputGeom instanceof LineString) return this.transformLineString(inputGeom, null);
  7434. if (inputGeom instanceof MultiLineString) return this.transformMultiLineString(inputGeom, null);
  7435. if (inputGeom instanceof Polygon) return this.transformPolygon(inputGeom, null);
  7436. if (inputGeom instanceof MultiPolygon) return this.transformMultiPolygon(inputGeom, null);
  7437. if (inputGeom instanceof GeometryCollection) return this.transformGeometryCollection(inputGeom, null);
  7438. throw new IllegalArgumentException('Unknown Geometry subtype: ' + inputGeom.getGeometryType());
  7439. }
  7440. transformLinearRing(geom, parent) {
  7441. const seq = this.transformCoordinates(geom.getCoordinateSequence(), geom);
  7442. if (seq === null) return this._factory.createLinearRing(null);
  7443. const seqSize = seq.size();
  7444. if (seqSize > 0 && seqSize < 4 && !this._preserveType) return this._factory.createLineString(seq);
  7445. return this._factory.createLinearRing(seq);
  7446. }
  7447. }
  7448. class LineStringExtracter {
  7449. constructor() {
  7450. LineStringExtracter.constructor_.apply(this, arguments);
  7451. }
  7452. static constructor_() {
  7453. this._comps = null;
  7454. const comps = arguments[0];
  7455. this._comps = comps;
  7456. }
  7457. static getGeometry(geom) {
  7458. return geom.getFactory().buildGeometry(LineStringExtracter.getLines(geom));
  7459. }
  7460. static getLines() {
  7461. if (arguments.length === 1) {
  7462. const geom = arguments[0];
  7463. return LineStringExtracter.getLines(geom, new ArrayList());
  7464. } else if (arguments.length === 2) {
  7465. const geom = arguments[0],
  7466. lines = arguments[1];
  7467. if (geom instanceof LineString) lines.add(geom);else if (geom instanceof GeometryCollection) geom.apply(new LineStringExtracter(lines));
  7468. return lines;
  7469. }
  7470. }
  7471. filter(geom) {
  7472. if (geom instanceof LineString) this._comps.add(geom);
  7473. }
  7474. get interfaces_() {
  7475. return [GeometryFilter];
  7476. }
  7477. }
  7478. class LinearComponentExtracter {
  7479. constructor() {
  7480. LinearComponentExtracter.constructor_.apply(this, arguments);
  7481. }
  7482. static constructor_() {
  7483. this._lines = null;
  7484. this._isForcedToLineString = false;
  7485. if (arguments.length === 1) {
  7486. const lines = arguments[0];
  7487. this._lines = lines;
  7488. } else if (arguments.length === 2) {
  7489. const lines = arguments[0],
  7490. isForcedToLineString = arguments[1];
  7491. this._lines = lines;
  7492. this._isForcedToLineString = isForcedToLineString;
  7493. }
  7494. }
  7495. static getGeometry() {
  7496. if (arguments.length === 1) {
  7497. const geom = arguments[0];
  7498. return geom.getFactory().buildGeometry(LinearComponentExtracter.getLines(geom));
  7499. } else if (arguments.length === 2) {
  7500. const geom = arguments[0],
  7501. forceToLineString = arguments[1];
  7502. return geom.getFactory().buildGeometry(LinearComponentExtracter.getLines(geom, forceToLineString));
  7503. }
  7504. }
  7505. static getLines() {
  7506. if (arguments.length === 1) {
  7507. const geom = arguments[0];
  7508. return LinearComponentExtracter.getLines(geom, false);
  7509. } else if (arguments.length === 2) {
  7510. if (hasInterface(arguments[0], Collection) && hasInterface(arguments[1], Collection)) {
  7511. const geoms = arguments[0],
  7512. lines = arguments[1];
  7513. for (let i = geoms.iterator(); i.hasNext();) {
  7514. const g = i.next();
  7515. LinearComponentExtracter.getLines(g, lines);
  7516. }
  7517. return lines;
  7518. } else if (arguments[0] instanceof Geometry && typeof arguments[1] === 'boolean') {
  7519. const geom = arguments[0],
  7520. forceToLineString = arguments[1];
  7521. const lines = new ArrayList();
  7522. geom.apply(new LinearComponentExtracter(lines, forceToLineString));
  7523. return lines;
  7524. } else if (arguments[0] instanceof Geometry && hasInterface(arguments[1], Collection)) {
  7525. const geom = arguments[0],
  7526. lines = arguments[1];
  7527. if (geom instanceof LineString) lines.add(geom);else geom.apply(new LinearComponentExtracter(lines));
  7528. return lines;
  7529. }
  7530. } else if (arguments.length === 3) {
  7531. if (typeof arguments[2] === 'boolean' && hasInterface(arguments[0], Collection) && hasInterface(arguments[1], Collection)) {
  7532. const geoms = arguments[0],
  7533. lines = arguments[1],
  7534. forceToLineString = arguments[2];
  7535. for (let i = geoms.iterator(); i.hasNext();) {
  7536. const g = i.next();
  7537. LinearComponentExtracter.getLines(g, lines, forceToLineString);
  7538. }
  7539. return lines;
  7540. } else if (typeof arguments[2] === 'boolean' && arguments[0] instanceof Geometry && hasInterface(arguments[1], Collection)) {
  7541. const geom = arguments[0],
  7542. lines = arguments[1],
  7543. forceToLineString = arguments[2];
  7544. geom.apply(new LinearComponentExtracter(lines, forceToLineString));
  7545. return lines;
  7546. }
  7547. }
  7548. }
  7549. filter(geom) {
  7550. if (this._isForcedToLineString && geom instanceof LinearRing) {
  7551. const line = geom.getFactory().createLineString(geom.getCoordinateSequence());
  7552. this._lines.add(line);
  7553. return null;
  7554. }
  7555. if (geom instanceof LineString) this._lines.add(geom);
  7556. }
  7557. setForceToLineString(isForcedToLineString) {
  7558. this._isForcedToLineString = isForcedToLineString;
  7559. }
  7560. get interfaces_() {
  7561. return [GeometryComponentFilter];
  7562. }
  7563. }
  7564. const Collections = {
  7565. reverseOrder: function () {
  7566. return {
  7567. compare(a, b) {
  7568. return b.compareTo(a);
  7569. }
  7570. };
  7571. },
  7572. min: function (l) {
  7573. Collections.sort(l);
  7574. return l.get(0);
  7575. },
  7576. sort: function (l, c) {
  7577. const a = l.toArray();
  7578. if (c) Arrays.sort(a, c);else Arrays.sort(a);
  7579. const i = l.iterator();
  7580. for (let pos = 0, alen = a.length; pos < alen; pos++) {
  7581. i.next();
  7582. i.set(a[pos]);
  7583. }
  7584. },
  7585. singletonList: function (o) {
  7586. const arrayList = new ArrayList();
  7587. arrayList.add(o);
  7588. return arrayList;
  7589. }
  7590. };
  7591. class PointExtracter {
  7592. constructor() {
  7593. PointExtracter.constructor_.apply(this, arguments);
  7594. }
  7595. static constructor_() {
  7596. this._pts = null;
  7597. const pts = arguments[0];
  7598. this._pts = pts;
  7599. }
  7600. static getPoints() {
  7601. if (arguments.length === 1) {
  7602. const geom = arguments[0];
  7603. if (geom instanceof Point) return Collections.singletonList(geom);
  7604. return PointExtracter.getPoints(geom, new ArrayList());
  7605. } else if (arguments.length === 2) {
  7606. const geom = arguments[0],
  7607. list = arguments[1];
  7608. if (geom instanceof Point) list.add(geom);else if (geom instanceof GeometryCollection) geom.apply(new PointExtracter(list));
  7609. return list;
  7610. }
  7611. }
  7612. filter(geom) {
  7613. if (geom instanceof Point) this._pts.add(geom);
  7614. }
  7615. get interfaces_() {
  7616. return [GeometryFilter];
  7617. }
  7618. }
  7619. class PolygonExtracter {
  7620. constructor() {
  7621. PolygonExtracter.constructor_.apply(this, arguments);
  7622. }
  7623. static constructor_() {
  7624. this._comps = null;
  7625. const comps = arguments[0];
  7626. this._comps = comps;
  7627. }
  7628. static getPolygons() {
  7629. if (arguments.length === 1) {
  7630. const geom = arguments[0];
  7631. return PolygonExtracter.getPolygons(geom, new ArrayList());
  7632. } else if (arguments.length === 2) {
  7633. const geom = arguments[0],
  7634. list = arguments[1];
  7635. if (geom instanceof Polygon) list.add(geom);else if (geom instanceof GeometryCollection) geom.apply(new PolygonExtracter(list));
  7636. return list;
  7637. }
  7638. }
  7639. filter(geom) {
  7640. if (geom instanceof Polygon) this._comps.add(geom);
  7641. }
  7642. get interfaces_() {
  7643. return [GeometryFilter];
  7644. }
  7645. }
  7646. class ShortCircuitedGeometryVisitor {
  7647. constructor() {
  7648. ShortCircuitedGeometryVisitor.constructor_.apply(this, arguments);
  7649. }
  7650. static constructor_() {
  7651. this._isDone = false;
  7652. }
  7653. applyTo(geom) {
  7654. for (let i = 0; i < geom.getNumGeometries() && !this._isDone; i++) {
  7655. const element = geom.getGeometryN(i);
  7656. if (!(element instanceof GeometryCollection)) {
  7657. this.visit(element);
  7658. if (this.isDone()) {
  7659. this._isDone = true;
  7660. return null;
  7661. }
  7662. } else {
  7663. this.applyTo(element);
  7664. }
  7665. }
  7666. }
  7667. }
  7668. class GeometricShapeFactory {
  7669. constructor() {
  7670. GeometricShapeFactory.constructor_.apply(this, arguments);
  7671. }
  7672. static constructor_() {
  7673. this._geomFact = null;
  7674. this._precModel = null;
  7675. this._dim = new Dimensions();
  7676. this._nPts = 100;
  7677. this._rotationAngle = 0.0;
  7678. if (arguments.length === 0) {
  7679. GeometricShapeFactory.constructor_.call(this, new GeometryFactory());
  7680. } else if (arguments.length === 1) {
  7681. const geomFact = arguments[0];
  7682. this._geomFact = geomFact;
  7683. this._precModel = geomFact.getPrecisionModel();
  7684. }
  7685. }
  7686. createSupercircle(power) {
  7687. const recipPow = 1.0 / power;
  7688. const radius = this._dim.getMinSize() / 2;
  7689. const centre = this._dim.getCentre();
  7690. const r4 = Math.pow(radius, power);
  7691. const y0 = radius;
  7692. const xyInt = Math.pow(r4 / 2, recipPow);
  7693. const nSegsInOct = Math.trunc(this._nPts / 8);
  7694. const totPts = nSegsInOct * 8 + 1;
  7695. const pts = new Array(totPts).fill(null);
  7696. const xInc = xyInt / nSegsInOct;
  7697. for (let i = 0; i <= nSegsInOct; i++) {
  7698. let x = 0.0;
  7699. let y = y0;
  7700. if (i !== 0) {
  7701. x = xInc * i;
  7702. const x4 = Math.pow(x, power);
  7703. y = Math.pow(r4 - x4, recipPow);
  7704. }
  7705. pts[i] = this.coordTrans(x, y, centre);
  7706. pts[2 * nSegsInOct - i] = this.coordTrans(y, x, centre);
  7707. pts[2 * nSegsInOct + i] = this.coordTrans(y, -x, centre);
  7708. pts[4 * nSegsInOct - i] = this.coordTrans(x, -y, centre);
  7709. pts[4 * nSegsInOct + i] = this.coordTrans(-x, -y, centre);
  7710. pts[6 * nSegsInOct - i] = this.coordTrans(-y, -x, centre);
  7711. pts[6 * nSegsInOct + i] = this.coordTrans(-y, x, centre);
  7712. pts[8 * nSegsInOct - i] = this.coordTrans(-x, y, centre);
  7713. }
  7714. pts[pts.length - 1] = new Coordinate(pts[0]);
  7715. const ring = this._geomFact.createLinearRing(pts);
  7716. const poly = this._geomFact.createPolygon(ring);
  7717. return this.rotate(poly);
  7718. }
  7719. setNumPoints(nPts) {
  7720. this._nPts = nPts;
  7721. }
  7722. setBase(base) {
  7723. this._dim.setBase(base);
  7724. }
  7725. setRotation(radians) {
  7726. this._rotationAngle = radians;
  7727. }
  7728. setWidth(width) {
  7729. this._dim.setWidth(width);
  7730. }
  7731. createEllipse() {
  7732. const env = this._dim.getEnvelope();
  7733. const xRadius = env.getWidth() / 2.0;
  7734. const yRadius = env.getHeight() / 2.0;
  7735. const centreX = env.getMinX() + xRadius;
  7736. const centreY = env.getMinY() + yRadius;
  7737. const pts = new Array(this._nPts + 1).fill(null);
  7738. let iPt = 0;
  7739. for (let i = 0; i < this._nPts; i++) {
  7740. const ang = i * (2 * Math.PI / this._nPts);
  7741. const x = xRadius * Math.cos(ang) + centreX;
  7742. const y = yRadius * Math.sin(ang) + centreY;
  7743. pts[iPt++] = this.coord(x, y);
  7744. }
  7745. pts[iPt] = new Coordinate(pts[0]);
  7746. const ring = this._geomFact.createLinearRing(pts);
  7747. const poly = this._geomFact.createPolygon(ring);
  7748. return this.rotate(poly);
  7749. }
  7750. coordTrans(x, y, trans) {
  7751. return this.coord(x + trans.x, y + trans.y);
  7752. }
  7753. createSquircle() {
  7754. return this.createSupercircle(4);
  7755. }
  7756. setEnvelope(env) {
  7757. this._dim.setEnvelope(env);
  7758. }
  7759. setCentre(centre) {
  7760. this._dim.setCentre(centre);
  7761. }
  7762. createArc(startAng, angExtent) {
  7763. const env = this._dim.getEnvelope();
  7764. const xRadius = env.getWidth() / 2.0;
  7765. const yRadius = env.getHeight() / 2.0;
  7766. const centreX = env.getMinX() + xRadius;
  7767. const centreY = env.getMinY() + yRadius;
  7768. let angSize = angExtent;
  7769. if (angSize <= 0.0 || angSize > 2 * Math.PI) angSize = 2 * Math.PI;
  7770. const angInc = angSize / (this._nPts - 1);
  7771. const pts = new Array(this._nPts).fill(null);
  7772. let iPt = 0;
  7773. for (let i = 0; i < this._nPts; i++) {
  7774. const ang = startAng + i * angInc;
  7775. const x = xRadius * Math.cos(ang) + centreX;
  7776. const y = yRadius * Math.sin(ang) + centreY;
  7777. pts[iPt++] = this.coord(x, y);
  7778. }
  7779. const line = this._geomFact.createLineString(pts);
  7780. return this.rotate(line);
  7781. }
  7782. rotate(geom) {
  7783. if (this._rotationAngle !== 0.0) {
  7784. const trans = AffineTransformation.rotationInstance(this._rotationAngle, this._dim.getCentre().x, this._dim.getCentre().y);
  7785. geom.apply(trans);
  7786. }
  7787. return geom;
  7788. }
  7789. coord(x, y) {
  7790. const pt = new Coordinate(x, y);
  7791. this._precModel.makePrecise(pt);
  7792. return pt;
  7793. }
  7794. createArcPolygon(startAng, angExtent) {
  7795. const env = this._dim.getEnvelope();
  7796. const xRadius = env.getWidth() / 2.0;
  7797. const yRadius = env.getHeight() / 2.0;
  7798. const centreX = env.getMinX() + xRadius;
  7799. const centreY = env.getMinY() + yRadius;
  7800. let angSize = angExtent;
  7801. if (angSize <= 0.0 || angSize > 2 * Math.PI) angSize = 2 * Math.PI;
  7802. const angInc = angSize / (this._nPts - 1);
  7803. const pts = new Array(this._nPts + 2).fill(null);
  7804. let iPt = 0;
  7805. pts[iPt++] = this.coord(centreX, centreY);
  7806. for (let i = 0; i < this._nPts; i++) {
  7807. const ang = startAng + angInc * i;
  7808. const x = xRadius * Math.cos(ang) + centreX;
  7809. const y = yRadius * Math.sin(ang) + centreY;
  7810. pts[iPt++] = this.coord(x, y);
  7811. }
  7812. pts[iPt++] = this.coord(centreX, centreY);
  7813. const ring = this._geomFact.createLinearRing(pts);
  7814. const poly = this._geomFact.createPolygon(ring);
  7815. return this.rotate(poly);
  7816. }
  7817. createRectangle() {
  7818. let i = null;
  7819. let ipt = 0;
  7820. let nSide = Math.trunc(this._nPts / 4);
  7821. if (nSide < 1) nSide = 1;
  7822. const XsegLen = this._dim.getEnvelope().getWidth() / nSide;
  7823. const YsegLen = this._dim.getEnvelope().getHeight() / nSide;
  7824. const pts = new Array(4 * nSide + 1).fill(null);
  7825. const env = this._dim.getEnvelope();
  7826. for (i = 0; i < nSide; i++) {
  7827. const x = env.getMinX() + i * XsegLen;
  7828. const y = env.getMinY();
  7829. pts[ipt++] = this.coord(x, y);
  7830. }
  7831. for (i = 0; i < nSide; i++) {
  7832. const x = env.getMaxX();
  7833. const y = env.getMinY() + i * YsegLen;
  7834. pts[ipt++] = this.coord(x, y);
  7835. }
  7836. for (i = 0; i < nSide; i++) {
  7837. const x = env.getMaxX() - i * XsegLen;
  7838. const y = env.getMaxY();
  7839. pts[ipt++] = this.coord(x, y);
  7840. }
  7841. for (i = 0; i < nSide; i++) {
  7842. const x = env.getMinX();
  7843. const y = env.getMaxY() - i * YsegLen;
  7844. pts[ipt++] = this.coord(x, y);
  7845. }
  7846. pts[ipt++] = new Coordinate(pts[0]);
  7847. const ring = this._geomFact.createLinearRing(pts);
  7848. const poly = this._geomFact.createPolygon(ring);
  7849. return this.rotate(poly);
  7850. }
  7851. createCircle() {
  7852. return this.createEllipse();
  7853. }
  7854. setHeight(height) {
  7855. this._dim.setHeight(height);
  7856. }
  7857. setSize(size) {
  7858. this._dim.setSize(size);
  7859. }
  7860. }
  7861. class Dimensions {
  7862. constructor() {
  7863. Dimensions.constructor_.apply(this, arguments);
  7864. }
  7865. static constructor_() {
  7866. this.base = null;
  7867. this.centre = null;
  7868. this.width = null;
  7869. this.height = null;
  7870. }
  7871. setBase(base) {
  7872. this.base = base;
  7873. }
  7874. setWidth(width) {
  7875. this.width = width;
  7876. }
  7877. getBase() {
  7878. return this.base;
  7879. }
  7880. getWidth() {
  7881. return this.width;
  7882. }
  7883. setEnvelope(env) {
  7884. this.width = env.getWidth();
  7885. this.height = env.getHeight();
  7886. this.base = new Coordinate(env.getMinX(), env.getMinY());
  7887. this.centre = new Coordinate(env.centre());
  7888. }
  7889. setCentre(centre) {
  7890. this.centre = centre;
  7891. }
  7892. getMinSize() {
  7893. return Math.min(this.width, this.height);
  7894. }
  7895. getEnvelope() {
  7896. if (this.base !== null) return new Envelope(this.base.x, this.base.x + this.width, this.base.y, this.base.y + this.height);
  7897. if (this.centre !== null) return new Envelope(this.centre.x - this.width / 2, this.centre.x + this.width / 2, this.centre.y - this.height / 2, this.centre.y + this.height / 2);
  7898. return new Envelope(0, this.width, 0, this.height);
  7899. }
  7900. getCentre() {
  7901. if (this.centre === null) this.centre = new Coordinate(this.base.x + this.width / 2, this.base.y + this.height / 2);
  7902. return this.centre;
  7903. }
  7904. getHeight() {
  7905. return this.height;
  7906. }
  7907. setHeight(height) {
  7908. this.height = height;
  7909. }
  7910. setSize(size) {
  7911. this.height = size;
  7912. this.width = size;
  7913. }
  7914. }
  7915. GeometricShapeFactory.Dimensions = Dimensions;
  7916. class SineStarFactory extends GeometricShapeFactory {
  7917. constructor() {
  7918. super();
  7919. SineStarFactory.constructor_.apply(this, arguments);
  7920. }
  7921. static constructor_() {
  7922. this._numArms = 8;
  7923. this._armLengthRatio = 0.5;
  7924. if (arguments.length === 0) {
  7925. GeometricShapeFactory.constructor_.call(this);
  7926. } else if (arguments.length === 1) {
  7927. const geomFact = arguments[0];
  7928. GeometricShapeFactory.constructor_.call(this, geomFact);
  7929. }
  7930. }
  7931. static create(origin, size, nPts, nArms, armLengthRatio) {
  7932. const gsf = new SineStarFactory();
  7933. gsf.setCentre(origin);
  7934. gsf.setSize(size);
  7935. gsf.setNumPoints(nPts);
  7936. gsf.setArmLengthRatio(armLengthRatio);
  7937. gsf.setNumArms(nArms);
  7938. const poly = gsf.createSineStar();
  7939. return poly;
  7940. }
  7941. setNumArms(numArms) {
  7942. this._numArms = numArms;
  7943. }
  7944. setArmLengthRatio(armLengthRatio) {
  7945. this._armLengthRatio = armLengthRatio;
  7946. }
  7947. createSineStar() {
  7948. const env = this._dim.getEnvelope();
  7949. const radius = env.getWidth() / 2.0;
  7950. let armRatio = this._armLengthRatio;
  7951. if (armRatio < 0.0) armRatio = 0.0;
  7952. if (armRatio > 1.0) armRatio = 1.0;
  7953. const armMaxLen = armRatio * radius;
  7954. const insideRadius = (1 - armRatio) * radius;
  7955. const centreX = env.getMinX() + radius;
  7956. const centreY = env.getMinY() + radius;
  7957. const pts = new Array(this._nPts + 1).fill(null);
  7958. let iPt = 0;
  7959. for (let i = 0; i < this._nPts; i++) {
  7960. const ptArcFrac = i / this._nPts * this._numArms;
  7961. const armAngFrac = ptArcFrac - Math.floor(ptArcFrac);
  7962. const armAng = 2 * Math.PI * armAngFrac;
  7963. const armLenFrac = (Math.cos(armAng) + 1.0) / 2.0;
  7964. const curveRadius = insideRadius + armMaxLen * armLenFrac;
  7965. const ang = i * (2 * Math.PI / this._nPts);
  7966. const x = curveRadius * Math.cos(ang) + centreX;
  7967. const y = curveRadius * Math.sin(ang) + centreY;
  7968. pts[iPt++] = this.coord(x, y);
  7969. }
  7970. pts[iPt] = new Coordinate(pts[0]);
  7971. const ring = this._geomFact.createLinearRing(pts);
  7972. const poly = this._geomFact.createPolygon(ring);
  7973. return poly;
  7974. }
  7975. }
  7976. var util$1 = /*#__PURE__*/Object.freeze({
  7977. __proto__: null,
  7978. AffineTransformation: AffineTransformation,
  7979. AffineTransformationBuilder: AffineTransformationBuilder,
  7980. AffineTransformationFactory: AffineTransformationFactory,
  7981. ComponentCoordinateExtracter: ComponentCoordinateExtracter,
  7982. GeometryCollectionMapper: GeometryCollectionMapper,
  7983. GeometryCombiner: GeometryCombiner,
  7984. GeometryEditor: GeometryEditor,
  7985. GeometryExtracter: GeometryExtracter,
  7986. GeometryMapper: GeometryMapper,
  7987. GeometryTransformer: GeometryTransformer,
  7988. LineStringExtracter: LineStringExtracter,
  7989. LinearComponentExtracter: LinearComponentExtracter,
  7990. PointExtracter: PointExtracter,
  7991. PolygonExtracter: PolygonExtracter,
  7992. ShortCircuitedGeometryVisitor: ShortCircuitedGeometryVisitor,
  7993. SineStarFactory: SineStarFactory
  7994. });
  7995. var geom = /*#__PURE__*/Object.freeze({
  7996. __proto__: null,
  7997. Coordinate: Coordinate,
  7998. CoordinateXY: CoordinateXY,
  7999. CoordinateXYM: CoordinateXYM,
  8000. CoordinateXYZM: CoordinateXYZM,
  8001. CoordinateList: CoordinateList,
  8002. CoordinateSequenceFilter: CoordinateSequenceFilter,
  8003. Envelope: Envelope,
  8004. LineSegment: LineSegment,
  8005. GeometryFactory: GeometryFactory,
  8006. Geometry: Geometry,
  8007. Point: Point,
  8008. LineString: LineString,
  8009. LinearRing: LinearRing,
  8010. Polygon: Polygon,
  8011. GeometryCollection: GeometryCollection,
  8012. MultiPoint: MultiPoint,
  8013. MultiLineString: MultiLineString,
  8014. MultiPolygon: MultiPolygon,
  8015. Dimension: Dimension,
  8016. IntersectionMatrix: IntersectionMatrix,
  8017. PrecisionModel: PrecisionModel,
  8018. Location: Location,
  8019. Triangle: Triangle,
  8020. util: util$1
  8021. });
  8022. class PointPairDistance {
  8023. constructor() {
  8024. PointPairDistance.constructor_.apply(this, arguments);
  8025. }
  8026. static constructor_() {
  8027. this._pt = [new Coordinate(), new Coordinate()];
  8028. this._distance = Double.NaN;
  8029. this._isNull = true;
  8030. }
  8031. getCoordinates() {
  8032. return this._pt;
  8033. }
  8034. getCoordinate(i) {
  8035. return this._pt[i];
  8036. }
  8037. setMinimum() {
  8038. if (arguments.length === 1) {
  8039. const ptDist = arguments[0];
  8040. this.setMinimum(ptDist._pt[0], ptDist._pt[1]);
  8041. } else if (arguments.length === 2) {
  8042. const p0 = arguments[0],
  8043. p1 = arguments[1];
  8044. if (this._isNull) {
  8045. this.initialize(p0, p1);
  8046. return null;
  8047. }
  8048. const dist = p0.distance(p1);
  8049. if (dist < this._distance) this.initialize(p0, p1, dist);
  8050. }
  8051. }
  8052. initialize() {
  8053. if (arguments.length === 0) {
  8054. this._isNull = true;
  8055. } else if (arguments.length === 2) {
  8056. const p0 = arguments[0],
  8057. p1 = arguments[1];
  8058. this._pt[0].setCoordinate(p0);
  8059. this._pt[1].setCoordinate(p1);
  8060. this._distance = p0.distance(p1);
  8061. this._isNull = false;
  8062. } else if (arguments.length === 3) {
  8063. const p0 = arguments[0],
  8064. p1 = arguments[1],
  8065. distance = arguments[2];
  8066. this._pt[0].setCoordinate(p0);
  8067. this._pt[1].setCoordinate(p1);
  8068. this._distance = distance;
  8069. this._isNull = false;
  8070. }
  8071. }
  8072. toString() {
  8073. return WKTWriter.toLineString(this._pt[0], this._pt[1]);
  8074. }
  8075. getDistance() {
  8076. return this._distance;
  8077. }
  8078. setMaximum() {
  8079. if (arguments.length === 1) {
  8080. const ptDist = arguments[0];
  8081. this.setMaximum(ptDist._pt[0], ptDist._pt[1]);
  8082. } else if (arguments.length === 2) {
  8083. const p0 = arguments[0],
  8084. p1 = arguments[1];
  8085. if (this._isNull) {
  8086. this.initialize(p0, p1);
  8087. return null;
  8088. }
  8089. const dist = p0.distance(p1);
  8090. if (dist > this._distance) this.initialize(p0, p1, dist);
  8091. }
  8092. }
  8093. }
  8094. class DistanceToPoint {
  8095. static computeDistance() {
  8096. if (arguments[2] instanceof PointPairDistance && arguments[0] instanceof LineString && arguments[1] instanceof Coordinate) {
  8097. const line = arguments[0],
  8098. pt = arguments[1],
  8099. ptDist = arguments[2];
  8100. const tempSegment = new LineSegment();
  8101. const coords = line.getCoordinates();
  8102. for (let i = 0; i < coords.length - 1; i++) {
  8103. tempSegment.setCoordinates(coords[i], coords[i + 1]);
  8104. const closestPt = tempSegment.closestPoint(pt);
  8105. ptDist.setMinimum(closestPt, pt);
  8106. }
  8107. } else if (arguments[2] instanceof PointPairDistance && arguments[0] instanceof Polygon && arguments[1] instanceof Coordinate) {
  8108. const poly = arguments[0],
  8109. pt = arguments[1],
  8110. ptDist = arguments[2];
  8111. DistanceToPoint.computeDistance(poly.getExteriorRing(), pt, ptDist);
  8112. for (let i = 0; i < poly.getNumInteriorRing(); i++) DistanceToPoint.computeDistance(poly.getInteriorRingN(i), pt, ptDist);
  8113. } else if (arguments[2] instanceof PointPairDistance && arguments[0] instanceof Geometry && arguments[1] instanceof Coordinate) {
  8114. const geom = arguments[0],
  8115. pt = arguments[1],
  8116. ptDist = arguments[2];
  8117. if (geom instanceof LineString) {
  8118. DistanceToPoint.computeDistance(geom, pt, ptDist);
  8119. } else if (geom instanceof Polygon) {
  8120. DistanceToPoint.computeDistance(geom, pt, ptDist);
  8121. } else if (geom instanceof GeometryCollection) {
  8122. const gc = geom;
  8123. for (let i = 0; i < gc.getNumGeometries(); i++) {
  8124. const g = gc.getGeometryN(i);
  8125. DistanceToPoint.computeDistance(g, pt, ptDist);
  8126. }
  8127. } else {
  8128. ptDist.setMinimum(geom.getCoordinate(), pt);
  8129. }
  8130. } else if (arguments[2] instanceof PointPairDistance && arguments[0] instanceof LineSegment && arguments[1] instanceof Coordinate) {
  8131. const segment = arguments[0],
  8132. pt = arguments[1],
  8133. ptDist = arguments[2];
  8134. const closestPt = segment.closestPoint(pt);
  8135. ptDist.setMinimum(closestPt, pt);
  8136. }
  8137. }
  8138. }
  8139. class DiscreteHausdorffDistance {
  8140. constructor() {
  8141. DiscreteHausdorffDistance.constructor_.apply(this, arguments);
  8142. }
  8143. static constructor_() {
  8144. this._g0 = null;
  8145. this._g1 = null;
  8146. this._ptDist = new PointPairDistance();
  8147. this._densifyFrac = 0.0;
  8148. const g0 = arguments[0],
  8149. g1 = arguments[1];
  8150. this._g0 = g0;
  8151. this._g1 = g1;
  8152. }
  8153. static distance() {
  8154. if (arguments.length === 2) {
  8155. const g0 = arguments[0],
  8156. g1 = arguments[1];
  8157. const dist = new DiscreteHausdorffDistance(g0, g1);
  8158. return dist.distance();
  8159. } else if (arguments.length === 3) {
  8160. const g0 = arguments[0],
  8161. g1 = arguments[1],
  8162. densifyFrac = arguments[2];
  8163. const dist = new DiscreteHausdorffDistance(g0, g1);
  8164. dist.setDensifyFraction(densifyFrac);
  8165. return dist.distance();
  8166. }
  8167. }
  8168. getCoordinates() {
  8169. return this._ptDist.getCoordinates();
  8170. }
  8171. setDensifyFraction(densifyFrac) {
  8172. if (densifyFrac > 1.0 || densifyFrac <= 0.0) throw new IllegalArgumentException('Fraction is not in range (0.0 - 1.0]');
  8173. this._densifyFrac = densifyFrac;
  8174. }
  8175. compute(g0, g1) {
  8176. this.computeOrientedDistance(g0, g1, this._ptDist);
  8177. this.computeOrientedDistance(g1, g0, this._ptDist);
  8178. }
  8179. distance() {
  8180. this.compute(this._g0, this._g1);
  8181. return this._ptDist.getDistance();
  8182. }
  8183. computeOrientedDistance(discreteGeom, geom, ptDist) {
  8184. const distFilter = new MaxPointDistanceFilter(geom);
  8185. discreteGeom.apply(distFilter);
  8186. ptDist.setMaximum(distFilter.getMaxPointDistance());
  8187. if (this._densifyFrac > 0) {
  8188. const fracFilter = new MaxDensifiedByFractionDistanceFilter(geom, this._densifyFrac);
  8189. discreteGeom.apply(fracFilter);
  8190. ptDist.setMaximum(fracFilter.getMaxPointDistance());
  8191. }
  8192. }
  8193. orientedDistance() {
  8194. this.computeOrientedDistance(this._g0, this._g1, this._ptDist);
  8195. return this._ptDist.getDistance();
  8196. }
  8197. }
  8198. class MaxPointDistanceFilter {
  8199. constructor() {
  8200. MaxPointDistanceFilter.constructor_.apply(this, arguments);
  8201. }
  8202. static constructor_() {
  8203. this._maxPtDist = new PointPairDistance();
  8204. this._minPtDist = new PointPairDistance();
  8205. this._euclideanDist = new DistanceToPoint();
  8206. this._geom = null;
  8207. const geom = arguments[0];
  8208. this._geom = geom;
  8209. }
  8210. filter(pt) {
  8211. this._minPtDist.initialize();
  8212. DistanceToPoint.computeDistance(this._geom, pt, this._minPtDist);
  8213. this._maxPtDist.setMaximum(this._minPtDist);
  8214. }
  8215. getMaxPointDistance() {
  8216. return this._maxPtDist;
  8217. }
  8218. get interfaces_() {
  8219. return [CoordinateFilter];
  8220. }
  8221. }
  8222. class MaxDensifiedByFractionDistanceFilter {
  8223. constructor() {
  8224. MaxDensifiedByFractionDistanceFilter.constructor_.apply(this, arguments);
  8225. }
  8226. static constructor_() {
  8227. this._maxPtDist = new PointPairDistance();
  8228. this._minPtDist = new PointPairDistance();
  8229. this._geom = null;
  8230. this._numSubSegs = 0;
  8231. const geom = arguments[0],
  8232. fraction = arguments[1];
  8233. this._geom = geom;
  8234. this._numSubSegs = Math.trunc(Math.round(1.0 / fraction));
  8235. }
  8236. filter(seq, index) {
  8237. if (index === 0) return null;
  8238. const p0 = seq.getCoordinate(index - 1);
  8239. const p1 = seq.getCoordinate(index);
  8240. const delx = (p1.x - p0.x) / this._numSubSegs;
  8241. const dely = (p1.y - p0.y) / this._numSubSegs;
  8242. for (let i = 0; i < this._numSubSegs; i++) {
  8243. const x = p0.x + i * delx;
  8244. const y = p0.y + i * dely;
  8245. const pt = new Coordinate(x, y);
  8246. this._minPtDist.initialize();
  8247. DistanceToPoint.computeDistance(this._geom, pt, this._minPtDist);
  8248. this._maxPtDist.setMaximum(this._minPtDist);
  8249. }
  8250. }
  8251. isDone() {
  8252. return false;
  8253. }
  8254. isGeometryChanged() {
  8255. return false;
  8256. }
  8257. getMaxPointDistance() {
  8258. return this._maxPtDist;
  8259. }
  8260. get interfaces_() {
  8261. return [CoordinateSequenceFilter];
  8262. }
  8263. }
  8264. DiscreteHausdorffDistance.MaxPointDistanceFilter = MaxPointDistanceFilter;
  8265. DiscreteHausdorffDistance.MaxDensifiedByFractionDistanceFilter = MaxDensifiedByFractionDistanceFilter;
  8266. var distance_module = /*#__PURE__*/Object.freeze({
  8267. __proto__: null,
  8268. DiscreteHausdorffDistance: DiscreteHausdorffDistance,
  8269. DistanceToPoint: DistanceToPoint,
  8270. PointPairDistance: PointPairDistance
  8271. });
  8272. class ItemVisitor {
  8273. visitItem(item) {}
  8274. }
  8275. class PointOnGeometryLocator {
  8276. locate(p) {}
  8277. }
  8278. class IntervalRTreeNode {
  8279. constructor() {
  8280. IntervalRTreeNode.constructor_.apply(this, arguments);
  8281. }
  8282. static constructor_() {
  8283. this._min = Double.POSITIVE_INFINITY;
  8284. this._max = Double.NEGATIVE_INFINITY;
  8285. }
  8286. getMin() {
  8287. return this._min;
  8288. }
  8289. intersects(queryMin, queryMax) {
  8290. if (this._min > queryMax || this._max < queryMin) return false;
  8291. return true;
  8292. }
  8293. getMax() {
  8294. return this._max;
  8295. }
  8296. toString() {
  8297. return WKTWriter.toLineString(new Coordinate(this._min, 0), new Coordinate(this._max, 0));
  8298. }
  8299. }
  8300. class NodeComparator {
  8301. compare(o1, o2) {
  8302. const n1 = o1;
  8303. const n2 = o2;
  8304. const mid1 = (n1._min + n1._max) / 2;
  8305. const mid2 = (n2._min + n2._max) / 2;
  8306. if (mid1 < mid2) return -1;
  8307. if (mid1 > mid2) return 1;
  8308. return 0;
  8309. }
  8310. get interfaces_() {
  8311. return [Comparator];
  8312. }
  8313. }
  8314. IntervalRTreeNode.NodeComparator = NodeComparator;
  8315. class IntervalRTreeLeafNode extends IntervalRTreeNode {
  8316. constructor() {
  8317. super();
  8318. IntervalRTreeLeafNode.constructor_.apply(this, arguments);
  8319. }
  8320. static constructor_() {
  8321. this._item = null;
  8322. const min = arguments[0],
  8323. max = arguments[1],
  8324. item = arguments[2];
  8325. this._min = min;
  8326. this._max = max;
  8327. this._item = item;
  8328. }
  8329. query(queryMin, queryMax, visitor) {
  8330. if (!this.intersects(queryMin, queryMax)) return null;
  8331. visitor.visitItem(this._item);
  8332. }
  8333. }
  8334. class IntervalRTreeBranchNode extends IntervalRTreeNode {
  8335. constructor() {
  8336. super();
  8337. IntervalRTreeBranchNode.constructor_.apply(this, arguments);
  8338. }
  8339. static constructor_() {
  8340. this._node1 = null;
  8341. this._node2 = null;
  8342. const n1 = arguments[0],
  8343. n2 = arguments[1];
  8344. this._node1 = n1;
  8345. this._node2 = n2;
  8346. this.buildExtent(this._node1, this._node2);
  8347. }
  8348. buildExtent(n1, n2) {
  8349. this._min = Math.min(n1._min, n2._min);
  8350. this._max = Math.max(n1._max, n2._max);
  8351. }
  8352. query(queryMin, queryMax, visitor) {
  8353. if (!this.intersects(queryMin, queryMax)) return null;
  8354. if (this._node1 !== null) this._node1.query(queryMin, queryMax, visitor);
  8355. if (this._node2 !== null) this._node2.query(queryMin, queryMax, visitor);
  8356. }
  8357. }
  8358. class SortedPackedIntervalRTree {
  8359. constructor() {
  8360. SortedPackedIntervalRTree.constructor_.apply(this, arguments);
  8361. }
  8362. static constructor_() {
  8363. this._leaves = new ArrayList();
  8364. this._root = null;
  8365. this._level = 0;
  8366. }
  8367. buildTree() {
  8368. Collections.sort(this._leaves, new IntervalRTreeNode.NodeComparator());
  8369. let src = this._leaves;
  8370. let temp = null;
  8371. let dest = new ArrayList();
  8372. while (true) {
  8373. this.buildLevel(src, dest);
  8374. if (dest.size() === 1) return dest.get(0);
  8375. temp = src;
  8376. src = dest;
  8377. dest = temp;
  8378. }
  8379. }
  8380. insert(min, max, item) {
  8381. if (this._root !== null) throw new IllegalStateException('Index cannot be added to once it has been queried');
  8382. this._leaves.add(new IntervalRTreeLeafNode(min, max, item));
  8383. }
  8384. query(min, max, visitor) {
  8385. this.init();
  8386. if (this._root === null) return null;
  8387. this._root.query(min, max, visitor);
  8388. }
  8389. buildRoot() {
  8390. if (this._root !== null) return null;
  8391. this._root = this.buildTree();
  8392. }
  8393. printNode(node) {
  8394. System.out.println(WKTWriter.toLineString(new Coordinate(node._min, this._level), new Coordinate(node._max, this._level)));
  8395. }
  8396. init() {
  8397. if (this._root !== null) return null;
  8398. if (this._leaves.size() === 0) return null;
  8399. this.buildRoot();
  8400. }
  8401. buildLevel(src, dest) {
  8402. this._level++;
  8403. dest.clear();
  8404. for (let i = 0; i < src.size(); i += 2) {
  8405. const n1 = src.get(i);
  8406. const n2 = i + 1 < src.size() ? src.get(i) : null;
  8407. if (n2 === null) {
  8408. dest.add(n1);
  8409. } else {
  8410. const node = new IntervalRTreeBranchNode(src.get(i), src.get(i + 1));
  8411. dest.add(node);
  8412. }
  8413. }
  8414. }
  8415. }
  8416. class ArrayListVisitor {
  8417. constructor() {
  8418. ArrayListVisitor.constructor_.apply(this, arguments);
  8419. }
  8420. static constructor_() {
  8421. this._items = new ArrayList();
  8422. }
  8423. visitItem(item) {
  8424. this._items.add(item);
  8425. }
  8426. getItems() {
  8427. return this._items;
  8428. }
  8429. get interfaces_() {
  8430. return [ItemVisitor];
  8431. }
  8432. }
  8433. class RayCrossingCounter {
  8434. constructor() {
  8435. RayCrossingCounter.constructor_.apply(this, arguments);
  8436. }
  8437. static constructor_() {
  8438. this._p = null;
  8439. this._crossingCount = 0;
  8440. this._isPointOnSegment = false;
  8441. const p = arguments[0];
  8442. this._p = p;
  8443. }
  8444. static locatePointInRing() {
  8445. if (arguments[0] instanceof Coordinate && hasInterface(arguments[1], CoordinateSequence)) {
  8446. const p = arguments[0],
  8447. ring = arguments[1];
  8448. const counter = new RayCrossingCounter(p);
  8449. const p1 = new Coordinate();
  8450. const p2 = new Coordinate();
  8451. for (let i = 1; i < ring.size(); i++) {
  8452. ring.getCoordinate(i, p1);
  8453. ring.getCoordinate(i - 1, p2);
  8454. counter.countSegment(p1, p2);
  8455. if (counter.isOnSegment()) return counter.getLocation();
  8456. }
  8457. return counter.getLocation();
  8458. } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Array) {
  8459. const p = arguments[0],
  8460. ring = arguments[1];
  8461. const counter = new RayCrossingCounter(p);
  8462. for (let i = 1; i < ring.length; i++) {
  8463. const p1 = ring[i];
  8464. const p2 = ring[i - 1];
  8465. counter.countSegment(p1, p2);
  8466. if (counter.isOnSegment()) return counter.getLocation();
  8467. }
  8468. return counter.getLocation();
  8469. }
  8470. }
  8471. countSegment(p1, p2) {
  8472. if (p1.x < this._p.x && p2.x < this._p.x) return null;
  8473. if (this._p.x === p2.x && this._p.y === p2.y) {
  8474. this._isPointOnSegment = true;
  8475. return null;
  8476. }
  8477. if (p1.y === this._p.y && p2.y === this._p.y) {
  8478. let minx = p1.x;
  8479. let maxx = p2.x;
  8480. if (minx > maxx) {
  8481. minx = p2.x;
  8482. maxx = p1.x;
  8483. }
  8484. if (this._p.x >= minx && this._p.x <= maxx) this._isPointOnSegment = true;
  8485. return null;
  8486. }
  8487. if (p1.y > this._p.y && p2.y <= this._p.y || p2.y > this._p.y && p1.y <= this._p.y) {
  8488. let orient = Orientation.index(p1, p2, this._p);
  8489. if (orient === Orientation.COLLINEAR) {
  8490. this._isPointOnSegment = true;
  8491. return null;
  8492. }
  8493. if (p2.y < p1.y) orient = -orient;
  8494. if (orient === Orientation.LEFT) this._crossingCount++;
  8495. }
  8496. }
  8497. isPointInPolygon() {
  8498. return this.getLocation() !== Location.EXTERIOR;
  8499. }
  8500. getLocation() {
  8501. if (this._isPointOnSegment) return Location.BOUNDARY;
  8502. if (this._crossingCount % 2 === 1) return Location.INTERIOR;
  8503. return Location.EXTERIOR;
  8504. }
  8505. isOnSegment() {
  8506. return this._isPointOnSegment;
  8507. }
  8508. }
  8509. class IndexedPointInAreaLocator {
  8510. constructor() {
  8511. IndexedPointInAreaLocator.constructor_.apply(this, arguments);
  8512. }
  8513. static constructor_() {
  8514. this._geom = null;
  8515. this._index = null;
  8516. const g = arguments[0];
  8517. if (!(hasInterface(g, Polygonal) || g instanceof LinearRing)) throw new IllegalArgumentException('Argument must be Polygonal or LinearRing');
  8518. this._geom = g;
  8519. }
  8520. locate(p) {
  8521. if (this._index === null) {
  8522. this._index = new IntervalIndexedGeometry(this._geom);
  8523. this._geom = null;
  8524. }
  8525. const rcc = new RayCrossingCounter(p);
  8526. const visitor = new SegmentVisitor(rcc);
  8527. this._index.query(p.y, p.y, visitor);
  8528. return rcc.getLocation();
  8529. }
  8530. get interfaces_() {
  8531. return [PointOnGeometryLocator];
  8532. }
  8533. }
  8534. class SegmentVisitor {
  8535. constructor() {
  8536. SegmentVisitor.constructor_.apply(this, arguments);
  8537. }
  8538. static constructor_() {
  8539. this._counter = null;
  8540. const counter = arguments[0];
  8541. this._counter = counter;
  8542. }
  8543. visitItem(item) {
  8544. const seg = item;
  8545. this._counter.countSegment(seg.getCoordinate(0), seg.getCoordinate(1));
  8546. }
  8547. get interfaces_() {
  8548. return [ItemVisitor];
  8549. }
  8550. }
  8551. class IntervalIndexedGeometry {
  8552. constructor() {
  8553. IntervalIndexedGeometry.constructor_.apply(this, arguments);
  8554. }
  8555. static constructor_() {
  8556. this._isEmpty = false;
  8557. this._index = new SortedPackedIntervalRTree();
  8558. const geom = arguments[0];
  8559. if (geom.isEmpty()) this._isEmpty = true;else this.init(geom);
  8560. }
  8561. init(geom) {
  8562. const lines = LinearComponentExtracter.getLines(geom);
  8563. for (let i = lines.iterator(); i.hasNext();) {
  8564. const line = i.next();
  8565. const pts = line.getCoordinates();
  8566. this.addLine(pts);
  8567. }
  8568. }
  8569. addLine(pts) {
  8570. for (let i = 1; i < pts.length; i++) {
  8571. const seg = new LineSegment(pts[i - 1], pts[i]);
  8572. const min = Math.min(seg.p0.y, seg.p1.y);
  8573. const max = Math.max(seg.p0.y, seg.p1.y);
  8574. this._index.insert(min, max, seg);
  8575. }
  8576. }
  8577. query() {
  8578. if (arguments.length === 2) {
  8579. const min = arguments[0],
  8580. max = arguments[1];
  8581. if (this._isEmpty) return new ArrayList();
  8582. const visitor = new ArrayListVisitor();
  8583. this._index.query(min, max, visitor);
  8584. return visitor.getItems();
  8585. } else if (arguments.length === 3) {
  8586. const min = arguments[0],
  8587. max = arguments[1],
  8588. visitor = arguments[2];
  8589. if (this._isEmpty) return null;
  8590. this._index.query(min, max, visitor);
  8591. }
  8592. }
  8593. }
  8594. IndexedPointInAreaLocator.SegmentVisitor = SegmentVisitor;
  8595. IndexedPointInAreaLocator.IntervalIndexedGeometry = IntervalIndexedGeometry;
  8596. class PointLocation {
  8597. static isOnLine() {
  8598. if (arguments[0] instanceof Coordinate && hasInterface(arguments[1], CoordinateSequence)) {
  8599. const p = arguments[0],
  8600. line = arguments[1];
  8601. const lineIntersector = new RobustLineIntersector();
  8602. const p0 = new Coordinate();
  8603. const p1 = new Coordinate();
  8604. const n = line.size();
  8605. for (let i = 1; i < n; i++) {
  8606. line.getCoordinate(i - 1, p0);
  8607. line.getCoordinate(i, p1);
  8608. lineIntersector.computeIntersection(p, p0, p1);
  8609. if (lineIntersector.hasIntersection()) return true;
  8610. }
  8611. return false;
  8612. } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Array) {
  8613. const p = arguments[0],
  8614. line = arguments[1];
  8615. const lineIntersector = new RobustLineIntersector();
  8616. for (let i = 1; i < line.length; i++) {
  8617. const p0 = line[i - 1];
  8618. const p1 = line[i];
  8619. lineIntersector.computeIntersection(p, p0, p1);
  8620. if (lineIntersector.hasIntersection()) return true;
  8621. }
  8622. return false;
  8623. }
  8624. }
  8625. static locateInRing(p, ring) {
  8626. return RayCrossingCounter.locatePointInRing(p, ring);
  8627. }
  8628. static isInRing(p, ring) {
  8629. return PointLocation.locateInRing(p, ring) !== Location.EXTERIOR;
  8630. }
  8631. }
  8632. /**
  8633. * @see http://download.oracle.com/javase/6/docs/api/java/util/Iterator.html
  8634. * @constructor
  8635. * @private
  8636. */
  8637. class Iterator {
  8638. /**
  8639. * Returns true if the iteration has more elements.
  8640. * @return {boolean}
  8641. */
  8642. hasNext() {}
  8643. /**
  8644. * Returns the next element in the iteration.
  8645. * @return {Object}
  8646. */
  8647. next() {}
  8648. /**
  8649. * Removes from the underlying collection the last element returned by the
  8650. * iterator (optional operation).
  8651. */
  8652. remove() {}
  8653. }
  8654. class GeometryCollectionIterator {
  8655. constructor() {
  8656. GeometryCollectionIterator.constructor_.apply(this, arguments);
  8657. }
  8658. static constructor_() {
  8659. this._parent = null;
  8660. this._atStart = null;
  8661. this._max = null;
  8662. this._index = null;
  8663. this._subcollectionIterator = null;
  8664. const parent = arguments[0];
  8665. this._parent = parent;
  8666. this._atStart = true;
  8667. this._index = 0;
  8668. this._max = parent.getNumGeometries();
  8669. }
  8670. static isAtomic(geom) {
  8671. return !(geom instanceof GeometryCollection);
  8672. }
  8673. next() {
  8674. if (this._atStart) {
  8675. this._atStart = false;
  8676. if (GeometryCollectionIterator.isAtomic(this._parent)) this._index++;
  8677. return this._parent;
  8678. }
  8679. if (this._subcollectionIterator !== null) if (this._subcollectionIterator.hasNext()) return this._subcollectionIterator.next();else this._subcollectionIterator = null;
  8680. if (this._index >= this._max) throw new NoSuchElementException();
  8681. const obj = this._parent.getGeometryN(this._index++);
  8682. if (obj instanceof GeometryCollection) {
  8683. this._subcollectionIterator = new GeometryCollectionIterator(obj);
  8684. return this._subcollectionIterator.next();
  8685. }
  8686. return obj;
  8687. }
  8688. remove() {
  8689. throw new UnsupportedOperationException(this.getClass().getName());
  8690. }
  8691. hasNext() {
  8692. if (this._atStart) return true;
  8693. if (this._subcollectionIterator !== null) {
  8694. if (this._subcollectionIterator.hasNext()) return true;
  8695. this._subcollectionIterator = null;
  8696. }
  8697. if (this._index >= this._max) return false;
  8698. return true;
  8699. }
  8700. get interfaces_() {
  8701. return [Iterator];
  8702. }
  8703. }
  8704. class SimplePointInAreaLocator {
  8705. constructor() {
  8706. SimplePointInAreaLocator.constructor_.apply(this, arguments);
  8707. }
  8708. static constructor_() {
  8709. this._geom = null;
  8710. const geom = arguments[0];
  8711. this._geom = geom;
  8712. }
  8713. static locatePointInPolygon(p, poly) {
  8714. if (poly.isEmpty()) return Location.EXTERIOR;
  8715. const shell = poly.getExteriorRing();
  8716. const shellLoc = SimplePointInAreaLocator.locatePointInRing(p, shell);
  8717. if (shellLoc !== Location.INTERIOR) return shellLoc;
  8718. for (let i = 0; i < poly.getNumInteriorRing(); i++) {
  8719. const hole = poly.getInteriorRingN(i);
  8720. const holeLoc = SimplePointInAreaLocator.locatePointInRing(p, hole);
  8721. if (holeLoc === Location.BOUNDARY) return Location.BOUNDARY;
  8722. if (holeLoc === Location.INTERIOR) return Location.EXTERIOR;
  8723. }
  8724. return Location.INTERIOR;
  8725. }
  8726. static locatePointInRing(p, ring) {
  8727. if (!ring.getEnvelopeInternal().intersects(p)) return Location.EXTERIOR;
  8728. return PointLocation.locateInRing(p, ring.getCoordinates());
  8729. }
  8730. static containsPointInPolygon(p, poly) {
  8731. return Location.EXTERIOR !== SimplePointInAreaLocator.locatePointInPolygon(p, poly);
  8732. }
  8733. static locateInGeometry(p, geom) {
  8734. if (geom instanceof Polygon) return SimplePointInAreaLocator.locatePointInPolygon(p, geom);
  8735. if (geom instanceof GeometryCollection) {
  8736. const geomi = new GeometryCollectionIterator(geom);
  8737. while (geomi.hasNext()) {
  8738. const g2 = geomi.next();
  8739. if (g2 !== geom) {
  8740. const loc = SimplePointInAreaLocator.locateInGeometry(p, g2);
  8741. if (loc !== Location.EXTERIOR) return loc;
  8742. }
  8743. }
  8744. }
  8745. return Location.EXTERIOR;
  8746. }
  8747. static isContained(p, geom) {
  8748. return Location.EXTERIOR !== SimplePointInAreaLocator.locate(p, geom);
  8749. }
  8750. static locate(p, geom) {
  8751. if (geom.isEmpty()) return Location.EXTERIOR;
  8752. if (!geom.getEnvelopeInternal().intersects(p)) return Location.EXTERIOR;
  8753. return SimplePointInAreaLocator.locateInGeometry(p, geom);
  8754. }
  8755. locate(p) {
  8756. return SimplePointInAreaLocator.locate(p, this._geom);
  8757. }
  8758. get interfaces_() {
  8759. return [PointOnGeometryLocator];
  8760. }
  8761. }
  8762. var locate = /*#__PURE__*/Object.freeze({
  8763. __proto__: null,
  8764. IndexedPointInAreaLocator: IndexedPointInAreaLocator,
  8765. PointOnGeometryLocator: PointOnGeometryLocator,
  8766. SimplePointInAreaLocator: SimplePointInAreaLocator
  8767. });
  8768. class SimilarityMeasure {
  8769. measure(g1, g2) {}
  8770. }
  8771. class AreaSimilarityMeasure {
  8772. measure(g1, g2) {
  8773. const areaInt = g1.intersection(g2).getArea();
  8774. const areaUnion = g1.union(g2).getArea();
  8775. return areaInt / areaUnion;
  8776. }
  8777. get interfaces_() {
  8778. return [SimilarityMeasure];
  8779. }
  8780. }
  8781. class HausdorffSimilarityMeasure {
  8782. static diagonalSize(env) {
  8783. if (env.isNull()) return 0.0;
  8784. const width = env.getWidth();
  8785. const hgt = env.getHeight();
  8786. return Math.sqrt(width * width + hgt * hgt);
  8787. }
  8788. measure(g1, g2) {
  8789. const distance = DiscreteHausdorffDistance.distance(g1, g2, HausdorffSimilarityMeasure.DENSIFY_FRACTION);
  8790. const env = new Envelope(g1.getEnvelopeInternal());
  8791. env.expandToInclude(g2.getEnvelopeInternal());
  8792. const envSize = HausdorffSimilarityMeasure.diagonalSize(env);
  8793. const measure = 1 - distance / envSize;
  8794. return measure;
  8795. }
  8796. get interfaces_() {
  8797. return [SimilarityMeasure];
  8798. }
  8799. }
  8800. HausdorffSimilarityMeasure.DENSIFY_FRACTION = 0.25;
  8801. class SimilarityMeasureCombiner {
  8802. static combine(measure1, measure2) {
  8803. return Math.min(measure1, measure2);
  8804. }
  8805. }
  8806. var match = /*#__PURE__*/Object.freeze({
  8807. __proto__: null,
  8808. AreaSimilarityMeasure: AreaSimilarityMeasure,
  8809. HausdorffSimilarityMeasure: HausdorffSimilarityMeasure,
  8810. SimilarityMeasure: SimilarityMeasure,
  8811. SimilarityMeasureCombiner: SimilarityMeasureCombiner
  8812. });
  8813. class Centroid {
  8814. constructor() {
  8815. Centroid.constructor_.apply(this, arguments);
  8816. }
  8817. static constructor_() {
  8818. this._areaBasePt = null;
  8819. this._triangleCent3 = new Coordinate();
  8820. this._areasum2 = 0;
  8821. this._cg3 = new Coordinate();
  8822. this._lineCentSum = new Coordinate();
  8823. this._totalLength = 0.0;
  8824. this._ptCount = 0;
  8825. this._ptCentSum = new Coordinate();
  8826. const geom = arguments[0];
  8827. this._areaBasePt = null;
  8828. this.add(geom);
  8829. }
  8830. static area2(p1, p2, p3) {
  8831. return (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y);
  8832. }
  8833. static centroid3(p1, p2, p3, c) {
  8834. c.x = p1.x + p2.x + p3.x;
  8835. c.y = p1.y + p2.y + p3.y;
  8836. return null;
  8837. }
  8838. static getCentroid(geom) {
  8839. const cent = new Centroid(geom);
  8840. return cent.getCentroid();
  8841. }
  8842. setAreaBasePoint(basePt) {
  8843. this._areaBasePt = basePt;
  8844. }
  8845. addPoint(pt) {
  8846. this._ptCount += 1;
  8847. this._ptCentSum.x += pt.x;
  8848. this._ptCentSum.y += pt.y;
  8849. }
  8850. addLineSegments(pts) {
  8851. let lineLen = 0.0;
  8852. for (let i = 0; i < pts.length - 1; i++) {
  8853. const segmentLen = pts[i].distance(pts[i + 1]);
  8854. if (segmentLen === 0.0) continue;
  8855. lineLen += segmentLen;
  8856. const midx = (pts[i].x + pts[i + 1].x) / 2;
  8857. this._lineCentSum.x += segmentLen * midx;
  8858. const midy = (pts[i].y + pts[i + 1].y) / 2;
  8859. this._lineCentSum.y += segmentLen * midy;
  8860. }
  8861. this._totalLength += lineLen;
  8862. if (lineLen === 0.0 && pts.length > 0) this.addPoint(pts[0]);
  8863. }
  8864. addHole(pts) {
  8865. const isPositiveArea = Orientation.isCCW(pts);
  8866. for (let i = 0; i < pts.length - 1; i++) this.addTriangle(this._areaBasePt, pts[i], pts[i + 1], isPositiveArea);
  8867. this.addLineSegments(pts);
  8868. }
  8869. getCentroid() {
  8870. const cent = new Coordinate();
  8871. if (Math.abs(this._areasum2) > 0.0) {
  8872. cent.x = this._cg3.x / 3 / this._areasum2;
  8873. cent.y = this._cg3.y / 3 / this._areasum2;
  8874. } else if (this._totalLength > 0.0) {
  8875. cent.x = this._lineCentSum.x / this._totalLength;
  8876. cent.y = this._lineCentSum.y / this._totalLength;
  8877. } else if (this._ptCount > 0) {
  8878. cent.x = this._ptCentSum.x / this._ptCount;
  8879. cent.y = this._ptCentSum.y / this._ptCount;
  8880. } else {
  8881. return null;
  8882. }
  8883. return cent;
  8884. }
  8885. addShell(pts) {
  8886. if (pts.length > 0) this.setAreaBasePoint(pts[0]);
  8887. const isPositiveArea = !Orientation.isCCW(pts);
  8888. for (let i = 0; i < pts.length - 1; i++) this.addTriangle(this._areaBasePt, pts[i], pts[i + 1], isPositiveArea);
  8889. this.addLineSegments(pts);
  8890. }
  8891. addTriangle(p0, p1, p2, isPositiveArea) {
  8892. const sign = isPositiveArea ? 1.0 : -1.0;
  8893. Centroid.centroid3(p0, p1, p2, this._triangleCent3);
  8894. const area2 = Centroid.area2(p0, p1, p2);
  8895. this._cg3.x += sign * area2 * this._triangleCent3.x;
  8896. this._cg3.y += sign * area2 * this._triangleCent3.y;
  8897. this._areasum2 += sign * area2;
  8898. }
  8899. add() {
  8900. if (arguments[0] instanceof Polygon) {
  8901. const poly = arguments[0];
  8902. this.addShell(poly.getExteriorRing().getCoordinates());
  8903. for (let i = 0; i < poly.getNumInteriorRing(); i++) this.addHole(poly.getInteriorRingN(i).getCoordinates());
  8904. } else if (arguments[0] instanceof Geometry) {
  8905. const geom = arguments[0];
  8906. if (geom.isEmpty()) return null;
  8907. if (geom instanceof Point) {
  8908. this.addPoint(geom.getCoordinate());
  8909. } else if (geom instanceof LineString) {
  8910. this.addLineSegments(geom.getCoordinates());
  8911. } else if (geom instanceof Polygon) {
  8912. const poly = geom;
  8913. this.add(poly);
  8914. } else if (geom instanceof GeometryCollection) {
  8915. const gc = geom;
  8916. for (let i = 0; i < gc.getNumGeometries(); i++) this.add(gc.getGeometryN(i));
  8917. }
  8918. }
  8919. }
  8920. }
  8921. class EmptyStackException extends Exception {
  8922. constructor(message) {
  8923. super(message);
  8924. this.name = Object.keys({
  8925. EmptyStackException
  8926. })[0];
  8927. }
  8928. }
  8929. /**
  8930. * @see http://download.oracle.com/javase/6/docs/api/java/util/Stack.html
  8931. */
  8932. class Stack extends List {
  8933. constructor() {
  8934. super();
  8935. this.array = [];
  8936. }
  8937. add(e) {
  8938. this.array.push(e);
  8939. return true;
  8940. }
  8941. get(index) {
  8942. if (index < 0 || index >= this.size()) throw new IndexOutOfBoundsException();
  8943. return this.array[index];
  8944. }
  8945. /**
  8946. * Pushes an item onto the top of this stack.
  8947. * @param {Object} e
  8948. * @return {Object}
  8949. */
  8950. push(e) {
  8951. this.array.push(e);
  8952. return e;
  8953. }
  8954. /**
  8955. * Removes the object at the top of this stack and returns that object as the value of this function.
  8956. * @return {Object}
  8957. */
  8958. pop() {
  8959. if (this.array.length === 0) throw new EmptyStackException();
  8960. return this.array.pop();
  8961. }
  8962. /**
  8963. * Looks at the object at the top of this stack without removing it from the
  8964. * stack.
  8965. * @return {Object}
  8966. */
  8967. peek() {
  8968. if (this.array.length === 0) throw new EmptyStackException();
  8969. return this.array[this.array.length - 1];
  8970. }
  8971. /**
  8972. * Tests if this stack is empty.
  8973. * @return {boolean} true if and only if this stack contains no items; false
  8974. * otherwise.
  8975. */
  8976. empty() {
  8977. return this.array.length === 0;
  8978. }
  8979. /**
  8980. * @return {boolean}
  8981. */
  8982. isEmpty() {
  8983. return this.empty();
  8984. }
  8985. /**
  8986. * Returns the 1-based position where an object is on this stack. If the object
  8987. * o occurs as an item in this stack, this method returns the distance from the
  8988. * top of the stack of the occurrence nearest the top of the stack; the topmost
  8989. * item on the stack is considered to be at distance 1. The equals method is
  8990. * used to compare o to the items in this stack.
  8991. *
  8992. * NOTE: does not currently actually use equals. (=== is used)
  8993. *
  8994. * @param {Object} o
  8995. * @return {number} the 1-based position from the top of the stack where the
  8996. * object is located; the return value -1 indicates that the object is
  8997. * not on the stack.
  8998. */
  8999. search(o) {
  9000. return this.array.indexOf(o);
  9001. }
  9002. /**
  9003. * @return {number}
  9004. */
  9005. size() {
  9006. return this.array.length;
  9007. }
  9008. /**
  9009. * @return {Array}
  9010. */
  9011. toArray() {
  9012. return this.array.slice();
  9013. }
  9014. }
  9015. class UniqueCoordinateArrayFilter {
  9016. constructor() {
  9017. UniqueCoordinateArrayFilter.constructor_.apply(this, arguments);
  9018. }
  9019. static constructor_() {
  9020. this._coordSet = new HashSet();
  9021. this._list = new ArrayList();
  9022. }
  9023. static filterCoordinates(coords) {
  9024. const filter = new UniqueCoordinateArrayFilter();
  9025. for (let i = 0; i < coords.length; i++) filter.filter(coords[i]);
  9026. return filter.getCoordinates();
  9027. }
  9028. filter(coord) {
  9029. if (this._coordSet.add(coord)) this._list.add(coord);
  9030. }
  9031. getCoordinates() {
  9032. const coordinates = new Array(this._list.size()).fill(null);
  9033. return this._list.toArray(coordinates);
  9034. }
  9035. get interfaces_() {
  9036. return [CoordinateFilter];
  9037. }
  9038. }
  9039. class ConvexHull {
  9040. constructor() {
  9041. ConvexHull.constructor_.apply(this, arguments);
  9042. }
  9043. static constructor_() {
  9044. this._geomFactory = null;
  9045. this._inputPts = null;
  9046. if (arguments.length === 1) {
  9047. const geometry = arguments[0];
  9048. ConvexHull.constructor_.call(this, ConvexHull.extractCoordinates(geometry), geometry.getFactory());
  9049. } else if (arguments.length === 2) {
  9050. const pts = arguments[0],
  9051. geomFactory = arguments[1];
  9052. this._inputPts = UniqueCoordinateArrayFilter.filterCoordinates(pts);
  9053. this._geomFactory = geomFactory;
  9054. }
  9055. }
  9056. static extractCoordinates(geom) {
  9057. const filter = new UniqueCoordinateArrayFilter();
  9058. geom.apply(filter);
  9059. return filter.getCoordinates();
  9060. }
  9061. preSort(pts) {
  9062. let t = null;
  9063. for (let i = 1; i < pts.length; i++) if (pts[i].y < pts[0].y || pts[i].y === pts[0].y && pts[i].x < pts[0].x) {
  9064. t = pts[0];
  9065. pts[0] = pts[i];
  9066. pts[i] = t;
  9067. }
  9068. Arrays.sort(pts, 1, pts.length, new RadialComparator(pts[0]));
  9069. return pts;
  9070. }
  9071. computeOctRing(inputPts) {
  9072. const octPts = this.computeOctPts(inputPts);
  9073. const coordList = new CoordinateList();
  9074. coordList.add(octPts, false);
  9075. if (coordList.size() < 3) return null;
  9076. coordList.closeRing();
  9077. return coordList.toCoordinateArray();
  9078. }
  9079. lineOrPolygon(coordinates) {
  9080. coordinates = this.cleanRing(coordinates);
  9081. if (coordinates.length === 3) return this._geomFactory.createLineString([coordinates[0], coordinates[1]]);
  9082. const linearRing = this._geomFactory.createLinearRing(coordinates);
  9083. return this._geomFactory.createPolygon(linearRing);
  9084. }
  9085. cleanRing(original) {
  9086. Assert.equals(original[0], original[original.length - 1]);
  9087. const cleanedRing = new ArrayList();
  9088. let previousDistinctCoordinate = null;
  9089. for (let i = 0; i <= original.length - 2; i++) {
  9090. const currentCoordinate = original[i];
  9091. const nextCoordinate = original[i + 1];
  9092. if (currentCoordinate.equals(nextCoordinate)) continue;
  9093. if (previousDistinctCoordinate !== null && this.isBetween(previousDistinctCoordinate, currentCoordinate, nextCoordinate)) continue;
  9094. cleanedRing.add(currentCoordinate);
  9095. previousDistinctCoordinate = currentCoordinate;
  9096. }
  9097. cleanedRing.add(original[original.length - 1]);
  9098. const cleanedRingCoordinates = new Array(cleanedRing.size()).fill(null);
  9099. return cleanedRing.toArray(cleanedRingCoordinates);
  9100. }
  9101. isBetween(c1, c2, c3) {
  9102. if (Orientation.index(c1, c2, c3) !== 0) return false;
  9103. if (c1.x !== c3.x) {
  9104. if (c1.x <= c2.x && c2.x <= c3.x) return true;
  9105. if (c3.x <= c2.x && c2.x <= c1.x) return true;
  9106. }
  9107. if (c1.y !== c3.y) {
  9108. if (c1.y <= c2.y && c2.y <= c3.y) return true;
  9109. if (c3.y <= c2.y && c2.y <= c1.y) return true;
  9110. }
  9111. return false;
  9112. }
  9113. reduce(inputPts) {
  9114. const polyPts = this.computeOctRing(inputPts);
  9115. if (polyPts === null) return inputPts;
  9116. const reducedSet = new TreeSet();
  9117. for (let i = 0; i < polyPts.length; i++) reducedSet.add(polyPts[i]);
  9118. for (let i = 0; i < inputPts.length; i++) if (!PointLocation.isInRing(inputPts[i], polyPts)) reducedSet.add(inputPts[i]);
  9119. const reducedPts = CoordinateArrays.toCoordinateArray(reducedSet);
  9120. if (reducedPts.length < 3) return this.padArray3(reducedPts);
  9121. return reducedPts;
  9122. }
  9123. getConvexHull() {
  9124. if (this._inputPts.length === 0) return this._geomFactory.createGeometryCollection();
  9125. if (this._inputPts.length === 1) return this._geomFactory.createPoint(this._inputPts[0]);
  9126. if (this._inputPts.length === 2) return this._geomFactory.createLineString(this._inputPts);
  9127. let reducedPts = this._inputPts;
  9128. if (this._inputPts.length > 50) reducedPts = this.reduce(this._inputPts);
  9129. const sortedPts = this.preSort(reducedPts);
  9130. const cHS = this.grahamScan(sortedPts);
  9131. const cH = this.toCoordinateArray(cHS);
  9132. return this.lineOrPolygon(cH);
  9133. }
  9134. padArray3(pts) {
  9135. const pad = new Array(3).fill(null);
  9136. for (let i = 0; i < pad.length; i++) if (i < pts.length) pad[i] = pts[i];else pad[i] = pts[0];
  9137. return pad;
  9138. }
  9139. computeOctPts(inputPts) {
  9140. const pts = new Array(8).fill(null);
  9141. for (let j = 0; j < pts.length; j++) pts[j] = inputPts[0];
  9142. for (let i = 1; i < inputPts.length; i++) {
  9143. if (inputPts[i].x < pts[0].x) pts[0] = inputPts[i];
  9144. if (inputPts[i].x - inputPts[i].y < pts[1].x - pts[1].y) pts[1] = inputPts[i];
  9145. if (inputPts[i].y > pts[2].y) pts[2] = inputPts[i];
  9146. if (inputPts[i].x + inputPts[i].y > pts[3].x + pts[3].y) pts[3] = inputPts[i];
  9147. if (inputPts[i].x > pts[4].x) pts[4] = inputPts[i];
  9148. if (inputPts[i].x - inputPts[i].y > pts[5].x - pts[5].y) pts[5] = inputPts[i];
  9149. if (inputPts[i].y < pts[6].y) pts[6] = inputPts[i];
  9150. if (inputPts[i].x + inputPts[i].y < pts[7].x + pts[7].y) pts[7] = inputPts[i];
  9151. }
  9152. return pts;
  9153. }
  9154. toCoordinateArray(stack) {
  9155. const coordinates = new Array(stack.size()).fill(null);
  9156. for (let i = 0; i < stack.size(); i++) {
  9157. const coordinate = stack.get(i);
  9158. coordinates[i] = coordinate;
  9159. }
  9160. return coordinates;
  9161. }
  9162. grahamScan(c) {
  9163. let p = null;
  9164. const ps = new Stack();
  9165. ps.push(c[0]);
  9166. ps.push(c[1]);
  9167. ps.push(c[2]);
  9168. for (let i = 3; i < c.length; i++) {
  9169. p = ps.pop();
  9170. while (!ps.empty() && Orientation.index(ps.peek(), p, c[i]) > 0) p = ps.pop();
  9171. ps.push(p);
  9172. ps.push(c[i]);
  9173. }
  9174. ps.push(c[0]);
  9175. return ps;
  9176. }
  9177. }
  9178. class RadialComparator {
  9179. constructor() {
  9180. RadialComparator.constructor_.apply(this, arguments);
  9181. }
  9182. static constructor_() {
  9183. this._origin = null;
  9184. const origin = arguments[0];
  9185. this._origin = origin;
  9186. }
  9187. static polarCompare(o, p, q) {
  9188. const dxp = p.x - o.x;
  9189. const dyp = p.y - o.y;
  9190. const dxq = q.x - o.x;
  9191. const dyq = q.y - o.y;
  9192. const orient = Orientation.index(o, p, q);
  9193. if (orient === Orientation.COUNTERCLOCKWISE) return 1;
  9194. if (orient === Orientation.CLOCKWISE) return -1;
  9195. const op = dxp * dxp + dyp * dyp;
  9196. const oq = dxq * dxq + dyq * dyq;
  9197. if (op < oq) return -1;
  9198. if (op > oq) return 1;
  9199. return 0;
  9200. }
  9201. compare(o1, o2) {
  9202. const p1 = o1;
  9203. const p2 = o2;
  9204. return RadialComparator.polarCompare(this._origin, p1, p2);
  9205. }
  9206. get interfaces_() {
  9207. return [Comparator];
  9208. }
  9209. }
  9210. ConvexHull.RadialComparator = RadialComparator;
  9211. class InteriorPointArea {
  9212. constructor() {
  9213. InteriorPointArea.constructor_.apply(this, arguments);
  9214. }
  9215. static constructor_() {
  9216. this._interiorPoint = null;
  9217. this._maxWidth = -1;
  9218. const g = arguments[0];
  9219. this.process(g);
  9220. }
  9221. static getInteriorPoint(geom) {
  9222. const intPt = new InteriorPointArea(geom);
  9223. return intPt.getInteriorPoint();
  9224. }
  9225. static avg(a, b) {
  9226. return (a + b) / 2.0;
  9227. }
  9228. getInteriorPoint() {
  9229. return this._interiorPoint;
  9230. }
  9231. process(geom) {
  9232. if (geom.isEmpty()) return null;
  9233. if (geom instanceof Polygon) {
  9234. this.processPolygon(geom);
  9235. } else if (geom instanceof GeometryCollection) {
  9236. const gc = geom;
  9237. for (let i = 0; i < gc.getNumGeometries(); i++) this.process(gc.getGeometryN(i));
  9238. }
  9239. }
  9240. processPolygon(polygon) {
  9241. const intPtPoly = new InteriorPointPolygon(polygon);
  9242. intPtPoly.process();
  9243. const width = intPtPoly.getWidth();
  9244. if (width > this._maxWidth) {
  9245. this._maxWidth = width;
  9246. this._interiorPoint = intPtPoly.getInteriorPoint();
  9247. }
  9248. }
  9249. }
  9250. class InteriorPointPolygon {
  9251. constructor() {
  9252. InteriorPointPolygon.constructor_.apply(this, arguments);
  9253. }
  9254. static constructor_() {
  9255. this._polygon = null;
  9256. this._interiorPointY = null;
  9257. this._interiorSectionWidth = 0.0;
  9258. this._interiorPoint = null;
  9259. const polygon = arguments[0];
  9260. this._polygon = polygon;
  9261. this._interiorPointY = ScanLineYOrdinateFinder.getScanLineY(polygon);
  9262. }
  9263. static isEdgeCrossingCounted(p0, p1, scanY) {
  9264. const y0 = p0.getY();
  9265. const y1 = p1.getY();
  9266. if (y0 === y1) return false;
  9267. if (y0 === scanY && y1 < scanY) return false;
  9268. if (y1 === scanY && y0 < scanY) return false;
  9269. return true;
  9270. }
  9271. static intersectsHorizontalLine() {
  9272. if (arguments.length === 2) {
  9273. const env = arguments[0],
  9274. y = arguments[1];
  9275. if (y < env.getMinY()) return false;
  9276. if (y > env.getMaxY()) return false;
  9277. return true;
  9278. } else if (arguments.length === 3) {
  9279. const p0 = arguments[0],
  9280. p1 = arguments[1],
  9281. y = arguments[2];
  9282. if (p0.getY() > y && p1.getY() > y) return false;
  9283. if (p0.getY() < y && p1.getY() < y) return false;
  9284. return true;
  9285. }
  9286. }
  9287. static intersection(p0, p1, Y) {
  9288. const x0 = p0.getX();
  9289. const x1 = p1.getX();
  9290. if (x0 === x1) return x0;
  9291. const segDX = x1 - x0;
  9292. const segDY = p1.getY() - p0.getY();
  9293. const m = segDY / segDX;
  9294. const x = x0 + (Y - p0.getY()) / m;
  9295. return x;
  9296. }
  9297. findBestMidpoint(crossings) {
  9298. if (crossings.size() === 0) return null;
  9299. Assert.isTrue(0 === crossings.size() % 2, 'Interior Point robustness failure: odd number of scanline crossings');
  9300. crossings.sort(new DoubleComparator());
  9301. for (let i = 0; i < crossings.size(); i += 2) {
  9302. const x1 = crossings.get(i);
  9303. const x2 = crossings.get(i + 1);
  9304. const width = x2 - x1;
  9305. if (width > this._interiorSectionWidth) {
  9306. this._interiorSectionWidth = width;
  9307. const interiorPointX = InteriorPointArea.avg(x1, x2);
  9308. this._interiorPoint = new Coordinate(interiorPointX, this._interiorPointY);
  9309. }
  9310. }
  9311. }
  9312. process() {
  9313. if (this._polygon.isEmpty()) return null;
  9314. this._interiorPoint = new Coordinate(this._polygon.getCoordinate());
  9315. const crossings = new ArrayList();
  9316. this.scanRing(this._polygon.getExteriorRing(), crossings);
  9317. for (let i = 0; i < this._polygon.getNumInteriorRing(); i++) this.scanRing(this._polygon.getInteriorRingN(i), crossings);
  9318. this.findBestMidpoint(crossings);
  9319. }
  9320. scanRing(ring, crossings) {
  9321. if (!InteriorPointPolygon.intersectsHorizontalLine(ring.getEnvelopeInternal(), this._interiorPointY)) return null;
  9322. const seq = ring.getCoordinateSequence();
  9323. for (let i = 1; i < seq.size(); i++) {
  9324. const ptPrev = seq.getCoordinate(i - 1);
  9325. const pt = seq.getCoordinate(i);
  9326. this.addEdgeCrossing(ptPrev, pt, this._interiorPointY, crossings);
  9327. }
  9328. }
  9329. getWidth() {
  9330. return this._interiorSectionWidth;
  9331. }
  9332. getInteriorPoint() {
  9333. return this._interiorPoint;
  9334. }
  9335. addEdgeCrossing(p0, p1, scanY, crossings) {
  9336. if (!InteriorPointPolygon.intersectsHorizontalLine(p0, p1, scanY)) return null;
  9337. if (!InteriorPointPolygon.isEdgeCrossingCounted(p0, p1, scanY)) return null;
  9338. const xInt = InteriorPointPolygon.intersection(p0, p1, scanY);
  9339. crossings.add(xInt);
  9340. }
  9341. }
  9342. class DoubleComparator {
  9343. compare(v1, v2) {
  9344. return v1 < v2 ? -1 : v1 > v2 ? +1 : 0;
  9345. }
  9346. get interfaces_() {
  9347. return [Comparator];
  9348. }
  9349. }
  9350. InteriorPointPolygon.DoubleComparator = DoubleComparator;
  9351. class ScanLineYOrdinateFinder {
  9352. constructor() {
  9353. ScanLineYOrdinateFinder.constructor_.apply(this, arguments);
  9354. }
  9355. static constructor_() {
  9356. this._poly = null;
  9357. this._centreY = null;
  9358. this._hiY = Double.MAX_VALUE;
  9359. this._loY = -Double.MAX_VALUE;
  9360. const poly = arguments[0];
  9361. this._poly = poly;
  9362. this._hiY = poly.getEnvelopeInternal().getMaxY();
  9363. this._loY = poly.getEnvelopeInternal().getMinY();
  9364. this._centreY = InteriorPointArea.avg(this._loY, this._hiY);
  9365. }
  9366. static getScanLineY(poly) {
  9367. const finder = new ScanLineYOrdinateFinder(poly);
  9368. return finder.getScanLineY();
  9369. }
  9370. updateInterval(y) {
  9371. if (y <= this._centreY) {
  9372. if (y > this._loY) this._loY = y;
  9373. } else if (y > this._centreY) {
  9374. if (y < this._hiY) this._hiY = y;
  9375. }
  9376. }
  9377. getScanLineY() {
  9378. this.process(this._poly.getExteriorRing());
  9379. for (let i = 0; i < this._poly.getNumInteriorRing(); i++) this.process(this._poly.getInteriorRingN(i));
  9380. const scanLineY = InteriorPointArea.avg(this._hiY, this._loY);
  9381. return scanLineY;
  9382. }
  9383. process(line) {
  9384. const seq = line.getCoordinateSequence();
  9385. for (let i = 0; i < seq.size(); i++) {
  9386. const y = seq.getY(i);
  9387. this.updateInterval(y);
  9388. }
  9389. }
  9390. }
  9391. InteriorPointArea.InteriorPointPolygon = InteriorPointPolygon;
  9392. InteriorPointArea.ScanLineYOrdinateFinder = ScanLineYOrdinateFinder;
  9393. class InteriorPointLine {
  9394. constructor() {
  9395. InteriorPointLine.constructor_.apply(this, arguments);
  9396. }
  9397. static constructor_() {
  9398. this._centroid = null;
  9399. this._minDistance = Double.MAX_VALUE;
  9400. this._interiorPoint = null;
  9401. const g = arguments[0];
  9402. if (g.isEmpty()) {
  9403. this._centroid = null;
  9404. } else {
  9405. this._centroid = Centroid.getCentroid(g);
  9406. g.getPrecisionModel().makePrecise(this._centroid);
  9407. }
  9408. this.addInterior(g);
  9409. if (this._interiorPoint === null) this.addEndpoints(g);
  9410. }
  9411. static getInteriorPoint(geom) {
  9412. const intPt = new InteriorPointLine(geom);
  9413. return intPt.getInteriorPoint();
  9414. }
  9415. addEndpoints() {
  9416. if (arguments[0] instanceof Geometry) {
  9417. const geom = arguments[0];
  9418. if (geom instanceof LineString) {
  9419. this.addEndpoints(geom.getCoordinates());
  9420. } else if (geom instanceof GeometryCollection) {
  9421. const gc = geom;
  9422. for (let i = 0; i < gc.getNumGeometries(); i++) this.addEndpoints(gc.getGeometryN(i));
  9423. }
  9424. } else if (arguments[0] instanceof Array) {
  9425. const pts = arguments[0];
  9426. this.add(pts[0]);
  9427. this.add(pts[pts.length - 1]);
  9428. }
  9429. }
  9430. getInteriorPoint() {
  9431. return this._interiorPoint;
  9432. }
  9433. addInterior() {
  9434. if (arguments[0] instanceof Geometry) {
  9435. const geom = arguments[0];
  9436. if (geom instanceof LineString) {
  9437. this.addInterior(geom.getCoordinates());
  9438. } else if (geom instanceof GeometryCollection) {
  9439. const gc = geom;
  9440. for (let i = 0; i < gc.getNumGeometries(); i++) this.addInterior(gc.getGeometryN(i));
  9441. }
  9442. } else if (arguments[0] instanceof Array) {
  9443. const pts = arguments[0];
  9444. for (let i = 1; i < pts.length - 1; i++) this.add(pts[i]);
  9445. }
  9446. }
  9447. add(point) {
  9448. const dist = point.distance(this._centroid);
  9449. if (dist < this._minDistance) {
  9450. this._interiorPoint = new Coordinate(point);
  9451. this._minDistance = dist;
  9452. }
  9453. }
  9454. }
  9455. class InteriorPointPoint {
  9456. constructor() {
  9457. InteriorPointPoint.constructor_.apply(this, arguments);
  9458. }
  9459. static constructor_() {
  9460. this._centroid = null;
  9461. this._minDistance = Double.MAX_VALUE;
  9462. this._interiorPoint = null;
  9463. const g = arguments[0];
  9464. this._centroid = Centroid.getCentroid(g);
  9465. this.add(g);
  9466. }
  9467. static getInteriorPoint(geom) {
  9468. const intPt = new InteriorPointPoint(geom);
  9469. return intPt.getInteriorPoint();
  9470. }
  9471. getInteriorPoint() {
  9472. return this._interiorPoint;
  9473. }
  9474. add() {
  9475. if (arguments[0] instanceof Geometry) {
  9476. const geom = arguments[0];
  9477. if (geom instanceof Point) {
  9478. this.add(geom.getCoordinate());
  9479. } else if (geom instanceof GeometryCollection) {
  9480. const gc = geom;
  9481. for (let i = 0; i < gc.getNumGeometries(); i++) this.add(gc.getGeometryN(i));
  9482. }
  9483. } else if (arguments[0] instanceof Coordinate) {
  9484. const point = arguments[0];
  9485. const dist = point.distance(this._centroid);
  9486. if (dist < this._minDistance) {
  9487. this._interiorPoint = new Coordinate(point);
  9488. this._minDistance = dist;
  9489. }
  9490. }
  9491. }
  9492. }
  9493. class BoundaryNodeRule {
  9494. isInBoundary(boundaryCount) {}
  9495. }
  9496. class Mod2BoundaryNodeRule {
  9497. isInBoundary(boundaryCount) {
  9498. return boundaryCount % 2 === 1;
  9499. }
  9500. get interfaces_() {
  9501. return [BoundaryNodeRule];
  9502. }
  9503. }
  9504. class EndPointBoundaryNodeRule {
  9505. isInBoundary(boundaryCount) {
  9506. return boundaryCount > 0;
  9507. }
  9508. get interfaces_() {
  9509. return [BoundaryNodeRule];
  9510. }
  9511. }
  9512. class MultiValentEndPointBoundaryNodeRule {
  9513. isInBoundary(boundaryCount) {
  9514. return boundaryCount > 1;
  9515. }
  9516. get interfaces_() {
  9517. return [BoundaryNodeRule];
  9518. }
  9519. }
  9520. class MonoValentEndPointBoundaryNodeRule {
  9521. isInBoundary(boundaryCount) {
  9522. return boundaryCount === 1;
  9523. }
  9524. get interfaces_() {
  9525. return [BoundaryNodeRule];
  9526. }
  9527. }
  9528. BoundaryNodeRule.Mod2BoundaryNodeRule = Mod2BoundaryNodeRule;
  9529. BoundaryNodeRule.EndPointBoundaryNodeRule = EndPointBoundaryNodeRule;
  9530. BoundaryNodeRule.MultiValentEndPointBoundaryNodeRule = MultiValentEndPointBoundaryNodeRule;
  9531. BoundaryNodeRule.MonoValentEndPointBoundaryNodeRule = MonoValentEndPointBoundaryNodeRule;
  9532. BoundaryNodeRule.MOD2_BOUNDARY_RULE = new Mod2BoundaryNodeRule();
  9533. BoundaryNodeRule.ENDPOINT_BOUNDARY_RULE = new EndPointBoundaryNodeRule();
  9534. BoundaryNodeRule.MULTIVALENT_ENDPOINT_BOUNDARY_RULE = new MultiValentEndPointBoundaryNodeRule();
  9535. BoundaryNodeRule.MONOVALENT_ENDPOINT_BOUNDARY_RULE = new MonoValentEndPointBoundaryNodeRule();
  9536. BoundaryNodeRule.OGC_SFS_BOUNDARY_RULE = BoundaryNodeRule.MOD2_BOUNDARY_RULE;
  9537. class PointLocator {
  9538. constructor() {
  9539. PointLocator.constructor_.apply(this, arguments);
  9540. }
  9541. static constructor_() {
  9542. this._boundaryRule = BoundaryNodeRule.OGC_SFS_BOUNDARY_RULE;
  9543. this._isIn = null;
  9544. this._numBoundaries = null;
  9545. if (arguments.length === 0) ; else if (arguments.length === 1) {
  9546. const boundaryRule = arguments[0];
  9547. if (boundaryRule === null) throw new IllegalArgumentException('Rule must be non-null');
  9548. this._boundaryRule = boundaryRule;
  9549. }
  9550. }
  9551. locateInPolygonRing(p, ring) {
  9552. if (!ring.getEnvelopeInternal().intersects(p)) return Location.EXTERIOR;
  9553. return PointLocation.locateInRing(p, ring.getCoordinates());
  9554. }
  9555. intersects(p, geom) {
  9556. return this.locate(p, geom) !== Location.EXTERIOR;
  9557. }
  9558. updateLocationInfo(loc) {
  9559. if (loc === Location.INTERIOR) this._isIn = true;
  9560. if (loc === Location.BOUNDARY) this._numBoundaries++;
  9561. }
  9562. computeLocation(p, geom) {
  9563. if (geom instanceof Point) this.updateLocationInfo(this.locateOnPoint(p, geom));
  9564. if (geom instanceof LineString) {
  9565. this.updateLocationInfo(this.locateOnLineString(p, geom));
  9566. } else if (geom instanceof Polygon) {
  9567. this.updateLocationInfo(this.locateInPolygon(p, geom));
  9568. } else if (geom instanceof MultiLineString) {
  9569. const ml = geom;
  9570. for (let i = 0; i < ml.getNumGeometries(); i++) {
  9571. const l = ml.getGeometryN(i);
  9572. this.updateLocationInfo(this.locateOnLineString(p, l));
  9573. }
  9574. } else if (geom instanceof MultiPolygon) {
  9575. const mpoly = geom;
  9576. for (let i = 0; i < mpoly.getNumGeometries(); i++) {
  9577. const poly = mpoly.getGeometryN(i);
  9578. this.updateLocationInfo(this.locateInPolygon(p, poly));
  9579. }
  9580. } else if (geom instanceof GeometryCollection) {
  9581. const geomi = new GeometryCollectionIterator(geom);
  9582. while (geomi.hasNext()) {
  9583. const g2 = geomi.next();
  9584. if (g2 !== geom) this.computeLocation(p, g2);
  9585. }
  9586. }
  9587. }
  9588. locateOnPoint(p, pt) {
  9589. const ptCoord = pt.getCoordinate();
  9590. if (ptCoord.equals2D(p)) return Location.INTERIOR;
  9591. return Location.EXTERIOR;
  9592. }
  9593. locateOnLineString(p, l) {
  9594. if (!l.getEnvelopeInternal().intersects(p)) return Location.EXTERIOR;
  9595. const seq = l.getCoordinateSequence();
  9596. if (!l.isClosed()) if (p.equals(seq.getCoordinate(0)) || p.equals(seq.getCoordinate(seq.size() - 1))) return Location.BOUNDARY;
  9597. if (PointLocation.isOnLine(p, seq)) return Location.INTERIOR;
  9598. return Location.EXTERIOR;
  9599. }
  9600. locateInPolygon(p, poly) {
  9601. if (poly.isEmpty()) return Location.EXTERIOR;
  9602. const shell = poly.getExteriorRing();
  9603. const shellLoc = this.locateInPolygonRing(p, shell);
  9604. if (shellLoc === Location.EXTERIOR) return Location.EXTERIOR;
  9605. if (shellLoc === Location.BOUNDARY) return Location.BOUNDARY;
  9606. for (let i = 0; i < poly.getNumInteriorRing(); i++) {
  9607. const hole = poly.getInteriorRingN(i);
  9608. const holeLoc = this.locateInPolygonRing(p, hole);
  9609. if (holeLoc === Location.INTERIOR) return Location.EXTERIOR;
  9610. if (holeLoc === Location.BOUNDARY) return Location.BOUNDARY;
  9611. }
  9612. return Location.INTERIOR;
  9613. }
  9614. locate(p, geom) {
  9615. if (geom.isEmpty()) return Location.EXTERIOR;
  9616. if (geom instanceof LineString) return this.locateOnLineString(p, geom);else if (geom instanceof Polygon) return this.locateInPolygon(p, geom);
  9617. this._isIn = false;
  9618. this._numBoundaries = 0;
  9619. this.computeLocation(p, geom);
  9620. if (this._boundaryRule.isInBoundary(this._numBoundaries)) return Location.BOUNDARY;
  9621. if (this._numBoundaries > 0 || this._isIn) return Location.INTERIOR;
  9622. return Location.EXTERIOR;
  9623. }
  9624. }
  9625. class MinimumBoundingCircle {
  9626. constructor() {
  9627. MinimumBoundingCircle.constructor_.apply(this, arguments);
  9628. }
  9629. static constructor_() {
  9630. this._input = null;
  9631. this._extremalPts = null;
  9632. this._centre = null;
  9633. this._radius = 0.0;
  9634. const geom = arguments[0];
  9635. this._input = geom;
  9636. }
  9637. static farthestPoints(pts) {
  9638. const dist01 = pts[0].distance(pts[1]);
  9639. const dist12 = pts[1].distance(pts[2]);
  9640. const dist20 = pts[2].distance(pts[0]);
  9641. if (dist01 >= dist12 && dist01 >= dist20) return [pts[0], pts[1]];
  9642. if (dist12 >= dist01 && dist12 >= dist20) return [pts[1], pts[2]];
  9643. return [pts[2], pts[0]];
  9644. }
  9645. static pointWitMinAngleWithX(pts, P) {
  9646. let minSin = Double.MAX_VALUE;
  9647. let minAngPt = null;
  9648. for (let i = 0; i < pts.length; i++) {
  9649. const p = pts[i];
  9650. if (p === P) continue;
  9651. const dx = p.x - P.x;
  9652. let dy = p.y - P.y;
  9653. if (dy < 0) dy = -dy;
  9654. const len = Math.sqrt(dx * dx + dy * dy);
  9655. const sin = dy / len;
  9656. if (sin < minSin) {
  9657. minSin = sin;
  9658. minAngPt = p;
  9659. }
  9660. }
  9661. return minAngPt;
  9662. }
  9663. static lowestPoint(pts) {
  9664. let min = pts[0];
  9665. for (let i = 1; i < pts.length; i++) if (pts[i].y < min.y) min = pts[i];
  9666. return min;
  9667. }
  9668. static pointWithMinAngleWithSegment(pts, P, Q) {
  9669. let minAng = Double.MAX_VALUE;
  9670. let minAngPt = null;
  9671. for (let i = 0; i < pts.length; i++) {
  9672. const p = pts[i];
  9673. if (p === P) continue;
  9674. if (p === Q) continue;
  9675. const ang = Angle.angleBetween(P, p, Q);
  9676. if (ang < minAng) {
  9677. minAng = ang;
  9678. minAngPt = p;
  9679. }
  9680. }
  9681. return minAngPt;
  9682. }
  9683. getRadius() {
  9684. this.compute();
  9685. return this._radius;
  9686. }
  9687. getDiameter() {
  9688. this.compute();
  9689. switch (this._extremalPts.length) {
  9690. case 0:
  9691. return this._input.getFactory().createLineString();
  9692. case 1:
  9693. return this._input.getFactory().createPoint(this._centre);
  9694. }
  9695. const p0 = this._extremalPts[0];
  9696. const p1 = this._extremalPts[1];
  9697. return this._input.getFactory().createLineString([p0, p1]);
  9698. }
  9699. getExtremalPoints() {
  9700. this.compute();
  9701. return this._extremalPts;
  9702. }
  9703. computeCirclePoints() {
  9704. if (this._input.isEmpty()) {
  9705. this._extremalPts = new Array(0).fill(null);
  9706. return null;
  9707. }
  9708. if (this._input.getNumPoints() === 1) {
  9709. const pts = this._input.getCoordinates();
  9710. this._extremalPts = [new Coordinate(pts[0])];
  9711. return null;
  9712. }
  9713. const convexHull = this._input.convexHull();
  9714. const hullPts = convexHull.getCoordinates();
  9715. let pts = hullPts;
  9716. if (hullPts[0].equals2D(hullPts[hullPts.length - 1])) {
  9717. pts = new Array(hullPts.length - 1).fill(null);
  9718. CoordinateArrays.copyDeep(hullPts, 0, pts, 0, hullPts.length - 1);
  9719. }
  9720. if (pts.length <= 2) {
  9721. this._extremalPts = CoordinateArrays.copyDeep(pts);
  9722. return null;
  9723. }
  9724. let P = MinimumBoundingCircle.lowestPoint(pts);
  9725. let Q = MinimumBoundingCircle.pointWitMinAngleWithX(pts, P);
  9726. for (let i = 0; i < pts.length; i++) {
  9727. const R = MinimumBoundingCircle.pointWithMinAngleWithSegment(pts, P, Q);
  9728. if (Angle.isObtuse(P, R, Q)) {
  9729. this._extremalPts = [new Coordinate(P), new Coordinate(Q)];
  9730. return null;
  9731. }
  9732. if (Angle.isObtuse(R, P, Q)) {
  9733. P = R;
  9734. continue;
  9735. }
  9736. if (Angle.isObtuse(R, Q, P)) {
  9737. Q = R;
  9738. continue;
  9739. }
  9740. this._extremalPts = [new Coordinate(P), new Coordinate(Q), new Coordinate(R)];
  9741. return null;
  9742. }
  9743. Assert.shouldNeverReachHere('Logic failure in Minimum Bounding Circle algorithm!');
  9744. }
  9745. compute() {
  9746. if (this._extremalPts !== null) return null;
  9747. this.computeCirclePoints();
  9748. this.computeCentre();
  9749. if (this._centre !== null) this._radius = this._centre.distance(this._extremalPts[0]);
  9750. }
  9751. getCircle() {
  9752. this.compute();
  9753. if (this._centre === null) return this._input.getFactory().createPolygon();
  9754. const centrePoint = this._input.getFactory().createPoint(this._centre);
  9755. if (this._radius === 0.0) return centrePoint;
  9756. return centrePoint.buffer(this._radius);
  9757. }
  9758. getCentre() {
  9759. this.compute();
  9760. return this._centre;
  9761. }
  9762. getMaximumDiameter() {
  9763. this.compute();
  9764. switch (this._extremalPts.length) {
  9765. case 0:
  9766. return this._input.getFactory().createLineString();
  9767. case 1:
  9768. return this._input.getFactory().createPoint(this._centre);
  9769. case 2:
  9770. return this._input.getFactory().createLineString([this._extremalPts[0], this._extremalPts[1]]);
  9771. default:
  9772. const maxDiameter = MinimumBoundingCircle.farthestPoints(this._extremalPts);
  9773. return this._input.getFactory().createLineString(maxDiameter);
  9774. }
  9775. }
  9776. computeCentre() {
  9777. switch (this._extremalPts.length) {
  9778. case 0:
  9779. this._centre = null;
  9780. break;
  9781. case 1:
  9782. this._centre = this._extremalPts[0];
  9783. break;
  9784. case 2:
  9785. this._centre = new Coordinate((this._extremalPts[0].x + this._extremalPts[1].x) / 2.0, (this._extremalPts[0].y + this._extremalPts[1].y) / 2.0);
  9786. break;
  9787. case 3:
  9788. this._centre = Triangle.circumcentre(this._extremalPts[0], this._extremalPts[1], this._extremalPts[2]);
  9789. break;
  9790. }
  9791. }
  9792. }
  9793. class MinimumDiameter {
  9794. constructor() {
  9795. MinimumDiameter.constructor_.apply(this, arguments);
  9796. }
  9797. static constructor_() {
  9798. this._inputGeom = null;
  9799. this._isConvex = null;
  9800. this._convexHullPts = null;
  9801. this._minBaseSeg = new LineSegment();
  9802. this._minWidthPt = null;
  9803. this._minPtIndex = null;
  9804. this._minWidth = 0.0;
  9805. if (arguments.length === 1) {
  9806. const inputGeom = arguments[0];
  9807. MinimumDiameter.constructor_.call(this, inputGeom, false);
  9808. } else if (arguments.length === 2) {
  9809. const inputGeom = arguments[0],
  9810. isConvex = arguments[1];
  9811. this._inputGeom = inputGeom;
  9812. this._isConvex = isConvex;
  9813. }
  9814. }
  9815. static nextIndex(pts, index) {
  9816. index++;
  9817. if (index >= pts.length) index = 0;
  9818. return index;
  9819. }
  9820. static computeC(a, b, p) {
  9821. return a * p.y - b * p.x;
  9822. }
  9823. static getMinimumDiameter(geom) {
  9824. return new MinimumDiameter(geom).getDiameter();
  9825. }
  9826. static getMinimumRectangle(geom) {
  9827. return new MinimumDiameter(geom).getMinimumRectangle();
  9828. }
  9829. static computeSegmentForLine(a, b, c) {
  9830. let p0 = null;
  9831. let p1 = null;
  9832. if (Math.abs(b) > Math.abs(a)) {
  9833. p0 = new Coordinate(0.0, c / b);
  9834. p1 = new Coordinate(1.0, c / b - a / b);
  9835. } else {
  9836. p0 = new Coordinate(c / a, 0.0);
  9837. p1 = new Coordinate(c / a - b / a, 1.0);
  9838. }
  9839. return new LineSegment(p0, p1);
  9840. }
  9841. getWidthCoordinate() {
  9842. this.computeMinimumDiameter();
  9843. return this._minWidthPt;
  9844. }
  9845. getSupportingSegment() {
  9846. this.computeMinimumDiameter();
  9847. return this._inputGeom.getFactory().createLineString([this._minBaseSeg.p0, this._minBaseSeg.p1]);
  9848. }
  9849. getDiameter() {
  9850. this.computeMinimumDiameter();
  9851. if (this._minWidthPt === null) return this._inputGeom.getFactory().createLineString();
  9852. const basePt = this._minBaseSeg.project(this._minWidthPt);
  9853. return this._inputGeom.getFactory().createLineString([basePt, this._minWidthPt]);
  9854. }
  9855. computeWidthConvex(convexGeom) {
  9856. if (convexGeom instanceof Polygon) this._convexHullPts = convexGeom.getExteriorRing().getCoordinates();else this._convexHullPts = convexGeom.getCoordinates();
  9857. if (this._convexHullPts.length === 0) {
  9858. this._minWidth = 0.0;
  9859. this._minWidthPt = null;
  9860. this._minBaseSeg = null;
  9861. } else if (this._convexHullPts.length === 1) {
  9862. this._minWidth = 0.0;
  9863. this._minWidthPt = this._convexHullPts[0];
  9864. this._minBaseSeg.p0 = this._convexHullPts[0];
  9865. this._minBaseSeg.p1 = this._convexHullPts[0];
  9866. } else if (this._convexHullPts.length === 2 || this._convexHullPts.length === 3) {
  9867. this._minWidth = 0.0;
  9868. this._minWidthPt = this._convexHullPts[0];
  9869. this._minBaseSeg.p0 = this._convexHullPts[0];
  9870. this._minBaseSeg.p1 = this._convexHullPts[1];
  9871. } else {
  9872. this.computeConvexRingMinDiameter(this._convexHullPts);
  9873. }
  9874. }
  9875. computeConvexRingMinDiameter(pts) {
  9876. this._minWidth = Double.MAX_VALUE;
  9877. let currMaxIndex = 1;
  9878. const seg = new LineSegment();
  9879. for (let i = 0; i < pts.length - 1; i++) {
  9880. seg.p0 = pts[i];
  9881. seg.p1 = pts[i + 1];
  9882. currMaxIndex = this.findMaxPerpDistance(pts, seg, currMaxIndex);
  9883. }
  9884. }
  9885. computeMinimumDiameter() {
  9886. if (this._minWidthPt !== null) return null;
  9887. if (this._isConvex) {
  9888. this.computeWidthConvex(this._inputGeom);
  9889. } else {
  9890. const convexGeom = new ConvexHull(this._inputGeom).getConvexHull();
  9891. this.computeWidthConvex(convexGeom);
  9892. }
  9893. }
  9894. getLength() {
  9895. this.computeMinimumDiameter();
  9896. return this._minWidth;
  9897. }
  9898. findMaxPerpDistance(pts, seg, startIndex) {
  9899. let maxPerpDistance = seg.distancePerpendicular(pts[startIndex]);
  9900. let nextPerpDistance = maxPerpDistance;
  9901. let maxIndex = startIndex;
  9902. let nextIndex = maxIndex;
  9903. while (nextPerpDistance >= maxPerpDistance) {
  9904. maxPerpDistance = nextPerpDistance;
  9905. maxIndex = nextIndex;
  9906. nextIndex = MinimumDiameter.nextIndex(pts, maxIndex);
  9907. nextPerpDistance = seg.distancePerpendicular(pts[nextIndex]);
  9908. }
  9909. if (maxPerpDistance < this._minWidth) {
  9910. this._minPtIndex = maxIndex;
  9911. this._minWidth = maxPerpDistance;
  9912. this._minWidthPt = pts[this._minPtIndex];
  9913. this._minBaseSeg = new LineSegment(seg);
  9914. }
  9915. return maxIndex;
  9916. }
  9917. getMinimumRectangle() {
  9918. this.computeMinimumDiameter();
  9919. if (this._minWidth === 0.0) {
  9920. if (this._minBaseSeg.p0.equals2D(this._minBaseSeg.p1)) return this._inputGeom.getFactory().createPoint(this._minBaseSeg.p0);
  9921. return this._minBaseSeg.toGeometry(this._inputGeom.getFactory());
  9922. }
  9923. const dx = this._minBaseSeg.p1.x - this._minBaseSeg.p0.x;
  9924. const dy = this._minBaseSeg.p1.y - this._minBaseSeg.p0.y;
  9925. let minPara = Double.MAX_VALUE;
  9926. let maxPara = -Double.MAX_VALUE;
  9927. let minPerp = Double.MAX_VALUE;
  9928. let maxPerp = -Double.MAX_VALUE;
  9929. for (let i = 0; i < this._convexHullPts.length; i++) {
  9930. const paraC = MinimumDiameter.computeC(dx, dy, this._convexHullPts[i]);
  9931. if (paraC > maxPara) maxPara = paraC;
  9932. if (paraC < minPara) minPara = paraC;
  9933. const perpC = MinimumDiameter.computeC(-dy, dx, this._convexHullPts[i]);
  9934. if (perpC > maxPerp) maxPerp = perpC;
  9935. if (perpC < minPerp) minPerp = perpC;
  9936. }
  9937. const maxPerpLine = MinimumDiameter.computeSegmentForLine(-dx, -dy, maxPerp);
  9938. const minPerpLine = MinimumDiameter.computeSegmentForLine(-dx, -dy, minPerp);
  9939. const maxParaLine = MinimumDiameter.computeSegmentForLine(-dy, dx, maxPara);
  9940. const minParaLine = MinimumDiameter.computeSegmentForLine(-dy, dx, minPara);
  9941. const p0 = maxParaLine.lineIntersection(maxPerpLine);
  9942. const p1 = minParaLine.lineIntersection(maxPerpLine);
  9943. const p2 = minParaLine.lineIntersection(minPerpLine);
  9944. const p3 = maxParaLine.lineIntersection(minPerpLine);
  9945. const shell = this._inputGeom.getFactory().createLinearRing([p0, p1, p2, p3, p0]);
  9946. return this._inputGeom.getFactory().createPolygon(shell);
  9947. }
  9948. }
  9949. var algorithm = /*#__PURE__*/Object.freeze({
  9950. __proto__: null,
  9951. distance: distance_module,
  9952. locate: locate,
  9953. match: match,
  9954. Angle: Angle,
  9955. Area: Area,
  9956. Centroid: Centroid,
  9957. ConvexHull: ConvexHull,
  9958. Distance: Distance,
  9959. InteriorPointArea: InteriorPointArea,
  9960. InteriorPointLine: InteriorPointLine,
  9961. InteriorPointPoint: InteriorPointPoint,
  9962. Length: Length,
  9963. Orientation: Orientation,
  9964. PointLocation: PointLocation,
  9965. PointLocator: PointLocator,
  9966. RobustLineIntersector: RobustLineIntersector,
  9967. MinimumBoundingCircle: MinimumBoundingCircle,
  9968. MinimumDiameter: MinimumDiameter
  9969. });
  9970. class Densifier {
  9971. constructor() {
  9972. Densifier.constructor_.apply(this, arguments);
  9973. }
  9974. static constructor_() {
  9975. this._inputGeom = null;
  9976. this._distanceTolerance = null;
  9977. const inputGeom = arguments[0];
  9978. this._inputGeom = inputGeom;
  9979. }
  9980. static densifyPoints(pts, distanceTolerance, precModel) {
  9981. const seg = new LineSegment();
  9982. const coordList = new CoordinateList();
  9983. for (let i = 0; i < pts.length - 1; i++) {
  9984. seg.p0 = pts[i];
  9985. seg.p1 = pts[i + 1];
  9986. coordList.add(seg.p0, false);
  9987. const len = seg.getLength();
  9988. const densifiedSegCount = Math.trunc(len / distanceTolerance) + 1;
  9989. if (densifiedSegCount > 1) {
  9990. const densifiedSegLen = len / densifiedSegCount;
  9991. for (let j = 1; j < densifiedSegCount; j++) {
  9992. const segFract = j * densifiedSegLen / len;
  9993. const p = seg.pointAlong(segFract);
  9994. precModel.makePrecise(p);
  9995. coordList.add(p, false);
  9996. }
  9997. }
  9998. }
  9999. coordList.add(pts[pts.length - 1], false);
  10000. return coordList.toCoordinateArray();
  10001. }
  10002. static densify(geom, distanceTolerance) {
  10003. const densifier = new Densifier(geom);
  10004. densifier.setDistanceTolerance(distanceTolerance);
  10005. return densifier.getResultGeometry();
  10006. }
  10007. getResultGeometry() {
  10008. return new DensifyTransformer(this._distanceTolerance).transform(this._inputGeom);
  10009. }
  10010. setDistanceTolerance(distanceTolerance) {
  10011. if (distanceTolerance <= 0.0) throw new IllegalArgumentException('Tolerance must be positive');
  10012. this._distanceTolerance = distanceTolerance;
  10013. }
  10014. }
  10015. class DensifyTransformer extends GeometryTransformer {
  10016. constructor() {
  10017. super();
  10018. DensifyTransformer.constructor_.apply(this, arguments);
  10019. }
  10020. static constructor_() {
  10021. this.distanceTolerance = null;
  10022. const distanceTolerance = arguments[0];
  10023. this.distanceTolerance = distanceTolerance;
  10024. }
  10025. transformMultiPolygon(geom, parent) {
  10026. const roughGeom = super.transformMultiPolygon.call(this, geom, parent);
  10027. return this.createValidArea(roughGeom);
  10028. }
  10029. transformPolygon(geom, parent) {
  10030. const roughGeom = super.transformPolygon.call(this, geom, parent);
  10031. if (parent instanceof MultiPolygon) return roughGeom;
  10032. return this.createValidArea(roughGeom);
  10033. }
  10034. transformCoordinates(coords, parent) {
  10035. const inputPts = coords.toCoordinateArray();
  10036. let newPts = Densifier.densifyPoints(inputPts, this.distanceTolerance, parent.getPrecisionModel());
  10037. if (parent instanceof LineString && newPts.length === 1) newPts = new Array(0).fill(null);
  10038. return this._factory.getCoordinateSequenceFactory().create(newPts);
  10039. }
  10040. createValidArea(roughAreaGeom) {
  10041. return roughAreaGeom.buffer(0.0);
  10042. }
  10043. }
  10044. Densifier.DensifyTransformer = DensifyTransformer;
  10045. var densify = /*#__PURE__*/Object.freeze({
  10046. __proto__: null,
  10047. Densifier: Densifier
  10048. });
  10049. class Quadrant {
  10050. static isNorthern(quad) {
  10051. return quad === Quadrant.NE || quad === Quadrant.NW;
  10052. }
  10053. static isOpposite(quad1, quad2) {
  10054. if (quad1 === quad2) return false;
  10055. const diff = (quad1 - quad2 + 4) % 4;
  10056. if (diff === 2) return true;
  10057. return false;
  10058. }
  10059. static commonHalfPlane(quad1, quad2) {
  10060. if (quad1 === quad2) return quad1;
  10061. const diff = (quad1 - quad2 + 4) % 4;
  10062. if (diff === 2) return -1;
  10063. const min = quad1 < quad2 ? quad1 : quad2;
  10064. const max = quad1 > quad2 ? quad1 : quad2;
  10065. if (min === 0 && max === 3) return 3;
  10066. return min;
  10067. }
  10068. static isInHalfPlane(quad, halfPlane) {
  10069. if (halfPlane === Quadrant.SE) return quad === Quadrant.SE || quad === Quadrant.SW;
  10070. return quad === halfPlane || quad === halfPlane + 1;
  10071. }
  10072. static quadrant() {
  10073. if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') {
  10074. const dx = arguments[0],
  10075. dy = arguments[1];
  10076. if (dx === 0.0 && dy === 0.0) throw new IllegalArgumentException('Cannot compute the quadrant for point ( ' + dx + ', ' + dy + ' )');
  10077. if (dx >= 0.0) {
  10078. if (dy >= 0.0) return Quadrant.NE;else return Quadrant.SE;
  10079. } else if (dy >= 0.0) return Quadrant.NW;else return Quadrant.SW;
  10080. } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Coordinate) {
  10081. const p0 = arguments[0],
  10082. p1 = arguments[1];
  10083. if (p1.x === p0.x && p1.y === p0.y) throw new IllegalArgumentException('Cannot compute the quadrant for two identical points ' + p0);
  10084. if (p1.x >= p0.x) {
  10085. if (p1.y >= p0.y) return Quadrant.NE;else return Quadrant.SE;
  10086. } else if (p1.y >= p0.y) return Quadrant.NW;else return Quadrant.SW;
  10087. }
  10088. }
  10089. }
  10090. Quadrant.NE = 0;
  10091. Quadrant.NW = 1;
  10092. Quadrant.SW = 2;
  10093. Quadrant.SE = 3;
  10094. class HalfEdge {
  10095. constructor() {
  10096. HalfEdge.constructor_.apply(this, arguments);
  10097. }
  10098. static constructor_() {
  10099. this._orig = null;
  10100. this._sym = null;
  10101. this._next = null;
  10102. const orig = arguments[0];
  10103. this._orig = orig;
  10104. }
  10105. static create(p0, p1) {
  10106. const e0 = new HalfEdge(p0);
  10107. const e1 = new HalfEdge(p1);
  10108. e0.link(e1);
  10109. return e0;
  10110. }
  10111. find(dest) {
  10112. let oNext = this;
  10113. do {
  10114. if (oNext === null) return null;
  10115. if (oNext.dest().equals2D(dest)) return oNext;
  10116. oNext = oNext.oNext();
  10117. } while (oNext !== this);
  10118. return null;
  10119. }
  10120. dest() {
  10121. return this._sym._orig;
  10122. }
  10123. isEdgesSorted() {
  10124. const lowest = this.findLowest();
  10125. let e = lowest;
  10126. do {
  10127. const eNext = e.oNext();
  10128. if (eNext === lowest) break;
  10129. const isSorted = eNext.compareTo(e) > 0;
  10130. if (!isSorted) return false;
  10131. e = eNext;
  10132. } while (e !== lowest);
  10133. return true;
  10134. }
  10135. oNext() {
  10136. return this._sym._next;
  10137. }
  10138. directionY() {
  10139. return this.directionPt().getY() - this._orig.getY();
  10140. }
  10141. insert(eAdd) {
  10142. if (this.oNext() === this) {
  10143. this.insertAfter(eAdd);
  10144. return null;
  10145. }
  10146. const ePrev = this.insertionEdge(eAdd);
  10147. ePrev.insertAfter(eAdd);
  10148. }
  10149. insertAfter(e) {
  10150. Assert.equals(this._orig, e.orig());
  10151. const save = this.oNext();
  10152. this._sym.setNext(e);
  10153. e.sym().setNext(save);
  10154. }
  10155. degree() {
  10156. let degree = 0;
  10157. let e = this;
  10158. do {
  10159. degree++;
  10160. e = e.oNext();
  10161. } while (e !== this);
  10162. return degree;
  10163. }
  10164. equals() {
  10165. if (arguments.length === 2 && arguments[1] instanceof Coordinate && arguments[0] instanceof Coordinate) {
  10166. const p0 = arguments[0],
  10167. p1 = arguments[1];
  10168. return this._orig.equals2D(p0) && this._sym._orig.equals(p1);
  10169. }
  10170. }
  10171. findLowest() {
  10172. let lowest = this;
  10173. let e = this.oNext();
  10174. do {
  10175. if (e.compareTo(lowest) < 0) lowest = e;
  10176. e = e.oNext();
  10177. } while (e !== this);
  10178. return lowest;
  10179. }
  10180. directionPt() {
  10181. return this.dest();
  10182. }
  10183. sym() {
  10184. return this._sym;
  10185. }
  10186. prev() {
  10187. return this._sym.next()._sym;
  10188. }
  10189. compareAngularDirection(e) {
  10190. const dx = this.directionX();
  10191. const dy = this.directionY();
  10192. const dx2 = e.directionX();
  10193. const dy2 = e.directionY();
  10194. if (dx === dx2 && dy === dy2) return 0;
  10195. const quadrant = Quadrant.quadrant(dx, dy);
  10196. const quadrant2 = Quadrant.quadrant(dx2, dy2);
  10197. if (quadrant > quadrant2) return 1;
  10198. if (quadrant < quadrant2) return -1;
  10199. const dir1 = this.directionPt();
  10200. const dir2 = e.directionPt();
  10201. return Orientation.index(e._orig, dir2, dir1);
  10202. }
  10203. prevNode() {
  10204. let e = this;
  10205. while (e.degree() === 2) {
  10206. e = e.prev();
  10207. if (e === this) return null;
  10208. }
  10209. return e;
  10210. }
  10211. directionX() {
  10212. return this.directionPt().getX() - this._orig.getX();
  10213. }
  10214. insertionEdge(eAdd) {
  10215. let ePrev = this;
  10216. do {
  10217. const eNext = ePrev.oNext();
  10218. if (eNext.compareTo(ePrev) > 0 && eAdd.compareTo(ePrev) >= 0 && eAdd.compareTo(eNext) <= 0) return ePrev;
  10219. if (eNext.compareTo(ePrev) <= 0 && (eAdd.compareTo(eNext) <= 0 || eAdd.compareTo(ePrev) >= 0)) return ePrev;
  10220. ePrev = eNext;
  10221. } while (ePrev !== this);
  10222. Assert.shouldNeverReachHere();
  10223. return null;
  10224. }
  10225. compareTo(obj) {
  10226. const e = obj;
  10227. const comp = this.compareAngularDirection(e);
  10228. return comp;
  10229. }
  10230. toStringNode() {
  10231. const orig = this.orig();
  10232. this.dest();
  10233. const sb = new StringBuilder();
  10234. sb.append('Node( ' + WKTWriter.format(orig) + ' )' + '\n');
  10235. let e = this;
  10236. do {
  10237. sb.append(' -> ' + e);
  10238. sb.append('\n');
  10239. e = e.oNext();
  10240. } while (e !== this);
  10241. return sb.toString();
  10242. }
  10243. link(sym) {
  10244. this.setSym(sym);
  10245. sym.setSym(this);
  10246. this.setNext(sym);
  10247. sym.setNext(this);
  10248. }
  10249. next() {
  10250. return this._next;
  10251. }
  10252. setSym(e) {
  10253. this._sym = e;
  10254. }
  10255. orig() {
  10256. return this._orig;
  10257. }
  10258. toString() {
  10259. return 'HE(' + this._orig.x + ' ' + this._orig.y + ', ' + this._sym._orig.x + ' ' + this._sym._orig.y + ')';
  10260. }
  10261. toStringNodeEdge() {
  10262. return ' -> (' + WKTWriter.format(this.dest());
  10263. }
  10264. setNext(e) {
  10265. this._next = e;
  10266. }
  10267. }
  10268. class MarkHalfEdge extends HalfEdge {
  10269. constructor() {
  10270. super();
  10271. MarkHalfEdge.constructor_.apply(this, arguments);
  10272. }
  10273. static constructor_() {
  10274. this._isMarked = false;
  10275. const orig = arguments[0];
  10276. HalfEdge.constructor_.call(this, orig);
  10277. }
  10278. static setMarkBoth(e, isMarked) {
  10279. e.setMark(isMarked);
  10280. e.sym().setMark(isMarked);
  10281. }
  10282. static isMarked(e) {
  10283. return e.isMarked();
  10284. }
  10285. static setMark(e, isMarked) {
  10286. e.setMark(isMarked);
  10287. }
  10288. static markBoth(e) {
  10289. e.mark();
  10290. e.sym().mark();
  10291. }
  10292. static mark(e) {
  10293. e.mark();
  10294. }
  10295. mark() {
  10296. this._isMarked = true;
  10297. }
  10298. setMark(isMarked) {
  10299. this._isMarked = isMarked;
  10300. }
  10301. isMarked() {
  10302. return this._isMarked;
  10303. }
  10304. }
  10305. class EdgeGraph {
  10306. constructor() {
  10307. EdgeGraph.constructor_.apply(this, arguments);
  10308. }
  10309. static constructor_() {
  10310. this._vertexMap = new HashMap();
  10311. }
  10312. static isValidEdge(orig, dest) {
  10313. const cmp = dest.compareTo(orig);
  10314. return cmp !== 0;
  10315. }
  10316. insert(orig, dest, eAdj) {
  10317. const e = this.create(orig, dest);
  10318. if (eAdj !== null) eAdj.insert(e);else this._vertexMap.put(orig, e);
  10319. const eAdjDest = this._vertexMap.get(dest);
  10320. if (eAdjDest !== null) eAdjDest.insert(e.sym());else this._vertexMap.put(dest, e.sym());
  10321. return e;
  10322. }
  10323. create(p0, p1) {
  10324. const e0 = this.createEdge(p0);
  10325. const e1 = this.createEdge(p1);
  10326. e0.link(e1);
  10327. return e0;
  10328. }
  10329. createEdge(orig) {
  10330. return new HalfEdge(orig);
  10331. }
  10332. addEdge(orig, dest) {
  10333. if (!EdgeGraph.isValidEdge(orig, dest)) return null;
  10334. const eAdj = this._vertexMap.get(orig);
  10335. let eSame = null;
  10336. if (eAdj !== null) eSame = eAdj.find(dest);
  10337. if (eSame !== null) return eSame;
  10338. const e = this.insert(orig, dest, eAdj);
  10339. return e;
  10340. }
  10341. getVertexEdges() {
  10342. return this._vertexMap.values();
  10343. }
  10344. findEdge(orig, dest) {
  10345. const e = this._vertexMap.get(orig);
  10346. if (e === null) return null;
  10347. return e.find(dest);
  10348. }
  10349. }
  10350. class DissolveHalfEdge extends MarkHalfEdge {
  10351. constructor() {
  10352. super();
  10353. DissolveHalfEdge.constructor_.apply(this, arguments);
  10354. }
  10355. static constructor_() {
  10356. this._isStart = false;
  10357. const orig = arguments[0];
  10358. MarkHalfEdge.constructor_.call(this, orig);
  10359. }
  10360. setStart() {
  10361. this._isStart = true;
  10362. }
  10363. isStart() {
  10364. return this._isStart;
  10365. }
  10366. }
  10367. class DissolveEdgeGraph extends EdgeGraph {
  10368. constructor() {
  10369. super();
  10370. }
  10371. createEdge(p0) {
  10372. return new DissolveHalfEdge(p0);
  10373. }
  10374. }
  10375. class LineDissolver {
  10376. constructor() {
  10377. LineDissolver.constructor_.apply(this, arguments);
  10378. }
  10379. static constructor_() {
  10380. this._result = null;
  10381. this._factory = null;
  10382. this._graph = null;
  10383. this._lines = new ArrayList();
  10384. this._nodeEdgeStack = new Stack();
  10385. this._ringStartEdge = null;
  10386. this._graph = new DissolveEdgeGraph();
  10387. }
  10388. static dissolve(g) {
  10389. const d = new LineDissolver();
  10390. d.add(g);
  10391. return d.getResult();
  10392. }
  10393. addLine(line) {
  10394. this._lines.add(this._factory.createLineString(line.toCoordinateArray()));
  10395. }
  10396. updateRingStartEdge(e) {
  10397. if (!e.isStart()) {
  10398. e = e.sym();
  10399. if (!e.isStart()) return null;
  10400. }
  10401. if (this._ringStartEdge === null) {
  10402. this._ringStartEdge = e;
  10403. return null;
  10404. }
  10405. if (e.orig().compareTo(this._ringStartEdge.orig()) < 0) this._ringStartEdge = e;
  10406. }
  10407. getResult() {
  10408. if (this._result === null) this.computeResult();
  10409. return this._result;
  10410. }
  10411. process(e) {
  10412. let eNode = e.prevNode();
  10413. if (eNode === null) eNode = e;
  10414. this.stackEdges(eNode);
  10415. this.buildLines();
  10416. }
  10417. buildRing(eStartRing) {
  10418. const line = new CoordinateList();
  10419. let e = eStartRing;
  10420. line.add(e.orig().copy(), false);
  10421. while (e.sym().degree() === 2) {
  10422. const eNext = e.next();
  10423. if (eNext === eStartRing) break;
  10424. line.add(eNext.orig().copy(), false);
  10425. e = eNext;
  10426. }
  10427. line.add(e.dest().copy(), false);
  10428. this.addLine(line);
  10429. }
  10430. buildLine(eStart) {
  10431. const line = new CoordinateList();
  10432. let e = eStart;
  10433. this._ringStartEdge = null;
  10434. MarkHalfEdge.markBoth(e);
  10435. line.add(e.orig().copy(), false);
  10436. while (e.sym().degree() === 2) {
  10437. this.updateRingStartEdge(e);
  10438. const eNext = e.next();
  10439. if (eNext === eStart) {
  10440. this.buildRing(this._ringStartEdge);
  10441. return null;
  10442. }
  10443. line.add(eNext.orig().copy(), false);
  10444. e = eNext;
  10445. MarkHalfEdge.markBoth(e);
  10446. }
  10447. line.add(e.dest().clone(), false);
  10448. this.stackEdges(e.sym());
  10449. this.addLine(line);
  10450. }
  10451. stackEdges(node) {
  10452. let e = node;
  10453. do {
  10454. if (!MarkHalfEdge.isMarked(e)) this._nodeEdgeStack.add(e);
  10455. e = e.oNext();
  10456. } while (e !== node);
  10457. }
  10458. computeResult() {
  10459. const edges = this._graph.getVertexEdges();
  10460. for (let i = edges.iterator(); i.hasNext();) {
  10461. const e = i.next();
  10462. if (MarkHalfEdge.isMarked(e)) continue;
  10463. this.process(e);
  10464. }
  10465. this._result = this._factory.buildGeometry(this._lines);
  10466. }
  10467. buildLines() {
  10468. while (!this._nodeEdgeStack.empty()) {
  10469. const e = this._nodeEdgeStack.pop();
  10470. if (MarkHalfEdge.isMarked(e)) continue;
  10471. this.buildLine(e);
  10472. }
  10473. }
  10474. add() {
  10475. if (arguments[0] instanceof Geometry) {
  10476. const geometry = arguments[0];
  10477. geometry.apply(new class {
  10478. get interfaces_() {
  10479. return [GeometryComponentFilter];
  10480. }
  10481. filter(component) {
  10482. if (component instanceof LineString) this.add(component);
  10483. }
  10484. }());
  10485. } else if (hasInterface(arguments[0], Collection)) {
  10486. const geometries = arguments[0];
  10487. for (let i = geometries.iterator(); i.hasNext();) {
  10488. const geometry = i.next();
  10489. this.add(geometry);
  10490. }
  10491. } else if (arguments[0] instanceof LineString) {
  10492. const lineString = arguments[0];
  10493. if (this._factory === null) this._factory = lineString.getFactory();
  10494. const seq = lineString.getCoordinateSequence();
  10495. let doneStart = false;
  10496. for (let i = 1; i < seq.size(); i++) {
  10497. const e = this._graph.addEdge(seq.getCoordinate(i - 1), seq.getCoordinate(i));
  10498. if (e === null) continue;
  10499. if (!doneStart) {
  10500. e.setStart();
  10501. doneStart = true;
  10502. }
  10503. }
  10504. }
  10505. }
  10506. }
  10507. var dissolve = /*#__PURE__*/Object.freeze({
  10508. __proto__: null,
  10509. LineDissolver: LineDissolver
  10510. });
  10511. class Position {
  10512. static opposite(position) {
  10513. if (position === Position.LEFT) return Position.RIGHT;
  10514. if (position === Position.RIGHT) return Position.LEFT;
  10515. return position;
  10516. }
  10517. }
  10518. Position.ON = 0;
  10519. Position.LEFT = 1;
  10520. Position.RIGHT = 2;
  10521. class MonotoneChain$1 {
  10522. constructor() {
  10523. MonotoneChain$1.constructor_.apply(this, arguments);
  10524. }
  10525. static constructor_() {
  10526. this.mce = null;
  10527. this.chainIndex = null;
  10528. const mce = arguments[0],
  10529. chainIndex = arguments[1];
  10530. this.mce = mce;
  10531. this.chainIndex = chainIndex;
  10532. }
  10533. computeIntersections(mc, si) {
  10534. this.mce.computeIntersectsForChain(this.chainIndex, mc.mce, mc.chainIndex, si);
  10535. }
  10536. }
  10537. class SweepLineEvent {
  10538. constructor() {
  10539. SweepLineEvent.constructor_.apply(this, arguments);
  10540. }
  10541. static constructor_() {
  10542. this._label = null;
  10543. this._xValue = null;
  10544. this._eventType = null;
  10545. this._insertEvent = null;
  10546. this._deleteEventIndex = null;
  10547. this._obj = null;
  10548. if (arguments.length === 2) {
  10549. const x = arguments[0],
  10550. insertEvent = arguments[1];
  10551. this._eventType = SweepLineEvent.DELETE;
  10552. this._xValue = x;
  10553. this._insertEvent = insertEvent;
  10554. } else if (arguments.length === 3) {
  10555. const label = arguments[0],
  10556. x = arguments[1],
  10557. obj = arguments[2];
  10558. this._eventType = SweepLineEvent.INSERT;
  10559. this._label = label;
  10560. this._xValue = x;
  10561. this._obj = obj;
  10562. }
  10563. }
  10564. isDelete() {
  10565. return this._eventType === SweepLineEvent.DELETE;
  10566. }
  10567. setDeleteEventIndex(deleteEventIndex) {
  10568. this._deleteEventIndex = deleteEventIndex;
  10569. }
  10570. getObject() {
  10571. return this._obj;
  10572. }
  10573. compareTo(o) {
  10574. const pe = o;
  10575. if (this._xValue < pe._xValue) return -1;
  10576. if (this._xValue > pe._xValue) return 1;
  10577. if (this._eventType < pe._eventType) return -1;
  10578. if (this._eventType > pe._eventType) return 1;
  10579. return 0;
  10580. }
  10581. getInsertEvent() {
  10582. return this._insertEvent;
  10583. }
  10584. isInsert() {
  10585. return this._eventType === SweepLineEvent.INSERT;
  10586. }
  10587. isSameLabel(ev) {
  10588. if (this._label === null) return false;
  10589. return this._label === ev._label;
  10590. }
  10591. getDeleteEventIndex() {
  10592. return this._deleteEventIndex;
  10593. }
  10594. get interfaces_() {
  10595. return [Comparable];
  10596. }
  10597. }
  10598. SweepLineEvent.INSERT = 1;
  10599. SweepLineEvent.DELETE = 2;
  10600. class EdgeSetIntersector {}
  10601. class SegmentIntersector$1 {
  10602. constructor() {
  10603. SegmentIntersector$1.constructor_.apply(this, arguments);
  10604. }
  10605. static constructor_() {
  10606. this._hasIntersection = false;
  10607. this._hasProper = false;
  10608. this._hasProperInterior = false;
  10609. this._properIntersectionPoint = null;
  10610. this._li = null;
  10611. this._includeProper = null;
  10612. this._recordIsolated = null;
  10613. this._isSelfIntersection = null;
  10614. this._numIntersections = 0;
  10615. this.numTests = 0;
  10616. this._bdyNodes = null;
  10617. this._isDone = false;
  10618. this._isDoneWhenProperInt = false;
  10619. const li = arguments[0],
  10620. includeProper = arguments[1],
  10621. recordIsolated = arguments[2];
  10622. this._li = li;
  10623. this._includeProper = includeProper;
  10624. this._recordIsolated = recordIsolated;
  10625. }
  10626. static isAdjacentSegments(i1, i2) {
  10627. return Math.abs(i1 - i2) === 1;
  10628. }
  10629. isTrivialIntersection(e0, segIndex0, e1, segIndex1) {
  10630. if (e0 === e1) if (this._li.getIntersectionNum() === 1) {
  10631. if (SegmentIntersector$1.isAdjacentSegments(segIndex0, segIndex1)) return true;
  10632. if (e0.isClosed()) {
  10633. const maxSegIndex = e0.getNumPoints() - 1;
  10634. if (segIndex0 === 0 && segIndex1 === maxSegIndex || segIndex1 === 0 && segIndex0 === maxSegIndex) return true;
  10635. }
  10636. }
  10637. return false;
  10638. }
  10639. getProperIntersectionPoint() {
  10640. return this._properIntersectionPoint;
  10641. }
  10642. setIsDoneIfProperInt(isDoneWhenProperInt) {
  10643. this._isDoneWhenProperInt = isDoneWhenProperInt;
  10644. }
  10645. hasProperInteriorIntersection() {
  10646. return this._hasProperInterior;
  10647. }
  10648. isBoundaryPointInternal(li, bdyNodes) {
  10649. for (let i = bdyNodes.iterator(); i.hasNext();) {
  10650. const node = i.next();
  10651. const pt = node.getCoordinate();
  10652. if (li.isIntersection(pt)) return true;
  10653. }
  10654. return false;
  10655. }
  10656. hasProperIntersection() {
  10657. return this._hasProper;
  10658. }
  10659. hasIntersection() {
  10660. return this._hasIntersection;
  10661. }
  10662. isDone() {
  10663. return this._isDone;
  10664. }
  10665. isBoundaryPoint(li, bdyNodes) {
  10666. if (bdyNodes === null) return false;
  10667. if (this.isBoundaryPointInternal(li, bdyNodes[0])) return true;
  10668. if (this.isBoundaryPointInternal(li, bdyNodes[1])) return true;
  10669. return false;
  10670. }
  10671. setBoundaryNodes(bdyNodes0, bdyNodes1) {
  10672. this._bdyNodes = new Array(2).fill(null);
  10673. this._bdyNodes[0] = bdyNodes0;
  10674. this._bdyNodes[1] = bdyNodes1;
  10675. }
  10676. addIntersections(e0, segIndex0, e1, segIndex1) {
  10677. if (e0 === e1 && segIndex0 === segIndex1) return null;
  10678. this.numTests++;
  10679. const p00 = e0.getCoordinates()[segIndex0];
  10680. const p01 = e0.getCoordinates()[segIndex0 + 1];
  10681. const p10 = e1.getCoordinates()[segIndex1];
  10682. const p11 = e1.getCoordinates()[segIndex1 + 1];
  10683. this._li.computeIntersection(p00, p01, p10, p11);
  10684. if (this._li.hasIntersection()) {
  10685. if (this._recordIsolated) {
  10686. e0.setIsolated(false);
  10687. e1.setIsolated(false);
  10688. }
  10689. this._numIntersections++;
  10690. if (!this.isTrivialIntersection(e0, segIndex0, e1, segIndex1)) {
  10691. this._hasIntersection = true;
  10692. if (this._includeProper || !this._li.isProper()) {
  10693. e0.addIntersections(this._li, segIndex0, 0);
  10694. e1.addIntersections(this._li, segIndex1, 1);
  10695. }
  10696. if (this._li.isProper()) {
  10697. this._properIntersectionPoint = this._li.getIntersection(0).copy();
  10698. this._hasProper = true;
  10699. if (this._isDoneWhenProperInt) this._isDone = true;
  10700. if (!this.isBoundaryPoint(this._li, this._bdyNodes)) this._hasProperInterior = true;
  10701. }
  10702. }
  10703. }
  10704. }
  10705. }
  10706. class SimpleMCSweepLineIntersector extends EdgeSetIntersector {
  10707. constructor() {
  10708. super();
  10709. SimpleMCSweepLineIntersector.constructor_.apply(this, arguments);
  10710. }
  10711. static constructor_() {
  10712. this.events = new ArrayList();
  10713. this.nOverlaps = null;
  10714. }
  10715. prepareEvents() {
  10716. Collections.sort(this.events);
  10717. for (let i = 0; i < this.events.size(); i++) {
  10718. const ev = this.events.get(i);
  10719. if (ev.isDelete()) ev.getInsertEvent().setDeleteEventIndex(i);
  10720. }
  10721. }
  10722. computeIntersections() {
  10723. if (arguments.length === 1) {
  10724. const si = arguments[0];
  10725. this.nOverlaps = 0;
  10726. this.prepareEvents();
  10727. for (let i = 0; i < this.events.size(); i++) {
  10728. const ev = this.events.get(i);
  10729. if (ev.isInsert()) this.processOverlaps(i, ev.getDeleteEventIndex(), ev, si);
  10730. if (si.isDone()) break;
  10731. }
  10732. } else if (arguments.length === 3) {
  10733. if (arguments[2] instanceof SegmentIntersector$1 && hasInterface(arguments[0], List) && hasInterface(arguments[1], List)) {
  10734. const edges0 = arguments[0],
  10735. edges1 = arguments[1],
  10736. si = arguments[2];
  10737. this.addEdges(edges0, edges0);
  10738. this.addEdges(edges1, edges1);
  10739. this.computeIntersections(si);
  10740. } else if (typeof arguments[2] === 'boolean' && hasInterface(arguments[0], List) && arguments[1] instanceof SegmentIntersector$1) {
  10741. const edges = arguments[0],
  10742. si = arguments[1],
  10743. testAllSegments = arguments[2];
  10744. if (testAllSegments) this.addEdges(edges, null);else this.addEdges(edges);
  10745. this.computeIntersections(si);
  10746. }
  10747. }
  10748. }
  10749. addEdge(edge, edgeSet) {
  10750. const mce = edge.getMonotoneChainEdge();
  10751. const startIndex = mce.getStartIndexes();
  10752. for (let i = 0; i < startIndex.length - 1; i++) {
  10753. const mc = new MonotoneChain$1(mce, i);
  10754. const insertEvent = new SweepLineEvent(edgeSet, mce.getMinX(i), mc);
  10755. this.events.add(insertEvent);
  10756. this.events.add(new SweepLineEvent(mce.getMaxX(i), insertEvent));
  10757. }
  10758. }
  10759. processOverlaps(start, end, ev0, si) {
  10760. const mc0 = ev0.getObject();
  10761. for (let i = start; i < end; i++) {
  10762. const ev1 = this.events.get(i);
  10763. if (ev1.isInsert()) {
  10764. const mc1 = ev1.getObject();
  10765. if (!ev0.isSameLabel(ev1)) {
  10766. mc0.computeIntersections(mc1, si);
  10767. this.nOverlaps++;
  10768. }
  10769. }
  10770. }
  10771. }
  10772. addEdges() {
  10773. if (arguments.length === 1) {
  10774. const edges = arguments[0];
  10775. for (let i = edges.iterator(); i.hasNext();) {
  10776. const edge = i.next();
  10777. this.addEdge(edge, edge);
  10778. }
  10779. } else if (arguments.length === 2) {
  10780. const edges = arguments[0],
  10781. edgeSet = arguments[1];
  10782. for (let i = edges.iterator(); i.hasNext();) {
  10783. const edge = i.next();
  10784. this.addEdge(edge, edgeSet);
  10785. }
  10786. }
  10787. }
  10788. }
  10789. class TopologyLocation {
  10790. constructor() {
  10791. TopologyLocation.constructor_.apply(this, arguments);
  10792. }
  10793. static constructor_() {
  10794. this.location = null;
  10795. if (arguments.length === 1) {
  10796. if (arguments[0] instanceof Array) {
  10797. const location = arguments[0];
  10798. this.init(location.length);
  10799. } else if (Number.isInteger(arguments[0])) {
  10800. const on = arguments[0];
  10801. this.init(1);
  10802. this.location[Position.ON] = on;
  10803. } else if (arguments[0] instanceof TopologyLocation) {
  10804. const gl = arguments[0];
  10805. this.init(gl.location.length);
  10806. if (gl !== null) for (let i = 0; i < this.location.length; i++) this.location[i] = gl.location[i];
  10807. }
  10808. } else if (arguments.length === 3) {
  10809. const on = arguments[0],
  10810. left = arguments[1],
  10811. right = arguments[2];
  10812. this.init(3);
  10813. this.location[Position.ON] = on;
  10814. this.location[Position.LEFT] = left;
  10815. this.location[Position.RIGHT] = right;
  10816. }
  10817. }
  10818. setAllLocations(locValue) {
  10819. for (let i = 0; i < this.location.length; i++) this.location[i] = locValue;
  10820. }
  10821. isNull() {
  10822. for (let i = 0; i < this.location.length; i++) if (this.location[i] !== Location.NONE) return false;
  10823. return true;
  10824. }
  10825. setAllLocationsIfNull(locValue) {
  10826. for (let i = 0; i < this.location.length; i++) if (this.location[i] === Location.NONE) this.location[i] = locValue;
  10827. }
  10828. isLine() {
  10829. return this.location.length === 1;
  10830. }
  10831. merge(gl) {
  10832. if (gl.location.length > this.location.length) {
  10833. const newLoc = new Array(3).fill(null);
  10834. newLoc[Position.ON] = this.location[Position.ON];
  10835. newLoc[Position.LEFT] = Location.NONE;
  10836. newLoc[Position.RIGHT] = Location.NONE;
  10837. this.location = newLoc;
  10838. }
  10839. for (let i = 0; i < this.location.length; i++) if (this.location[i] === Location.NONE && i < gl.location.length) this.location[i] = gl.location[i];
  10840. }
  10841. getLocations() {
  10842. return this.location;
  10843. }
  10844. flip() {
  10845. if (this.location.length <= 1) return null;
  10846. const temp = this.location[Position.LEFT];
  10847. this.location[Position.LEFT] = this.location[Position.RIGHT];
  10848. this.location[Position.RIGHT] = temp;
  10849. }
  10850. toString() {
  10851. const buf = new StringBuffer();
  10852. if (this.location.length > 1) buf.append(Location.toLocationSymbol(this.location[Position.LEFT]));
  10853. buf.append(Location.toLocationSymbol(this.location[Position.ON]));
  10854. if (this.location.length > 1) buf.append(Location.toLocationSymbol(this.location[Position.RIGHT]));
  10855. return buf.toString();
  10856. }
  10857. setLocations(on, left, right) {
  10858. this.location[Position.ON] = on;
  10859. this.location[Position.LEFT] = left;
  10860. this.location[Position.RIGHT] = right;
  10861. }
  10862. get(posIndex) {
  10863. if (posIndex < this.location.length) return this.location[posIndex];
  10864. return Location.NONE;
  10865. }
  10866. isArea() {
  10867. return this.location.length > 1;
  10868. }
  10869. isAnyNull() {
  10870. for (let i = 0; i < this.location.length; i++) if (this.location[i] === Location.NONE) return true;
  10871. return false;
  10872. }
  10873. setLocation() {
  10874. if (arguments.length === 1) {
  10875. const locValue = arguments[0];
  10876. this.setLocation(Position.ON, locValue);
  10877. } else if (arguments.length === 2) {
  10878. const locIndex = arguments[0],
  10879. locValue = arguments[1];
  10880. this.location[locIndex] = locValue;
  10881. }
  10882. }
  10883. init(size) {
  10884. this.location = new Array(size).fill(null);
  10885. this.setAllLocations(Location.NONE);
  10886. }
  10887. isEqualOnSide(le, locIndex) {
  10888. return this.location[locIndex] === le.location[locIndex];
  10889. }
  10890. allPositionsEqual(loc) {
  10891. for (let i = 0; i < this.location.length; i++) if (this.location[i] !== loc) return false;
  10892. return true;
  10893. }
  10894. }
  10895. class Label {
  10896. constructor() {
  10897. Label.constructor_.apply(this, arguments);
  10898. }
  10899. static constructor_() {
  10900. this.elt = new Array(2).fill(null);
  10901. if (arguments.length === 1) {
  10902. if (Number.isInteger(arguments[0])) {
  10903. const onLoc = arguments[0];
  10904. this.elt[0] = new TopologyLocation(onLoc);
  10905. this.elt[1] = new TopologyLocation(onLoc);
  10906. } else if (arguments[0] instanceof Label) {
  10907. const lbl = arguments[0];
  10908. this.elt[0] = new TopologyLocation(lbl.elt[0]);
  10909. this.elt[1] = new TopologyLocation(lbl.elt[1]);
  10910. }
  10911. } else if (arguments.length === 2) {
  10912. const geomIndex = arguments[0],
  10913. onLoc = arguments[1];
  10914. this.elt[0] = new TopologyLocation(Location.NONE);
  10915. this.elt[1] = new TopologyLocation(Location.NONE);
  10916. this.elt[geomIndex].setLocation(onLoc);
  10917. } else if (arguments.length === 3) {
  10918. const onLoc = arguments[0],
  10919. leftLoc = arguments[1],
  10920. rightLoc = arguments[2];
  10921. this.elt[0] = new TopologyLocation(onLoc, leftLoc, rightLoc);
  10922. this.elt[1] = new TopologyLocation(onLoc, leftLoc, rightLoc);
  10923. } else if (arguments.length === 4) {
  10924. const geomIndex = arguments[0],
  10925. onLoc = arguments[1],
  10926. leftLoc = arguments[2],
  10927. rightLoc = arguments[3];
  10928. this.elt[0] = new TopologyLocation(Location.NONE, Location.NONE, Location.NONE);
  10929. this.elt[1] = new TopologyLocation(Location.NONE, Location.NONE, Location.NONE);
  10930. this.elt[geomIndex].setLocations(onLoc, leftLoc, rightLoc);
  10931. }
  10932. }
  10933. static toLineLabel(label) {
  10934. const lineLabel = new Label(Location.NONE);
  10935. for (let i = 0; i < 2; i++) lineLabel.setLocation(i, label.getLocation(i));
  10936. return lineLabel;
  10937. }
  10938. getGeometryCount() {
  10939. let count = 0;
  10940. if (!this.elt[0].isNull()) count++;
  10941. if (!this.elt[1].isNull()) count++;
  10942. return count;
  10943. }
  10944. setAllLocations(geomIndex, location) {
  10945. this.elt[geomIndex].setAllLocations(location);
  10946. }
  10947. isNull(geomIndex) {
  10948. return this.elt[geomIndex].isNull();
  10949. }
  10950. setAllLocationsIfNull() {
  10951. if (arguments.length === 1) {
  10952. const location = arguments[0];
  10953. this.setAllLocationsIfNull(0, location);
  10954. this.setAllLocationsIfNull(1, location);
  10955. } else if (arguments.length === 2) {
  10956. const geomIndex = arguments[0],
  10957. location = arguments[1];
  10958. this.elt[geomIndex].setAllLocationsIfNull(location);
  10959. }
  10960. }
  10961. isLine(geomIndex) {
  10962. return this.elt[geomIndex].isLine();
  10963. }
  10964. merge(lbl) {
  10965. for (let i = 0; i < 2; i++) if (this.elt[i] === null && lbl.elt[i] !== null) this.elt[i] = new TopologyLocation(lbl.elt[i]);else this.elt[i].merge(lbl.elt[i]);
  10966. }
  10967. flip() {
  10968. this.elt[0].flip();
  10969. this.elt[1].flip();
  10970. }
  10971. getLocation() {
  10972. if (arguments.length === 1) {
  10973. const geomIndex = arguments[0];
  10974. return this.elt[geomIndex].get(Position.ON);
  10975. } else if (arguments.length === 2) {
  10976. const geomIndex = arguments[0],
  10977. posIndex = arguments[1];
  10978. return this.elt[geomIndex].get(posIndex);
  10979. }
  10980. }
  10981. toString() {
  10982. const buf = new StringBuffer();
  10983. if (this.elt[0] !== null) {
  10984. buf.append('A:');
  10985. buf.append(this.elt[0].toString());
  10986. }
  10987. if (this.elt[1] !== null) {
  10988. buf.append(' B:');
  10989. buf.append(this.elt[1].toString());
  10990. }
  10991. return buf.toString();
  10992. }
  10993. isArea() {
  10994. if (arguments.length === 0) {
  10995. return this.elt[0].isArea() || this.elt[1].isArea();
  10996. } else if (arguments.length === 1) {
  10997. const geomIndex = arguments[0];
  10998. return this.elt[geomIndex].isArea();
  10999. }
  11000. }
  11001. isAnyNull(geomIndex) {
  11002. return this.elt[geomIndex].isAnyNull();
  11003. }
  11004. setLocation() {
  11005. if (arguments.length === 2) {
  11006. const geomIndex = arguments[0],
  11007. location = arguments[1];
  11008. this.elt[geomIndex].setLocation(Position.ON, location);
  11009. } else if (arguments.length === 3) {
  11010. const geomIndex = arguments[0],
  11011. posIndex = arguments[1],
  11012. location = arguments[2];
  11013. this.elt[geomIndex].setLocation(posIndex, location);
  11014. }
  11015. }
  11016. isEqualOnSide(lbl, side) {
  11017. return this.elt[0].isEqualOnSide(lbl.elt[0], side) && this.elt[1].isEqualOnSide(lbl.elt[1], side);
  11018. }
  11019. allPositionsEqual(geomIndex, loc) {
  11020. return this.elt[geomIndex].allPositionsEqual(loc);
  11021. }
  11022. toLine(geomIndex) {
  11023. if (this.elt[geomIndex].isArea()) this.elt[geomIndex] = new TopologyLocation(this.elt[geomIndex].location[0]);
  11024. }
  11025. }
  11026. class EdgeIntersection {
  11027. constructor() {
  11028. EdgeIntersection.constructor_.apply(this, arguments);
  11029. }
  11030. static constructor_() {
  11031. this.coord = null;
  11032. this.segmentIndex = null;
  11033. this.dist = null;
  11034. const coord = arguments[0],
  11035. segmentIndex = arguments[1],
  11036. dist = arguments[2];
  11037. this.coord = new Coordinate(coord);
  11038. this.segmentIndex = segmentIndex;
  11039. this.dist = dist;
  11040. }
  11041. getSegmentIndex() {
  11042. return this.segmentIndex;
  11043. }
  11044. getCoordinate() {
  11045. return this.coord;
  11046. }
  11047. print(out) {
  11048. out.print(this.coord);
  11049. out.print(' seg # = ' + this.segmentIndex);
  11050. out.println(' dist = ' + this.dist);
  11051. }
  11052. compareTo(obj) {
  11053. const other = obj;
  11054. return this.compare(other.segmentIndex, other.dist);
  11055. }
  11056. isEndPoint(maxSegmentIndex) {
  11057. if (this.segmentIndex === 0 && this.dist === 0.0) return true;
  11058. if (this.segmentIndex === maxSegmentIndex) return true;
  11059. return false;
  11060. }
  11061. toString() {
  11062. return this.coord + ' seg # = ' + this.segmentIndex + ' dist = ' + this.dist;
  11063. }
  11064. getDistance() {
  11065. return this.dist;
  11066. }
  11067. compare(segmentIndex, dist) {
  11068. if (this.segmentIndex < segmentIndex) return -1;
  11069. if (this.segmentIndex > segmentIndex) return 1;
  11070. if (this.dist < dist) return -1;
  11071. if (this.dist > dist) return 1;
  11072. return 0;
  11073. }
  11074. get interfaces_() {
  11075. return [Comparable];
  11076. }
  11077. }
  11078. /**
  11079. * @see http://download.oracle.com/javase/6/docs/api/java/util/SortedMap.html
  11080. */
  11081. class SortedMap extends Map$1 {}
  11082. const BLACK = 0;
  11083. const RED = 1;
  11084. function colorOf(p) {
  11085. return p == null ? BLACK : p.color;
  11086. }
  11087. function parentOf(p) {
  11088. return p == null ? null : p.parent;
  11089. }
  11090. function setColor(p, c) {
  11091. if (p !== null) p.color = c;
  11092. }
  11093. function leftOf(p) {
  11094. return p == null ? null : p.left;
  11095. }
  11096. function rightOf(p) {
  11097. return p == null ? null : p.right;
  11098. }
  11099. /**
  11100. * @see http://download.oracle.com/javase/6/docs/api/java/util/TreeMap.html
  11101. */
  11102. class TreeMap extends SortedMap {
  11103. constructor() {
  11104. super();
  11105. this.root_ = null;
  11106. this.size_ = 0;
  11107. }
  11108. get(key) {
  11109. let p = this.root_;
  11110. while (p !== null) {
  11111. const cmp = key.compareTo(p.key);
  11112. if (cmp < 0) p = p.left;else if (cmp > 0) p = p.right;else return p.value;
  11113. }
  11114. return null;
  11115. }
  11116. put(key, value) {
  11117. if (this.root_ === null) {
  11118. this.root_ = {
  11119. key: key,
  11120. value: value,
  11121. left: null,
  11122. right: null,
  11123. parent: null,
  11124. color: BLACK,
  11125. getValue() {
  11126. return this.value;
  11127. },
  11128. getKey() {
  11129. return this.key;
  11130. }
  11131. };
  11132. this.size_ = 1;
  11133. return null;
  11134. }
  11135. let t = this.root_;
  11136. let parent;
  11137. let cmp;
  11138. do {
  11139. parent = t;
  11140. cmp = key.compareTo(t.key);
  11141. if (cmp < 0) {
  11142. t = t.left;
  11143. } else if (cmp > 0) {
  11144. t = t.right;
  11145. } else {
  11146. const oldValue = t.value;
  11147. t.value = value;
  11148. return oldValue;
  11149. }
  11150. } while (t !== null);
  11151. const e = {
  11152. key: key,
  11153. left: null,
  11154. right: null,
  11155. value: value,
  11156. parent: parent,
  11157. color: BLACK,
  11158. getValue() {
  11159. return this.value;
  11160. },
  11161. getKey() {
  11162. return this.key;
  11163. }
  11164. };
  11165. if (cmp < 0) parent.left = e;else parent.right = e;
  11166. this.fixAfterInsertion(e);
  11167. this.size_++;
  11168. return null;
  11169. }
  11170. /**
  11171. * @param {Object} x
  11172. */
  11173. fixAfterInsertion(x) {
  11174. let y;
  11175. x.color = RED;
  11176. while (x != null && x !== this.root_ && x.parent.color === RED) if (parentOf(x) === leftOf(parentOf(parentOf(x)))) {
  11177. y = rightOf(parentOf(parentOf(x)));
  11178. if (colorOf(y) === RED) {
  11179. setColor(parentOf(x), BLACK);
  11180. setColor(y, BLACK);
  11181. setColor(parentOf(parentOf(x)), RED);
  11182. x = parentOf(parentOf(x));
  11183. } else {
  11184. if (x === rightOf(parentOf(x))) {
  11185. x = parentOf(x);
  11186. this.rotateLeft(x);
  11187. }
  11188. setColor(parentOf(x), BLACK);
  11189. setColor(parentOf(parentOf(x)), RED);
  11190. this.rotateRight(parentOf(parentOf(x)));
  11191. }
  11192. } else {
  11193. y = leftOf(parentOf(parentOf(x)));
  11194. if (colorOf(y) === RED) {
  11195. setColor(parentOf(x), BLACK);
  11196. setColor(y, BLACK);
  11197. setColor(parentOf(parentOf(x)), RED);
  11198. x = parentOf(parentOf(x));
  11199. } else {
  11200. if (x === leftOf(parentOf(x))) {
  11201. x = parentOf(x);
  11202. this.rotateRight(x);
  11203. }
  11204. setColor(parentOf(x), BLACK);
  11205. setColor(parentOf(parentOf(x)), RED);
  11206. this.rotateLeft(parentOf(parentOf(x)));
  11207. }
  11208. }
  11209. this.root_.color = BLACK;
  11210. }
  11211. values() {
  11212. const arrayList = new ArrayList();
  11213. let p = this.getFirstEntry();
  11214. if (p !== null) {
  11215. arrayList.add(p.value);
  11216. while ((p = TreeMap.successor(p)) !== null) arrayList.add(p.value);
  11217. }
  11218. return arrayList;
  11219. }
  11220. entrySet() {
  11221. const hashSet = new HashSet();
  11222. let p = this.getFirstEntry();
  11223. if (p !== null) {
  11224. hashSet.add(p);
  11225. while ((p = TreeMap.successor(p)) !== null) hashSet.add(p);
  11226. }
  11227. return hashSet;
  11228. }
  11229. /**
  11230. * @param {Object} p
  11231. */
  11232. rotateLeft(p) {
  11233. if (p != null) {
  11234. const r = p.right;
  11235. p.right = r.left;
  11236. if (r.left != null) r.left.parent = p;
  11237. r.parent = p.parent;
  11238. if (p.parent == null) this.root_ = r;else if (p.parent.left === p) p.parent.left = r;else p.parent.right = r;
  11239. r.left = p;
  11240. p.parent = r;
  11241. }
  11242. }
  11243. /**
  11244. * @param {Object} p
  11245. */
  11246. rotateRight(p) {
  11247. if (p != null) {
  11248. const l = p.left;
  11249. p.left = l.right;
  11250. if (l.right != null) l.right.parent = p;
  11251. l.parent = p.parent;
  11252. if (p.parent == null) this.root_ = l;else if (p.parent.right === p) p.parent.right = l;else p.parent.left = l;
  11253. l.right = p;
  11254. p.parent = l;
  11255. }
  11256. }
  11257. /**
  11258. * @return {Object}
  11259. */
  11260. getFirstEntry() {
  11261. let p = this.root_;
  11262. if (p != null) while (p.left != null) p = p.left;
  11263. return p;
  11264. }
  11265. /**
  11266. * @param {Object} t
  11267. * @return {Object}
  11268. * @private
  11269. */
  11270. static successor(t) {
  11271. let p;
  11272. if (t === null) {
  11273. return null;
  11274. } else if (t.right !== null) {
  11275. p = t.right;
  11276. while (p.left !== null) p = p.left;
  11277. return p;
  11278. } else {
  11279. p = t.parent;
  11280. let ch = t;
  11281. while (p !== null && ch === p.right) {
  11282. ch = p;
  11283. p = p.parent;
  11284. }
  11285. return p;
  11286. }
  11287. }
  11288. size() {
  11289. return this.size_;
  11290. }
  11291. containsKey(key) {
  11292. let p = this.root_;
  11293. while (p !== null) {
  11294. const cmp = key.compareTo(p.key);
  11295. if (cmp < 0) p = p.left;else if (cmp > 0) p = p.right;else return true;
  11296. }
  11297. return false;
  11298. }
  11299. }
  11300. class EdgeIntersectionList {
  11301. constructor() {
  11302. EdgeIntersectionList.constructor_.apply(this, arguments);
  11303. }
  11304. static constructor_() {
  11305. this._nodeMap = new TreeMap();
  11306. this.edge = null;
  11307. const edge = arguments[0];
  11308. this.edge = edge;
  11309. }
  11310. print(out) {
  11311. out.println('Intersections:');
  11312. for (let it = this.iterator(); it.hasNext();) {
  11313. const ei = it.next();
  11314. ei.print(out);
  11315. }
  11316. }
  11317. iterator() {
  11318. return this._nodeMap.values().iterator();
  11319. }
  11320. addSplitEdges(edgeList) {
  11321. this.addEndpoints();
  11322. const it = this.iterator();
  11323. let eiPrev = it.next();
  11324. while (it.hasNext()) {
  11325. const ei = it.next();
  11326. const newEdge = this.createSplitEdge(eiPrev, ei);
  11327. edgeList.add(newEdge);
  11328. eiPrev = ei;
  11329. }
  11330. }
  11331. addEndpoints() {
  11332. const maxSegIndex = this.edge.pts.length - 1;
  11333. this.add(this.edge.pts[0], 0, 0.0);
  11334. this.add(this.edge.pts[maxSegIndex], maxSegIndex, 0.0);
  11335. }
  11336. createSplitEdge(ei0, ei1) {
  11337. let npts = ei1.segmentIndex - ei0.segmentIndex + 2;
  11338. const lastSegStartPt = this.edge.pts[ei1.segmentIndex];
  11339. const useIntPt1 = ei1.dist > 0.0 || !ei1.coord.equals2D(lastSegStartPt);
  11340. if (!useIntPt1) npts--;
  11341. const pts = new Array(npts).fill(null);
  11342. let ipt = 0;
  11343. pts[ipt++] = new Coordinate(ei0.coord);
  11344. for (let i = ei0.segmentIndex + 1; i <= ei1.segmentIndex; i++) pts[ipt++] = this.edge.pts[i];
  11345. if (useIntPt1) pts[ipt] = ei1.coord;
  11346. return new Edge$1(pts, new Label(this.edge._label));
  11347. }
  11348. add(intPt, segmentIndex, dist) {
  11349. const eiNew = new EdgeIntersection(intPt, segmentIndex, dist);
  11350. const ei = this._nodeMap.get(eiNew);
  11351. if (ei !== null) return ei;
  11352. this._nodeMap.put(eiNew, eiNew);
  11353. return eiNew;
  11354. }
  11355. isIntersection(pt) {
  11356. for (let it = this.iterator(); it.hasNext();) {
  11357. const ei = it.next();
  11358. if (ei.coord.equals(pt)) return true;
  11359. }
  11360. return false;
  11361. }
  11362. }
  11363. class IntArrayList {
  11364. constructor() {
  11365. IntArrayList.constructor_.apply(this, arguments);
  11366. }
  11367. static constructor_() {
  11368. this._data = null;
  11369. this._size = 0;
  11370. if (arguments.length === 0) {
  11371. IntArrayList.constructor_.call(this, 10);
  11372. } else if (arguments.length === 1) {
  11373. const initialCapacity = arguments[0];
  11374. this._data = new Array(initialCapacity).fill(null);
  11375. }
  11376. }
  11377. size() {
  11378. return this._size;
  11379. }
  11380. addAll(values) {
  11381. if (values === null) return null;
  11382. if (values.length === 0) return null;
  11383. this.ensureCapacity(this._size + values.length);
  11384. System.arraycopy(values, 0, this._data, this._size, values.length);
  11385. this._size += values.length;
  11386. }
  11387. ensureCapacity(capacity) {
  11388. if (capacity <= this._data.length) return null;
  11389. const newLength = Math.max(capacity, this._data.length * 2);
  11390. this._data = Arrays.copyOf(this._data, newLength);
  11391. }
  11392. toArray() {
  11393. const array = new Array(this._size).fill(null);
  11394. System.arraycopy(this._data, 0, array, 0, this._size);
  11395. return array;
  11396. }
  11397. add(value) {
  11398. this.ensureCapacity(this._size + 1);
  11399. this._data[this._size] = value;
  11400. ++this._size;
  11401. }
  11402. }
  11403. class MonotoneChainIndexer {
  11404. static toIntArray(list) {
  11405. const array = new Array(list.size()).fill(null);
  11406. for (let i = 0; i < array.length; i++) array[i] = list.get(i).intValue();
  11407. return array;
  11408. }
  11409. getChainStartIndices(pts) {
  11410. let start = 0;
  11411. const startIndexList = new IntArrayList(Math.trunc(pts.length / 2));
  11412. startIndexList.add(start);
  11413. do {
  11414. const last = this.findChainEnd(pts, start);
  11415. startIndexList.add(last);
  11416. start = last;
  11417. } while (start < pts.length - 1);
  11418. return startIndexList.toArray();
  11419. }
  11420. findChainEnd(pts, start) {
  11421. const chainQuad = Quadrant.quadrant(pts[start], pts[start + 1]);
  11422. let last = start + 1;
  11423. while (last < pts.length) {
  11424. const quad = Quadrant.quadrant(pts[last - 1], pts[last]);
  11425. if (quad !== chainQuad) break;
  11426. last++;
  11427. }
  11428. return last - 1;
  11429. }
  11430. OLDgetChainStartIndices(pts) {
  11431. let start = 0;
  11432. const startIndexList = new ArrayList();
  11433. startIndexList.add(start);
  11434. do {
  11435. const last = this.findChainEnd(pts, start);
  11436. startIndexList.add(last);
  11437. start = last;
  11438. } while (start < pts.length - 1);
  11439. const startIndex = MonotoneChainIndexer.toIntArray(startIndexList);
  11440. return startIndex;
  11441. }
  11442. }
  11443. class MonotoneChainEdge {
  11444. constructor() {
  11445. MonotoneChainEdge.constructor_.apply(this, arguments);
  11446. }
  11447. static constructor_() {
  11448. this.e = null;
  11449. this.pts = null;
  11450. this.startIndex = null;
  11451. const e = arguments[0];
  11452. this.e = e;
  11453. this.pts = e.getCoordinates();
  11454. const mcb = new MonotoneChainIndexer();
  11455. this.startIndex = mcb.getChainStartIndices(this.pts);
  11456. }
  11457. getCoordinates() {
  11458. return this.pts;
  11459. }
  11460. getMaxX(chainIndex) {
  11461. const x1 = this.pts[this.startIndex[chainIndex]].x;
  11462. const x2 = this.pts[this.startIndex[chainIndex + 1]].x;
  11463. return x1 > x2 ? x1 : x2;
  11464. }
  11465. getMinX(chainIndex) {
  11466. const x1 = this.pts[this.startIndex[chainIndex]].x;
  11467. const x2 = this.pts[this.startIndex[chainIndex + 1]].x;
  11468. return x1 < x2 ? x1 : x2;
  11469. }
  11470. computeIntersectsForChain() {
  11471. if (arguments.length === 4) {
  11472. const chainIndex0 = arguments[0],
  11473. mce = arguments[1],
  11474. chainIndex1 = arguments[2],
  11475. si = arguments[3];
  11476. this.computeIntersectsForChain(this.startIndex[chainIndex0], this.startIndex[chainIndex0 + 1], mce, mce.startIndex[chainIndex1], mce.startIndex[chainIndex1 + 1], si);
  11477. } else if (arguments.length === 6) {
  11478. const start0 = arguments[0],
  11479. end0 = arguments[1],
  11480. mce = arguments[2],
  11481. start1 = arguments[3],
  11482. end1 = arguments[4],
  11483. ei = arguments[5];
  11484. if (end0 - start0 === 1 && end1 - start1 === 1) {
  11485. ei.addIntersections(this.e, start0, mce.e, start1);
  11486. return null;
  11487. }
  11488. if (!this.overlaps(start0, end0, mce, start1, end1)) return null;
  11489. const mid0 = Math.trunc((start0 + end0) / 2);
  11490. const mid1 = Math.trunc((start1 + end1) / 2);
  11491. if (start0 < mid0) {
  11492. if (start1 < mid1) this.computeIntersectsForChain(start0, mid0, mce, start1, mid1, ei);
  11493. if (mid1 < end1) this.computeIntersectsForChain(start0, mid0, mce, mid1, end1, ei);
  11494. }
  11495. if (mid0 < end0) {
  11496. if (start1 < mid1) this.computeIntersectsForChain(mid0, end0, mce, start1, mid1, ei);
  11497. if (mid1 < end1) this.computeIntersectsForChain(mid0, end0, mce, mid1, end1, ei);
  11498. }
  11499. }
  11500. }
  11501. overlaps(start0, end0, mce, start1, end1) {
  11502. return Envelope.intersects(this.pts[start0], this.pts[end0], mce.pts[start1], mce.pts[end1]);
  11503. }
  11504. getStartIndexes() {
  11505. return this.startIndex;
  11506. }
  11507. computeIntersects(mce, si) {
  11508. for (let i = 0; i < this.startIndex.length - 1; i++) for (let j = 0; j < mce.startIndex.length - 1; j++) this.computeIntersectsForChain(i, mce, j, si);
  11509. }
  11510. }
  11511. class Depth {
  11512. constructor() {
  11513. Depth.constructor_.apply(this, arguments);
  11514. }
  11515. static constructor_() {
  11516. this._depth = Array(2).fill().map(() => Array(3));
  11517. for (let i = 0; i < 2; i++) for (let j = 0; j < 3; j++) this._depth[i][j] = Depth.NULL_VALUE;
  11518. }
  11519. static depthAtLocation(location) {
  11520. if (location === Location.EXTERIOR) return 0;
  11521. if (location === Location.INTERIOR) return 1;
  11522. return Depth.NULL_VALUE;
  11523. }
  11524. getDepth(geomIndex, posIndex) {
  11525. return this._depth[geomIndex][posIndex];
  11526. }
  11527. setDepth(geomIndex, posIndex, depthValue) {
  11528. this._depth[geomIndex][posIndex] = depthValue;
  11529. }
  11530. isNull() {
  11531. if (arguments.length === 0) {
  11532. for (let i = 0; i < 2; i++) for (let j = 0; j < 3; j++) if (this._depth[i][j] !== Depth.NULL_VALUE) return false;
  11533. return true;
  11534. } else if (arguments.length === 1) {
  11535. const geomIndex = arguments[0];
  11536. return this._depth[geomIndex][1] === Depth.NULL_VALUE;
  11537. } else if (arguments.length === 2) {
  11538. const geomIndex = arguments[0],
  11539. posIndex = arguments[1];
  11540. return this._depth[geomIndex][posIndex] === Depth.NULL_VALUE;
  11541. }
  11542. }
  11543. normalize() {
  11544. for (let i = 0; i < 2; i++) if (!this.isNull(i)) {
  11545. let minDepth = this._depth[i][1];
  11546. if (this._depth[i][2] < minDepth) minDepth = this._depth[i][2];
  11547. if (minDepth < 0) minDepth = 0;
  11548. for (let j = 1; j < 3; j++) {
  11549. let newValue = 0;
  11550. if (this._depth[i][j] > minDepth) newValue = 1;
  11551. this._depth[i][j] = newValue;
  11552. }
  11553. }
  11554. }
  11555. getDelta(geomIndex) {
  11556. return this._depth[geomIndex][Position.RIGHT] - this._depth[geomIndex][Position.LEFT];
  11557. }
  11558. getLocation(geomIndex, posIndex) {
  11559. if (this._depth[geomIndex][posIndex] <= 0) return Location.EXTERIOR;
  11560. return Location.INTERIOR;
  11561. }
  11562. toString() {
  11563. return 'A: ' + this._depth[0][1] + ',' + this._depth[0][2] + ' B: ' + this._depth[1][1] + ',' + this._depth[1][2];
  11564. }
  11565. add() {
  11566. if (arguments.length === 1) {
  11567. const lbl = arguments[0];
  11568. for (let i = 0; i < 2; i++) for (let j = 1; j < 3; j++) {
  11569. const loc = lbl.getLocation(i, j);
  11570. if (loc === Location.EXTERIOR || loc === Location.INTERIOR) if (this.isNull(i, j)) this._depth[i][j] = Depth.depthAtLocation(loc);else this._depth[i][j] += Depth.depthAtLocation(loc);
  11571. }
  11572. } else if (arguments.length === 3) {
  11573. const geomIndex = arguments[0],
  11574. posIndex = arguments[1],
  11575. location = arguments[2];
  11576. if (location === Location.INTERIOR) this._depth[geomIndex][posIndex]++;
  11577. }
  11578. }
  11579. }
  11580. Depth.NULL_VALUE = -1;
  11581. class GraphComponent$1 {
  11582. constructor() {
  11583. GraphComponent$1.constructor_.apply(this, arguments);
  11584. }
  11585. static constructor_() {
  11586. this._label = null;
  11587. this._isInResult = false;
  11588. this._isCovered = false;
  11589. this._isCoveredSet = false;
  11590. this._isVisited = false;
  11591. if (arguments.length === 0) ; else if (arguments.length === 1) {
  11592. const label = arguments[0];
  11593. this._label = label;
  11594. }
  11595. }
  11596. setVisited(isVisited) {
  11597. this._isVisited = isVisited;
  11598. }
  11599. setInResult(isInResult) {
  11600. this._isInResult = isInResult;
  11601. }
  11602. isCovered() {
  11603. return this._isCovered;
  11604. }
  11605. isCoveredSet() {
  11606. return this._isCoveredSet;
  11607. }
  11608. setLabel(label) {
  11609. this._label = label;
  11610. }
  11611. getLabel() {
  11612. return this._label;
  11613. }
  11614. setCovered(isCovered) {
  11615. this._isCovered = isCovered;
  11616. this._isCoveredSet = true;
  11617. }
  11618. updateIM(im) {
  11619. Assert.isTrue(this._label.getGeometryCount() >= 2, 'found partial label');
  11620. this.computeIM(im);
  11621. }
  11622. isInResult() {
  11623. return this._isInResult;
  11624. }
  11625. isVisited() {
  11626. return this._isVisited;
  11627. }
  11628. }
  11629. class Edge$1 extends GraphComponent$1 {
  11630. constructor() {
  11631. super();
  11632. Edge$1.constructor_.apply(this, arguments);
  11633. }
  11634. static constructor_() {
  11635. this.pts = null;
  11636. this._env = null;
  11637. this.eiList = new EdgeIntersectionList(this);
  11638. this._name = null;
  11639. this._mce = null;
  11640. this._isIsolated = true;
  11641. this._depth = new Depth();
  11642. this._depthDelta = 0;
  11643. if (arguments.length === 1) {
  11644. const pts = arguments[0];
  11645. Edge$1.constructor_.call(this, pts, null);
  11646. } else if (arguments.length === 2) {
  11647. const pts = arguments[0],
  11648. label = arguments[1];
  11649. this.pts = pts;
  11650. this._label = label;
  11651. }
  11652. }
  11653. static updateIM() {
  11654. if (arguments.length === 2 && arguments[1] instanceof IntersectionMatrix && arguments[0] instanceof Label) {
  11655. const label = arguments[0],
  11656. im = arguments[1];
  11657. im.setAtLeastIfValid(label.getLocation(0, Position.ON), label.getLocation(1, Position.ON), 1);
  11658. if (label.isArea()) {
  11659. im.setAtLeastIfValid(label.getLocation(0, Position.LEFT), label.getLocation(1, Position.LEFT), 2);
  11660. im.setAtLeastIfValid(label.getLocation(0, Position.RIGHT), label.getLocation(1, Position.RIGHT), 2);
  11661. }
  11662. } else {
  11663. return super.updateIM.apply(this, arguments);
  11664. }
  11665. }
  11666. getDepth() {
  11667. return this._depth;
  11668. }
  11669. getCollapsedEdge() {
  11670. const newPts = new Array(2).fill(null);
  11671. newPts[0] = this.pts[0];
  11672. newPts[1] = this.pts[1];
  11673. const newe = new Edge$1(newPts, Label.toLineLabel(this._label));
  11674. return newe;
  11675. }
  11676. isIsolated() {
  11677. return this._isIsolated;
  11678. }
  11679. getCoordinates() {
  11680. return this.pts;
  11681. }
  11682. setIsolated(isIsolated) {
  11683. this._isIsolated = isIsolated;
  11684. }
  11685. setName(name) {
  11686. this._name = name;
  11687. }
  11688. equals(o) {
  11689. if (!(o instanceof Edge$1)) return false;
  11690. const e = o;
  11691. if (this.pts.length !== e.pts.length) return false;
  11692. let isEqualForward = true;
  11693. let isEqualReverse = true;
  11694. let iRev = this.pts.length;
  11695. for (let i = 0; i < this.pts.length; i++) {
  11696. if (!this.pts[i].equals2D(e.pts[i])) isEqualForward = false;
  11697. if (!this.pts[i].equals2D(e.pts[--iRev])) isEqualReverse = false;
  11698. if (!isEqualForward && !isEqualReverse) return false;
  11699. }
  11700. return true;
  11701. }
  11702. getCoordinate() {
  11703. if (arguments.length === 0) {
  11704. if (this.pts.length > 0) return this.pts[0];
  11705. return null;
  11706. } else if (arguments.length === 1) {
  11707. const i = arguments[0];
  11708. return this.pts[i];
  11709. }
  11710. }
  11711. print(out) {
  11712. out.print('edge ' + this._name + ': ');
  11713. out.print('LINESTRING (');
  11714. for (let i = 0; i < this.pts.length; i++) {
  11715. if (i > 0) out.print(',');
  11716. out.print(this.pts[i].x + ' ' + this.pts[i].y);
  11717. }
  11718. out.print(') ' + this._label + ' ' + this._depthDelta);
  11719. }
  11720. computeIM(im) {
  11721. Edge$1.updateIM(this._label, im);
  11722. }
  11723. isCollapsed() {
  11724. if (!this._label.isArea()) return false;
  11725. if (this.pts.length !== 3) return false;
  11726. if (this.pts[0].equals(this.pts[2])) return true;
  11727. return false;
  11728. }
  11729. isClosed() {
  11730. return this.pts[0].equals(this.pts[this.pts.length - 1]);
  11731. }
  11732. getMaximumSegmentIndex() {
  11733. return this.pts.length - 1;
  11734. }
  11735. getDepthDelta() {
  11736. return this._depthDelta;
  11737. }
  11738. getNumPoints() {
  11739. return this.pts.length;
  11740. }
  11741. printReverse(out) {
  11742. out.print('edge ' + this._name + ': ');
  11743. for (let i = this.pts.length - 1; i >= 0; i--) out.print(this.pts[i] + ' ');
  11744. out.println('');
  11745. }
  11746. getMonotoneChainEdge() {
  11747. if (this._mce === null) this._mce = new MonotoneChainEdge(this);
  11748. return this._mce;
  11749. }
  11750. getEnvelope() {
  11751. if (this._env === null) {
  11752. this._env = new Envelope();
  11753. for (let i = 0; i < this.pts.length; i++) this._env.expandToInclude(this.pts[i]);
  11754. }
  11755. return this._env;
  11756. }
  11757. addIntersection(li, segmentIndex, geomIndex, intIndex) {
  11758. const intPt = new Coordinate(li.getIntersection(intIndex));
  11759. let normalizedSegmentIndex = segmentIndex;
  11760. let dist = li.getEdgeDistance(geomIndex, intIndex);
  11761. const nextSegIndex = normalizedSegmentIndex + 1;
  11762. if (nextSegIndex < this.pts.length) {
  11763. const nextPt = this.pts[nextSegIndex];
  11764. if (intPt.equals2D(nextPt)) {
  11765. normalizedSegmentIndex = nextSegIndex;
  11766. dist = 0.0;
  11767. }
  11768. }
  11769. this.eiList.add(intPt, normalizedSegmentIndex, dist);
  11770. }
  11771. toString() {
  11772. const builder = new StringBuilder();
  11773. builder.append('edge ' + this._name + ': ');
  11774. builder.append('LINESTRING (');
  11775. for (let i = 0; i < this.pts.length; i++) {
  11776. if (i > 0) builder.append(',');
  11777. builder.append(this.pts[i].x + ' ' + this.pts[i].y);
  11778. }
  11779. builder.append(') ' + this._label + ' ' + this._depthDelta);
  11780. return builder.toString();
  11781. }
  11782. isPointwiseEqual(e) {
  11783. if (this.pts.length !== e.pts.length) return false;
  11784. for (let i = 0; i < this.pts.length; i++) if (!this.pts[i].equals2D(e.pts[i])) return false;
  11785. return true;
  11786. }
  11787. setDepthDelta(depthDelta) {
  11788. this._depthDelta = depthDelta;
  11789. }
  11790. getEdgeIntersectionList() {
  11791. return this.eiList;
  11792. }
  11793. addIntersections(li, segmentIndex, geomIndex) {
  11794. for (let i = 0; i < li.getIntersectionNum(); i++) this.addIntersection(li, segmentIndex, geomIndex, i);
  11795. }
  11796. }
  11797. class Node$2 extends GraphComponent$1 {
  11798. constructor() {
  11799. super();
  11800. Node$2.constructor_.apply(this, arguments);
  11801. }
  11802. static constructor_() {
  11803. this._coord = null;
  11804. this._edges = null;
  11805. const coord = arguments[0],
  11806. edges = arguments[1];
  11807. this._coord = coord;
  11808. this._edges = edges;
  11809. this._label = new Label(0, Location.NONE);
  11810. }
  11811. isIncidentEdgeInResult() {
  11812. for (let it = this.getEdges().getEdges().iterator(); it.hasNext();) {
  11813. const de = it.next();
  11814. if (de.getEdge().isInResult()) return true;
  11815. }
  11816. return false;
  11817. }
  11818. isIsolated() {
  11819. return this._label.getGeometryCount() === 1;
  11820. }
  11821. getCoordinate() {
  11822. return this._coord;
  11823. }
  11824. print(out) {
  11825. out.println('node ' + this._coord + ' lbl: ' + this._label);
  11826. }
  11827. computeIM(im) {}
  11828. computeMergedLocation(label2, eltIndex) {
  11829. let loc = Location.NONE;
  11830. loc = this._label.getLocation(eltIndex);
  11831. if (!label2.isNull(eltIndex)) {
  11832. const nLoc = label2.getLocation(eltIndex);
  11833. if (loc !== Location.BOUNDARY) loc = nLoc;
  11834. }
  11835. return loc;
  11836. }
  11837. setLabel() {
  11838. if (arguments.length === 2 && Number.isInteger(arguments[1]) && Number.isInteger(arguments[0])) {
  11839. const argIndex = arguments[0],
  11840. onLocation = arguments[1];
  11841. if (this._label === null) this._label = new Label(argIndex, onLocation);else this._label.setLocation(argIndex, onLocation);
  11842. } else {
  11843. return super.setLabel.apply(this, arguments);
  11844. }
  11845. }
  11846. getEdges() {
  11847. return this._edges;
  11848. }
  11849. mergeLabel() {
  11850. if (arguments[0] instanceof Node$2) {
  11851. const n = arguments[0];
  11852. this.mergeLabel(n._label);
  11853. } else if (arguments[0] instanceof Label) {
  11854. const label2 = arguments[0];
  11855. for (let i = 0; i < 2; i++) {
  11856. const loc = this.computeMergedLocation(label2, i);
  11857. const thisLoc = this._label.getLocation(i);
  11858. if (thisLoc === Location.NONE) this._label.setLocation(i, loc);
  11859. }
  11860. }
  11861. }
  11862. add(e) {
  11863. this._edges.insert(e);
  11864. e.setNode(this);
  11865. }
  11866. setLabelBoundary(argIndex) {
  11867. if (this._label === null) return null;
  11868. let loc = Location.NONE;
  11869. if (this._label !== null) loc = this._label.getLocation(argIndex);
  11870. let newLoc = null;
  11871. switch (loc) {
  11872. case Location.BOUNDARY:
  11873. newLoc = Location.INTERIOR;
  11874. break;
  11875. case Location.INTERIOR:
  11876. newLoc = Location.BOUNDARY;
  11877. break;
  11878. default:
  11879. newLoc = Location.BOUNDARY;
  11880. break;
  11881. }
  11882. this._label.setLocation(argIndex, newLoc);
  11883. }
  11884. }
  11885. class NodeMap$1 {
  11886. constructor() {
  11887. NodeMap$1.constructor_.apply(this, arguments);
  11888. }
  11889. static constructor_() {
  11890. this.nodeMap = new TreeMap();
  11891. this.nodeFact = null;
  11892. const nodeFact = arguments[0];
  11893. this.nodeFact = nodeFact;
  11894. }
  11895. find(coord) {
  11896. return this.nodeMap.get(coord);
  11897. }
  11898. addNode() {
  11899. if (arguments[0] instanceof Coordinate) {
  11900. const coord = arguments[0];
  11901. let node = this.nodeMap.get(coord);
  11902. if (node === null) {
  11903. node = this.nodeFact.createNode(coord);
  11904. this.nodeMap.put(coord, node);
  11905. }
  11906. return node;
  11907. } else if (arguments[0] instanceof Node$2) {
  11908. const n = arguments[0];
  11909. const node = this.nodeMap.get(n.getCoordinate());
  11910. if (node === null) {
  11911. this.nodeMap.put(n.getCoordinate(), n);
  11912. return n;
  11913. }
  11914. node.mergeLabel(n);
  11915. return node;
  11916. }
  11917. }
  11918. print(out) {
  11919. for (let it = this.iterator(); it.hasNext();) {
  11920. const n = it.next();
  11921. n.print(out);
  11922. }
  11923. }
  11924. iterator() {
  11925. return this.nodeMap.values().iterator();
  11926. }
  11927. values() {
  11928. return this.nodeMap.values();
  11929. }
  11930. getBoundaryNodes(geomIndex) {
  11931. const bdyNodes = new ArrayList();
  11932. for (let i = this.iterator(); i.hasNext();) {
  11933. const node = i.next();
  11934. if (node.getLabel().getLocation(geomIndex) === Location.BOUNDARY) bdyNodes.add(node);
  11935. }
  11936. return bdyNodes;
  11937. }
  11938. add(e) {
  11939. const p = e.getCoordinate();
  11940. const n = this.addNode(p);
  11941. n.add(e);
  11942. }
  11943. }
  11944. class EdgeEnd {
  11945. constructor() {
  11946. EdgeEnd.constructor_.apply(this, arguments);
  11947. }
  11948. static constructor_() {
  11949. this._edge = null;
  11950. this._label = null;
  11951. this._node = null;
  11952. this._p0 = null;
  11953. this._p1 = null;
  11954. this._dx = null;
  11955. this._dy = null;
  11956. this._quadrant = null;
  11957. if (arguments.length === 1) {
  11958. const edge = arguments[0];
  11959. this._edge = edge;
  11960. } else if (arguments.length === 3) {
  11961. const edge = arguments[0],
  11962. p0 = arguments[1],
  11963. p1 = arguments[2];
  11964. EdgeEnd.constructor_.call(this, edge, p0, p1, null);
  11965. } else if (arguments.length === 4) {
  11966. const edge = arguments[0],
  11967. p0 = arguments[1],
  11968. p1 = arguments[2],
  11969. label = arguments[3];
  11970. EdgeEnd.constructor_.call(this, edge);
  11971. this.init(p0, p1);
  11972. this._label = label;
  11973. }
  11974. }
  11975. compareDirection(e) {
  11976. if (this._dx === e._dx && this._dy === e._dy) return 0;
  11977. if (this._quadrant > e._quadrant) return 1;
  11978. if (this._quadrant < e._quadrant) return -1;
  11979. return Orientation.index(e._p0, e._p1, this._p1);
  11980. }
  11981. getDy() {
  11982. return this._dy;
  11983. }
  11984. getCoordinate() {
  11985. return this._p0;
  11986. }
  11987. setNode(node) {
  11988. this._node = node;
  11989. }
  11990. print(out) {
  11991. const angle = Math.atan2(this._dy, this._dx);
  11992. const className = this.getClass().getName();
  11993. const lastDotPos = className.lastIndexOf('.');
  11994. const name = className.substring(lastDotPos + 1);
  11995. out.print(' ' + name + ': ' + this._p0 + ' - ' + this._p1 + ' ' + this._quadrant + ':' + angle + ' ' + this._label);
  11996. }
  11997. compareTo(obj) {
  11998. const e = obj;
  11999. return this.compareDirection(e);
  12000. }
  12001. getDirectedCoordinate() {
  12002. return this._p1;
  12003. }
  12004. getDx() {
  12005. return this._dx;
  12006. }
  12007. getLabel() {
  12008. return this._label;
  12009. }
  12010. getEdge() {
  12011. return this._edge;
  12012. }
  12013. getQuadrant() {
  12014. return this._quadrant;
  12015. }
  12016. getNode() {
  12017. return this._node;
  12018. }
  12019. toString() {
  12020. const angle = Math.atan2(this._dy, this._dx);
  12021. const className = this.getClass().getName();
  12022. const lastDotPos = className.lastIndexOf('.');
  12023. const name = className.substring(lastDotPos + 1);
  12024. return ' ' + name + ': ' + this._p0 + ' - ' + this._p1 + ' ' + this._quadrant + ':' + angle + ' ' + this._label;
  12025. }
  12026. computeLabel(boundaryNodeRule) {}
  12027. init(p0, p1) {
  12028. this._p0 = p0;
  12029. this._p1 = p1;
  12030. this._dx = p1.x - p0.x;
  12031. this._dy = p1.y - p0.y;
  12032. this._quadrant = Quadrant.quadrant(this._dx, this._dy);
  12033. Assert.isTrue(!(this._dx === 0 && this._dy === 0), 'EdgeEnd with identical endpoints found');
  12034. }
  12035. get interfaces_() {
  12036. return [Comparable];
  12037. }
  12038. }
  12039. class TopologyException extends RuntimeException {
  12040. constructor(msg, pt) {
  12041. super(pt ? msg + ' [ ' + pt + ' ]' : msg);
  12042. this.pt = pt ? new Coordinate(pt) : undefined;
  12043. this.name = Object.keys({
  12044. TopologyException
  12045. })[0];
  12046. }
  12047. getCoordinate() {
  12048. return this.pt;
  12049. }
  12050. }
  12051. class DirectedEdge$1 extends EdgeEnd {
  12052. constructor() {
  12053. super();
  12054. DirectedEdge$1.constructor_.apply(this, arguments);
  12055. }
  12056. static constructor_() {
  12057. this._isForward = null;
  12058. this._isInResult = false;
  12059. this._isVisited = false;
  12060. this._sym = null;
  12061. this._next = null;
  12062. this._nextMin = null;
  12063. this._edgeRing = null;
  12064. this._minEdgeRing = null;
  12065. this._depth = [0, -999, -999];
  12066. const edge = arguments[0],
  12067. isForward = arguments[1];
  12068. EdgeEnd.constructor_.call(this, edge);
  12069. this._isForward = isForward;
  12070. if (isForward) {
  12071. this.init(edge.getCoordinate(0), edge.getCoordinate(1));
  12072. } else {
  12073. const n = edge.getNumPoints() - 1;
  12074. this.init(edge.getCoordinate(n), edge.getCoordinate(n - 1));
  12075. }
  12076. this.computeDirectedLabel();
  12077. }
  12078. static depthFactor(currLocation, nextLocation) {
  12079. if (currLocation === Location.EXTERIOR && nextLocation === Location.INTERIOR) return 1;else if (currLocation === Location.INTERIOR && nextLocation === Location.EXTERIOR) return -1;
  12080. return 0;
  12081. }
  12082. getNextMin() {
  12083. return this._nextMin;
  12084. }
  12085. getDepth(position) {
  12086. return this._depth[position];
  12087. }
  12088. setVisited(isVisited) {
  12089. this._isVisited = isVisited;
  12090. }
  12091. computeDirectedLabel() {
  12092. this._label = new Label(this._edge.getLabel());
  12093. if (!this._isForward) this._label.flip();
  12094. }
  12095. getNext() {
  12096. return this._next;
  12097. }
  12098. setDepth(position, depthVal) {
  12099. if (this._depth[position] !== -999) if (this._depth[position] !== depthVal) throw new TopologyException('assigned depths do not match', this.getCoordinate());
  12100. this._depth[position] = depthVal;
  12101. }
  12102. isInteriorAreaEdge() {
  12103. let isInteriorAreaEdge = true;
  12104. for (let i = 0; i < 2; i++) if (!(this._label.isArea(i) && this._label.getLocation(i, Position.LEFT) === Location.INTERIOR && this._label.getLocation(i, Position.RIGHT) === Location.INTERIOR)) isInteriorAreaEdge = false;
  12105. return isInteriorAreaEdge;
  12106. }
  12107. setNextMin(nextMin) {
  12108. this._nextMin = nextMin;
  12109. }
  12110. print(out) {
  12111. super.print.call(this, out);
  12112. out.print(' ' + this._depth[Position.LEFT] + '/' + this._depth[Position.RIGHT]);
  12113. out.print(' (' + this.getDepthDelta() + ')');
  12114. if (this._isInResult) out.print(' inResult');
  12115. }
  12116. setMinEdgeRing(minEdgeRing) {
  12117. this._minEdgeRing = minEdgeRing;
  12118. }
  12119. isLineEdge() {
  12120. const isLine = this._label.isLine(0) || this._label.isLine(1);
  12121. const isExteriorIfArea0 = !this._label.isArea(0) || this._label.allPositionsEqual(0, Location.EXTERIOR);
  12122. const isExteriorIfArea1 = !this._label.isArea(1) || this._label.allPositionsEqual(1, Location.EXTERIOR);
  12123. return isLine && isExteriorIfArea0 && isExteriorIfArea1;
  12124. }
  12125. setEdgeRing(edgeRing) {
  12126. this._edgeRing = edgeRing;
  12127. }
  12128. getMinEdgeRing() {
  12129. return this._minEdgeRing;
  12130. }
  12131. getDepthDelta() {
  12132. let depthDelta = this._edge.getDepthDelta();
  12133. if (!this._isForward) depthDelta = -depthDelta;
  12134. return depthDelta;
  12135. }
  12136. setInResult(isInResult) {
  12137. this._isInResult = isInResult;
  12138. }
  12139. getSym() {
  12140. return this._sym;
  12141. }
  12142. isForward() {
  12143. return this._isForward;
  12144. }
  12145. getEdge() {
  12146. return this._edge;
  12147. }
  12148. printEdge(out) {
  12149. this.print(out);
  12150. out.print(' ');
  12151. if (this._isForward) this._edge.print(out);else this._edge.printReverse(out);
  12152. }
  12153. setSym(de) {
  12154. this._sym = de;
  12155. }
  12156. setVisitedEdge(isVisited) {
  12157. this.setVisited(isVisited);
  12158. this._sym.setVisited(isVisited);
  12159. }
  12160. setEdgeDepths(position, depth) {
  12161. let depthDelta = this.getEdge().getDepthDelta();
  12162. if (!this._isForward) depthDelta = -depthDelta;
  12163. let directionFactor = 1;
  12164. if (position === Position.LEFT) directionFactor = -1;
  12165. const oppositePos = Position.opposite(position);
  12166. const delta = depthDelta * directionFactor;
  12167. const oppositeDepth = depth + delta;
  12168. this.setDepth(position, depth);
  12169. this.setDepth(oppositePos, oppositeDepth);
  12170. }
  12171. getEdgeRing() {
  12172. return this._edgeRing;
  12173. }
  12174. isInResult() {
  12175. return this._isInResult;
  12176. }
  12177. setNext(next) {
  12178. this._next = next;
  12179. }
  12180. isVisited() {
  12181. return this._isVisited;
  12182. }
  12183. }
  12184. class NodeFactory {
  12185. createNode(coord) {
  12186. return new Node$2(coord, null);
  12187. }
  12188. }
  12189. class PlanarGraph$1 {
  12190. constructor() {
  12191. PlanarGraph$1.constructor_.apply(this, arguments);
  12192. }
  12193. static constructor_() {
  12194. this._edges = new ArrayList();
  12195. this._nodes = null;
  12196. this._edgeEndList = new ArrayList();
  12197. if (arguments.length === 0) {
  12198. this._nodes = new NodeMap$1(new NodeFactory());
  12199. } else if (arguments.length === 1) {
  12200. const nodeFact = arguments[0];
  12201. this._nodes = new NodeMap$1(nodeFact);
  12202. }
  12203. }
  12204. static linkResultDirectedEdges(nodes) {
  12205. for (let nodeit = nodes.iterator(); nodeit.hasNext();) {
  12206. const node = nodeit.next();
  12207. node.getEdges().linkResultDirectedEdges();
  12208. }
  12209. }
  12210. printEdges(out) {
  12211. out.println('Edges:');
  12212. for (let i = 0; i < this._edges.size(); i++) {
  12213. out.println('edge ' + i + ':');
  12214. const e = this._edges.get(i);
  12215. e.print(out);
  12216. e.eiList.print(out);
  12217. }
  12218. }
  12219. find(coord) {
  12220. return this._nodes.find(coord);
  12221. }
  12222. addNode() {
  12223. if (arguments[0] instanceof Node$2) {
  12224. const node = arguments[0];
  12225. return this._nodes.addNode(node);
  12226. } else if (arguments[0] instanceof Coordinate) {
  12227. const coord = arguments[0];
  12228. return this._nodes.addNode(coord);
  12229. }
  12230. }
  12231. getNodeIterator() {
  12232. return this._nodes.iterator();
  12233. }
  12234. linkResultDirectedEdges() {
  12235. for (let nodeit = this._nodes.iterator(); nodeit.hasNext();) {
  12236. const node = nodeit.next();
  12237. node.getEdges().linkResultDirectedEdges();
  12238. }
  12239. }
  12240. debugPrintln(o) {
  12241. System.out.println(o);
  12242. }
  12243. isBoundaryNode(geomIndex, coord) {
  12244. const node = this._nodes.find(coord);
  12245. if (node === null) return false;
  12246. const label = node.getLabel();
  12247. if (label !== null && label.getLocation(geomIndex) === Location.BOUNDARY) return true;
  12248. return false;
  12249. }
  12250. linkAllDirectedEdges() {
  12251. for (let nodeit = this._nodes.iterator(); nodeit.hasNext();) {
  12252. const node = nodeit.next();
  12253. node.getEdges().linkAllDirectedEdges();
  12254. }
  12255. }
  12256. matchInSameDirection(p0, p1, ep0, ep1) {
  12257. if (!p0.equals(ep0)) return false;
  12258. if (Orientation.index(p0, p1, ep1) === Orientation.COLLINEAR && Quadrant.quadrant(p0, p1) === Quadrant.quadrant(ep0, ep1)) return true;
  12259. return false;
  12260. }
  12261. getEdgeEnds() {
  12262. return this._edgeEndList;
  12263. }
  12264. debugPrint(o) {
  12265. System.out.print(o);
  12266. }
  12267. getEdgeIterator() {
  12268. return this._edges.iterator();
  12269. }
  12270. findEdgeInSameDirection(p0, p1) {
  12271. for (let i = 0; i < this._edges.size(); i++) {
  12272. const e = this._edges.get(i);
  12273. const eCoord = e.getCoordinates();
  12274. if (this.matchInSameDirection(p0, p1, eCoord[0], eCoord[1])) return e;
  12275. if (this.matchInSameDirection(p0, p1, eCoord[eCoord.length - 1], eCoord[eCoord.length - 2])) return e;
  12276. }
  12277. return null;
  12278. }
  12279. insertEdge(e) {
  12280. this._edges.add(e);
  12281. }
  12282. findEdgeEnd(e) {
  12283. for (let i = this.getEdgeEnds().iterator(); i.hasNext();) {
  12284. const ee = i.next();
  12285. if (ee.getEdge() === e) return ee;
  12286. }
  12287. return null;
  12288. }
  12289. addEdges(edgesToAdd) {
  12290. for (let it = edgesToAdd.iterator(); it.hasNext();) {
  12291. const e = it.next();
  12292. this._edges.add(e);
  12293. const de1 = new DirectedEdge$1(e, true);
  12294. const de2 = new DirectedEdge$1(e, false);
  12295. de1.setSym(de2);
  12296. de2.setSym(de1);
  12297. this.add(de1);
  12298. this.add(de2);
  12299. }
  12300. }
  12301. add(e) {
  12302. this._nodes.add(e);
  12303. this._edgeEndList.add(e);
  12304. }
  12305. getNodes() {
  12306. return this._nodes.values();
  12307. }
  12308. findEdge(p0, p1) {
  12309. for (let i = 0; i < this._edges.size(); i++) {
  12310. const e = this._edges.get(i);
  12311. const eCoord = e.getCoordinates();
  12312. if (p0.equals(eCoord[0]) && p1.equals(eCoord[1])) return e;
  12313. }
  12314. return null;
  12315. }
  12316. }
  12317. class GeometryGraph extends PlanarGraph$1 {
  12318. constructor() {
  12319. super();
  12320. GeometryGraph.constructor_.apply(this, arguments);
  12321. }
  12322. static constructor_() {
  12323. this._parentGeom = null;
  12324. this._lineEdgeMap = new HashMap();
  12325. this._boundaryNodeRule = null;
  12326. this._useBoundaryDeterminationRule = true;
  12327. this._argIndex = null;
  12328. this._boundaryNodes = null;
  12329. this._hasTooFewPoints = false;
  12330. this._invalidPoint = null;
  12331. this._areaPtLocator = null;
  12332. this._ptLocator = new PointLocator();
  12333. if (arguments.length === 2) {
  12334. const argIndex = arguments[0],
  12335. parentGeom = arguments[1];
  12336. GeometryGraph.constructor_.call(this, argIndex, parentGeom, BoundaryNodeRule.OGC_SFS_BOUNDARY_RULE);
  12337. } else if (arguments.length === 3) {
  12338. const argIndex = arguments[0],
  12339. parentGeom = arguments[1],
  12340. boundaryNodeRule = arguments[2];
  12341. this._argIndex = argIndex;
  12342. this._parentGeom = parentGeom;
  12343. this._boundaryNodeRule = boundaryNodeRule;
  12344. if (parentGeom !== null) this.add(parentGeom);
  12345. }
  12346. }
  12347. static determineBoundary(boundaryNodeRule, boundaryCount) {
  12348. return boundaryNodeRule.isInBoundary(boundaryCount) ? Location.BOUNDARY : Location.INTERIOR;
  12349. }
  12350. insertBoundaryPoint(argIndex, coord) {
  12351. const n = this._nodes.addNode(coord);
  12352. const lbl = n.getLabel();
  12353. let boundaryCount = 1;
  12354. let loc = Location.NONE;
  12355. loc = lbl.getLocation(argIndex, Position.ON);
  12356. if (loc === Location.BOUNDARY) boundaryCount++;
  12357. const newLoc = GeometryGraph.determineBoundary(this._boundaryNodeRule, boundaryCount);
  12358. lbl.setLocation(argIndex, newLoc);
  12359. }
  12360. computeSelfNodes() {
  12361. if (arguments.length === 2) {
  12362. const li = arguments[0],
  12363. computeRingSelfNodes = arguments[1];
  12364. return this.computeSelfNodes(li, computeRingSelfNodes, false);
  12365. } else if (arguments.length === 3) {
  12366. const li = arguments[0],
  12367. computeRingSelfNodes = arguments[1],
  12368. isDoneIfProperInt = arguments[2];
  12369. const si = new SegmentIntersector$1(li, true, false);
  12370. si.setIsDoneIfProperInt(isDoneIfProperInt);
  12371. const esi = this.createEdgeSetIntersector();
  12372. const isRings = this._parentGeom instanceof LinearRing || this._parentGeom instanceof Polygon || this._parentGeom instanceof MultiPolygon;
  12373. const computeAllSegments = computeRingSelfNodes || !isRings;
  12374. esi.computeIntersections(this._edges, si, computeAllSegments);
  12375. this.addSelfIntersectionNodes(this._argIndex);
  12376. return si;
  12377. }
  12378. }
  12379. computeSplitEdges(edgelist) {
  12380. for (let i = this._edges.iterator(); i.hasNext();) {
  12381. const e = i.next();
  12382. e.eiList.addSplitEdges(edgelist);
  12383. }
  12384. }
  12385. computeEdgeIntersections(g, li, includeProper) {
  12386. const si = new SegmentIntersector$1(li, includeProper, true);
  12387. si.setBoundaryNodes(this.getBoundaryNodes(), g.getBoundaryNodes());
  12388. const esi = this.createEdgeSetIntersector();
  12389. esi.computeIntersections(this._edges, g._edges, si);
  12390. return si;
  12391. }
  12392. getGeometry() {
  12393. return this._parentGeom;
  12394. }
  12395. getBoundaryNodeRule() {
  12396. return this._boundaryNodeRule;
  12397. }
  12398. hasTooFewPoints() {
  12399. return this._hasTooFewPoints;
  12400. }
  12401. addPoint() {
  12402. if (arguments[0] instanceof Point) {
  12403. const p = arguments[0];
  12404. const coord = p.getCoordinate();
  12405. this.insertPoint(this._argIndex, coord, Location.INTERIOR);
  12406. } else if (arguments[0] instanceof Coordinate) {
  12407. const pt = arguments[0];
  12408. this.insertPoint(this._argIndex, pt, Location.INTERIOR);
  12409. }
  12410. }
  12411. addPolygon(p) {
  12412. this.addPolygonRing(p.getExteriorRing(), Location.EXTERIOR, Location.INTERIOR);
  12413. for (let i = 0; i < p.getNumInteriorRing(); i++) {
  12414. const hole = p.getInteriorRingN(i);
  12415. this.addPolygonRing(hole, Location.INTERIOR, Location.EXTERIOR);
  12416. }
  12417. }
  12418. addEdge(e) {
  12419. this.insertEdge(e);
  12420. const coord = e.getCoordinates();
  12421. this.insertPoint(this._argIndex, coord[0], Location.BOUNDARY);
  12422. this.insertPoint(this._argIndex, coord[coord.length - 1], Location.BOUNDARY);
  12423. }
  12424. addLineString(line) {
  12425. const coord = CoordinateArrays.removeRepeatedPoints(line.getCoordinates());
  12426. if (coord.length < 2) {
  12427. this._hasTooFewPoints = true;
  12428. this._invalidPoint = coord[0];
  12429. return null;
  12430. }
  12431. const e = new Edge$1(coord, new Label(this._argIndex, Location.INTERIOR));
  12432. this._lineEdgeMap.put(line, e);
  12433. this.insertEdge(e);
  12434. Assert.isTrue(coord.length >= 2, 'found LineString with single point');
  12435. this.insertBoundaryPoint(this._argIndex, coord[0]);
  12436. this.insertBoundaryPoint(this._argIndex, coord[coord.length - 1]);
  12437. }
  12438. getInvalidPoint() {
  12439. return this._invalidPoint;
  12440. }
  12441. getBoundaryPoints() {
  12442. const coll = this.getBoundaryNodes();
  12443. const pts = new Array(coll.size()).fill(null);
  12444. let i = 0;
  12445. for (let it = coll.iterator(); it.hasNext();) {
  12446. const node = it.next();
  12447. pts[i++] = node.getCoordinate().copy();
  12448. }
  12449. return pts;
  12450. }
  12451. getBoundaryNodes() {
  12452. if (this._boundaryNodes === null) this._boundaryNodes = this._nodes.getBoundaryNodes(this._argIndex);
  12453. return this._boundaryNodes;
  12454. }
  12455. addSelfIntersectionNode(argIndex, coord, loc) {
  12456. if (this.isBoundaryNode(argIndex, coord)) return null;
  12457. if (loc === Location.BOUNDARY && this._useBoundaryDeterminationRule) this.insertBoundaryPoint(argIndex, coord);else this.insertPoint(argIndex, coord, loc);
  12458. }
  12459. addPolygonRing(lr, cwLeft, cwRight) {
  12460. if (lr.isEmpty()) return null;
  12461. const coord = CoordinateArrays.removeRepeatedPoints(lr.getCoordinates());
  12462. if (coord.length < 4) {
  12463. this._hasTooFewPoints = true;
  12464. this._invalidPoint = coord[0];
  12465. return null;
  12466. }
  12467. let left = cwLeft;
  12468. let right = cwRight;
  12469. if (Orientation.isCCW(coord)) {
  12470. left = cwRight;
  12471. right = cwLeft;
  12472. }
  12473. const e = new Edge$1(coord, new Label(this._argIndex, Location.BOUNDARY, left, right));
  12474. this._lineEdgeMap.put(lr, e);
  12475. this.insertEdge(e);
  12476. this.insertPoint(this._argIndex, coord[0], Location.BOUNDARY);
  12477. }
  12478. insertPoint(argIndex, coord, onLocation) {
  12479. const n = this._nodes.addNode(coord);
  12480. const lbl = n.getLabel();
  12481. if (lbl === null) n._label = new Label(argIndex, onLocation);else lbl.setLocation(argIndex, onLocation);
  12482. }
  12483. createEdgeSetIntersector() {
  12484. return new SimpleMCSweepLineIntersector();
  12485. }
  12486. addSelfIntersectionNodes(argIndex) {
  12487. for (let i = this._edges.iterator(); i.hasNext();) {
  12488. const e = i.next();
  12489. const eLoc = e.getLabel().getLocation(argIndex);
  12490. for (let eiIt = e.eiList.iterator(); eiIt.hasNext();) {
  12491. const ei = eiIt.next();
  12492. this.addSelfIntersectionNode(argIndex, ei.coord, eLoc);
  12493. }
  12494. }
  12495. }
  12496. add() {
  12497. if (arguments.length === 1 && arguments[0] instanceof Geometry) {
  12498. const g = arguments[0];
  12499. if (g.isEmpty()) return null;
  12500. if (g instanceof MultiPolygon) this._useBoundaryDeterminationRule = false;
  12501. if (g instanceof Polygon) this.addPolygon(g);else if (g instanceof LineString) this.addLineString(g);else if (g instanceof Point) this.addPoint(g);else if (g instanceof MultiPoint) this.addCollection(g);else if (g instanceof MultiLineString) this.addCollection(g);else if (g instanceof MultiPolygon) this.addCollection(g);else if (g instanceof GeometryCollection) this.addCollection(g);else throw new UnsupportedOperationException(g.getGeometryType());
  12502. } else {
  12503. return super.add.apply(this, arguments);
  12504. }
  12505. }
  12506. addCollection(gc) {
  12507. for (let i = 0; i < gc.getNumGeometries(); i++) {
  12508. const g = gc.getGeometryN(i);
  12509. this.add(g);
  12510. }
  12511. }
  12512. locate(pt) {
  12513. if (hasInterface(this._parentGeom, Polygonal) && this._parentGeom.getNumGeometries() > 50) {
  12514. if (this._areaPtLocator === null) this._areaPtLocator = new IndexedPointInAreaLocator(this._parentGeom);
  12515. return this._areaPtLocator.locate(pt);
  12516. }
  12517. return this._ptLocator.locate(pt, this._parentGeom);
  12518. }
  12519. findEdge() {
  12520. if (arguments.length === 1 && arguments[0] instanceof LineString) {
  12521. const line = arguments[0];
  12522. return this._lineEdgeMap.get(line);
  12523. } else {
  12524. return super.findEdge.apply(this, arguments);
  12525. }
  12526. }
  12527. }
  12528. var geomgraph = /*#__PURE__*/Object.freeze({
  12529. __proto__: null,
  12530. GeometryGraph: GeometryGraph
  12531. });
  12532. class KdNodeVisitor {
  12533. visit(node) {}
  12534. }
  12535. class KdNode {
  12536. constructor() {
  12537. KdNode.constructor_.apply(this, arguments);
  12538. }
  12539. static constructor_() {
  12540. this._p = null;
  12541. this._data = null;
  12542. this._left = null;
  12543. this._right = null;
  12544. this._count = null;
  12545. if (arguments.length === 2) {
  12546. const p = arguments[0],
  12547. data = arguments[1];
  12548. this._p = new Coordinate(p);
  12549. this._left = null;
  12550. this._right = null;
  12551. this._count = 1;
  12552. this._data = data;
  12553. } else if (arguments.length === 3) {
  12554. const _x = arguments[0],
  12555. _y = arguments[1],
  12556. data = arguments[2];
  12557. this._p = new Coordinate(_x, _y);
  12558. this._left = null;
  12559. this._right = null;
  12560. this._count = 1;
  12561. this._data = data;
  12562. }
  12563. }
  12564. isRepeated() {
  12565. return this._count > 1;
  12566. }
  12567. getRight() {
  12568. return this._right;
  12569. }
  12570. getCoordinate() {
  12571. return this._p;
  12572. }
  12573. setLeft(_left) {
  12574. this._left = _left;
  12575. }
  12576. getX() {
  12577. return this._p.x;
  12578. }
  12579. getData() {
  12580. return this._data;
  12581. }
  12582. getCount() {
  12583. return this._count;
  12584. }
  12585. getLeft() {
  12586. return this._left;
  12587. }
  12588. getY() {
  12589. return this._p.y;
  12590. }
  12591. increment() {
  12592. this._count = this._count + 1;
  12593. }
  12594. setRight(_right) {
  12595. this._right = _right;
  12596. }
  12597. }
  12598. class KdTree {
  12599. constructor() {
  12600. KdTree.constructor_.apply(this, arguments);
  12601. }
  12602. static constructor_() {
  12603. this._root = null;
  12604. this._numberOfNodes = null;
  12605. this._tolerance = null;
  12606. if (arguments.length === 0) {
  12607. KdTree.constructor_.call(this, 0.0);
  12608. } else if (arguments.length === 1) {
  12609. const tolerance = arguments[0];
  12610. this._tolerance = tolerance;
  12611. }
  12612. }
  12613. static toCoordinates() {
  12614. if (arguments.length === 1) {
  12615. const kdnodes = arguments[0];
  12616. return KdTree.toCoordinates(kdnodes, false);
  12617. } else if (arguments.length === 2) {
  12618. const kdnodes = arguments[0],
  12619. includeRepeated = arguments[1];
  12620. const coord = new CoordinateList();
  12621. for (let it = kdnodes.iterator(); it.hasNext();) {
  12622. const node = it.next();
  12623. const count = includeRepeated ? node.getCount() : 1;
  12624. for (let i = 0; i < count; i++) coord.add(node.getCoordinate(), true);
  12625. }
  12626. return coord.toCoordinateArray();
  12627. }
  12628. }
  12629. insert() {
  12630. if (arguments.length === 1) {
  12631. const p = arguments[0];
  12632. return this.insert(p, null);
  12633. } else if (arguments.length === 2) {
  12634. const p = arguments[0],
  12635. data = arguments[1];
  12636. if (this._root === null) {
  12637. this._root = new KdNode(p, data);
  12638. return this._root;
  12639. }
  12640. if (this._tolerance > 0) {
  12641. const matchNode = this.findBestMatchNode(p);
  12642. if (matchNode !== null) {
  12643. matchNode.increment();
  12644. return matchNode;
  12645. }
  12646. }
  12647. return this.insertExact(p, data);
  12648. }
  12649. }
  12650. query() {
  12651. if (arguments.length === 1) {
  12652. const queryEnv = arguments[0];
  12653. const result = new ArrayList();
  12654. this.query(queryEnv, result);
  12655. return result;
  12656. } else if (arguments.length === 2) {
  12657. if (arguments[0] instanceof Envelope && hasInterface(arguments[1], List)) {
  12658. const queryEnv = arguments[0],
  12659. result = arguments[1];
  12660. this.queryNode(this._root, queryEnv, true, new class {
  12661. get interfaces_() {
  12662. return [KdNodeVisitor];
  12663. }
  12664. visit(node) {
  12665. result.add(node);
  12666. }
  12667. }());
  12668. } else if (arguments[0] instanceof Envelope && hasInterface(arguments[1], KdNodeVisitor)) {
  12669. const queryEnv = arguments[0],
  12670. visitor = arguments[1];
  12671. this.queryNode(this._root, queryEnv, true, visitor);
  12672. }
  12673. }
  12674. }
  12675. queryNode(currentNode, queryEnv, odd, visitor) {
  12676. if (currentNode === null) return null;
  12677. let min = null;
  12678. let max = null;
  12679. let discriminant = null;
  12680. if (odd) {
  12681. min = queryEnv.getMinX();
  12682. max = queryEnv.getMaxX();
  12683. discriminant = currentNode.getX();
  12684. } else {
  12685. min = queryEnv.getMinY();
  12686. max = queryEnv.getMaxY();
  12687. discriminant = currentNode.getY();
  12688. }
  12689. const searchLeft = min < discriminant;
  12690. const searchRight = discriminant <= max;
  12691. if (searchLeft) this.queryNode(currentNode.getLeft(), queryEnv, !odd, visitor);
  12692. if (queryEnv.contains(currentNode.getCoordinate())) visitor.visit(currentNode);
  12693. if (searchRight) this.queryNode(currentNode.getRight(), queryEnv, !odd, visitor);
  12694. }
  12695. findBestMatchNode(p) {
  12696. const visitor = new BestMatchVisitor(p, this._tolerance);
  12697. this.query(visitor.queryEnvelope(), visitor);
  12698. return visitor.getNode();
  12699. }
  12700. isEmpty() {
  12701. if (this._root === null) return true;
  12702. return false;
  12703. }
  12704. insertExact(p, data) {
  12705. let currentNode = this._root;
  12706. let leafNode = this._root;
  12707. let isOddLevel = true;
  12708. let isLessThan = true;
  12709. while (currentNode !== null) {
  12710. if (currentNode !== null) {
  12711. const isInTolerance = p.distance(currentNode.getCoordinate()) <= this._tolerance;
  12712. if (isInTolerance) {
  12713. currentNode.increment();
  12714. return currentNode;
  12715. }
  12716. }
  12717. if (isOddLevel) isLessThan = p.x < currentNode.getX();else isLessThan = p.y < currentNode.getY();
  12718. leafNode = currentNode;
  12719. if (isLessThan) currentNode = currentNode.getLeft();else currentNode = currentNode.getRight();
  12720. isOddLevel = !isOddLevel;
  12721. }
  12722. this._numberOfNodes = this._numberOfNodes + 1;
  12723. const node = new KdNode(p, data);
  12724. if (isLessThan) leafNode.setLeft(node);else leafNode.setRight(node);
  12725. return node;
  12726. }
  12727. }
  12728. class BestMatchVisitor {
  12729. constructor() {
  12730. BestMatchVisitor.constructor_.apply(this, arguments);
  12731. }
  12732. static constructor_() {
  12733. this._tolerance = null;
  12734. this._matchNode = null;
  12735. this._matchDist = 0.0;
  12736. this._p = null;
  12737. const p = arguments[0],
  12738. tolerance = arguments[1];
  12739. this._p = p;
  12740. this._tolerance = tolerance;
  12741. }
  12742. visit(node) {
  12743. const dist = this._p.distance(node.getCoordinate());
  12744. const isInTolerance = dist <= this._tolerance;
  12745. if (!isInTolerance) return null;
  12746. let update = false;
  12747. if (this._matchNode === null || dist < this._matchDist || this._matchNode !== null && dist === this._matchDist && node.getCoordinate().compareTo(this._matchNode.getCoordinate()) < 1) update = true;
  12748. if (update) {
  12749. this._matchNode = node;
  12750. this._matchDist = dist;
  12751. }
  12752. }
  12753. queryEnvelope() {
  12754. const queryEnv = new Envelope(this._p);
  12755. queryEnv.expandBy(this._tolerance);
  12756. return queryEnv;
  12757. }
  12758. getNode() {
  12759. return this._matchNode;
  12760. }
  12761. get interfaces_() {
  12762. return [KdNodeVisitor];
  12763. }
  12764. }
  12765. KdTree.BestMatchVisitor = BestMatchVisitor;
  12766. var kdtree = /*#__PURE__*/Object.freeze({
  12767. __proto__: null,
  12768. KdTree: KdTree
  12769. });
  12770. class NodeBase {
  12771. constructor() {
  12772. NodeBase.constructor_.apply(this, arguments);
  12773. }
  12774. static constructor_() {
  12775. this._items = new ArrayList();
  12776. this._subnode = new Array(4).fill(null);
  12777. }
  12778. static getSubnodeIndex(env, centrex, centrey) {
  12779. let subnodeIndex = -1;
  12780. if (env.getMinX() >= centrex) {
  12781. if (env.getMinY() >= centrey) subnodeIndex = 3;
  12782. if (env.getMaxY() <= centrey) subnodeIndex = 1;
  12783. }
  12784. if (env.getMaxX() <= centrex) {
  12785. if (env.getMinY() >= centrey) subnodeIndex = 2;
  12786. if (env.getMaxY() <= centrey) subnodeIndex = 0;
  12787. }
  12788. return subnodeIndex;
  12789. }
  12790. hasChildren() {
  12791. for (let i = 0; i < 4; i++) if (this._subnode[i] !== null) return true;
  12792. return false;
  12793. }
  12794. isPrunable() {
  12795. return !(this.hasChildren() || this.hasItems());
  12796. }
  12797. addAllItems(resultItems) {
  12798. resultItems.addAll(this._items);
  12799. for (let i = 0; i < 4; i++) if (this._subnode[i] !== null) this._subnode[i].addAllItems(resultItems);
  12800. return resultItems;
  12801. }
  12802. getNodeCount() {
  12803. let subSize = 0;
  12804. for (let i = 0; i < 4; i++) if (this._subnode[i] !== null) subSize += this._subnode[i].size();
  12805. return subSize + 1;
  12806. }
  12807. size() {
  12808. let subSize = 0;
  12809. for (let i = 0; i < 4; i++) if (this._subnode[i] !== null) subSize += this._subnode[i].size();
  12810. return subSize + this._items.size();
  12811. }
  12812. addAllItemsFromOverlapping(searchEnv, resultItems) {
  12813. if (!this.isSearchMatch(searchEnv)) return null;
  12814. resultItems.addAll(this._items);
  12815. for (let i = 0; i < 4; i++) if (this._subnode[i] !== null) this._subnode[i].addAllItemsFromOverlapping(searchEnv, resultItems);
  12816. }
  12817. visitItems(searchEnv, visitor) {
  12818. for (let i = this._items.iterator(); i.hasNext();) visitor.visitItem(i.next());
  12819. }
  12820. hasItems() {
  12821. return !this._items.isEmpty();
  12822. }
  12823. remove(itemEnv, item) {
  12824. if (!this.isSearchMatch(itemEnv)) return false;
  12825. let found = false;
  12826. for (let i = 0; i < 4; i++) if (this._subnode[i] !== null) {
  12827. found = this._subnode[i].remove(itemEnv, item);
  12828. if (found) {
  12829. if (this._subnode[i].isPrunable()) this._subnode[i] = null;
  12830. break;
  12831. }
  12832. }
  12833. if (found) return found;
  12834. found = this._items.remove(item);
  12835. return found;
  12836. }
  12837. visit(searchEnv, visitor) {
  12838. if (!this.isSearchMatch(searchEnv)) return null;
  12839. this.visitItems(searchEnv, visitor);
  12840. for (let i = 0; i < 4; i++) if (this._subnode[i] !== null) this._subnode[i].visit(searchEnv, visitor);
  12841. }
  12842. getItems() {
  12843. return this._items;
  12844. }
  12845. depth() {
  12846. let maxSubDepth = 0;
  12847. for (let i = 0; i < 4; i++) if (this._subnode[i] !== null) {
  12848. const sqd = this._subnode[i].depth();
  12849. if (sqd > maxSubDepth) maxSubDepth = sqd;
  12850. }
  12851. return maxSubDepth + 1;
  12852. }
  12853. isEmpty() {
  12854. let isEmpty = true;
  12855. if (!this._items.isEmpty()) isEmpty = false;else for (let i = 0; i < 4; i++) if (this._subnode[i] !== null) if (!this._subnode[i].isEmpty()) {
  12856. isEmpty = false;
  12857. break;
  12858. }
  12859. return isEmpty;
  12860. }
  12861. add(item) {
  12862. this._items.add(item);
  12863. }
  12864. get interfaces_() {
  12865. return [Serializable];
  12866. }
  12867. }
  12868. function DoubleBits() {}
  12869. DoubleBits.exponent = function (d) {
  12870. return CVTFWD(64, d) - 1023;
  12871. };
  12872. DoubleBits.powerOf2 = function (exp) {
  12873. return Math.pow(2, exp);
  12874. };
  12875. /**
  12876. * Calculates the exponent of the bit-pattern for a number. Uses code from:
  12877. * http://www.merlyn.demon.co.uk/js-exact.htm
  12878. *
  12879. * @param {Number}
  12880. * NumW 32 or 64 to denote the number of bits.
  12881. * @param {Number}
  12882. * Qty the number to calculate the bit pattern for.
  12883. * @return {Number} The integer value of the exponent.
  12884. * @private
  12885. */
  12886. function CVTFWD(NumW, Qty) {
  12887. let Sign;
  12888. let Expo;
  12889. let Mant;
  12890. let Bin;
  12891. const Inf = {
  12892. 32: {
  12893. d: 0x7F,
  12894. c: 0x80,
  12895. b: 0,
  12896. a: 0
  12897. },
  12898. 64: {
  12899. d: 0x7FF0,
  12900. c: 0,
  12901. b: 0,
  12902. a: 0
  12903. }
  12904. };
  12905. const ExW = {
  12906. 32: 8,
  12907. 64: 11
  12908. }[NumW];
  12909. if (!Bin) {
  12910. Sign = Qty < 0 || 1 / Qty < 0; // OK for +-0
  12911. if (!isFinite(Qty)) {
  12912. Bin = Inf[NumW];
  12913. if (Sign) Bin.d += 1 << NumW / 4 - 1;
  12914. Expo = Math.pow(2, ExW) - 1;
  12915. Mant = 0;
  12916. }
  12917. }
  12918. if (!Bin) {
  12919. Expo = {
  12920. 32: 127,
  12921. 64: 1023
  12922. }[NumW];
  12923. Mant = Math.abs(Qty);
  12924. while (Mant >= 2) {
  12925. Expo++;
  12926. Mant /= 2;
  12927. }
  12928. while (Mant < 1 && Expo > 0) {
  12929. Expo--;
  12930. Mant *= 2;
  12931. }
  12932. if (Expo <= 0) Mant /= 2;
  12933. if (NumW === 32 && Expo > 254) {
  12934. Bin = {
  12935. d: Sign ? 0xFF : 0x7F,
  12936. c: 0x80,
  12937. b: 0,
  12938. a: 0
  12939. };
  12940. Expo = Math.pow(2, ExW) - 1;
  12941. Mant = 0;
  12942. }
  12943. }
  12944. return Expo;
  12945. }
  12946. class Key {
  12947. constructor() {
  12948. Key.constructor_.apply(this, arguments);
  12949. }
  12950. static constructor_() {
  12951. this._pt = new Coordinate();
  12952. this._level = 0;
  12953. this._env = null;
  12954. const itemEnv = arguments[0];
  12955. this.computeKey(itemEnv);
  12956. }
  12957. static computeQuadLevel(env) {
  12958. const dx = env.getWidth();
  12959. const dy = env.getHeight();
  12960. const dMax = dx > dy ? dx : dy;
  12961. const level = DoubleBits.exponent(dMax) + 1;
  12962. return level;
  12963. }
  12964. getLevel() {
  12965. return this._level;
  12966. }
  12967. computeKey() {
  12968. if (arguments.length === 1) {
  12969. const itemEnv = arguments[0];
  12970. this._level = Key.computeQuadLevel(itemEnv);
  12971. this._env = new Envelope();
  12972. this.computeKey(this._level, itemEnv);
  12973. while (!this._env.contains(itemEnv)) {
  12974. this._level += 1;
  12975. this.computeKey(this._level, itemEnv);
  12976. }
  12977. } else if (arguments.length === 2) {
  12978. const level = arguments[0],
  12979. itemEnv = arguments[1];
  12980. const quadSize = DoubleBits.powerOf2(level);
  12981. this._pt.x = Math.floor(itemEnv.getMinX() / quadSize) * quadSize;
  12982. this._pt.y = Math.floor(itemEnv.getMinY() / quadSize) * quadSize;
  12983. this._env.init(this._pt.x, this._pt.x + quadSize, this._pt.y, this._pt.y + quadSize);
  12984. }
  12985. }
  12986. getEnvelope() {
  12987. return this._env;
  12988. }
  12989. getCentre() {
  12990. return new Coordinate((this._env.getMinX() + this._env.getMaxX()) / 2, (this._env.getMinY() + this._env.getMaxY()) / 2);
  12991. }
  12992. getPoint() {
  12993. return this._pt;
  12994. }
  12995. }
  12996. class Node$1 extends NodeBase {
  12997. constructor() {
  12998. super();
  12999. Node$1.constructor_.apply(this, arguments);
  13000. }
  13001. static constructor_() {
  13002. this._env = null;
  13003. this._centrex = null;
  13004. this._centrey = null;
  13005. this._level = null;
  13006. const env = arguments[0],
  13007. level = arguments[1];
  13008. this._env = env;
  13009. this._level = level;
  13010. this._centrex = (env.getMinX() + env.getMaxX()) / 2;
  13011. this._centrey = (env.getMinY() + env.getMaxY()) / 2;
  13012. }
  13013. static createNode(env) {
  13014. const key = new Key(env);
  13015. const node = new Node$1(key.getEnvelope(), key.getLevel());
  13016. return node;
  13017. }
  13018. static createExpanded(node, addEnv) {
  13019. const expandEnv = new Envelope(addEnv);
  13020. if (node !== null) expandEnv.expandToInclude(node._env);
  13021. const largerNode = Node$1.createNode(expandEnv);
  13022. if (node !== null) largerNode.insertNode(node);
  13023. return largerNode;
  13024. }
  13025. find(searchEnv) {
  13026. const subnodeIndex = NodeBase.getSubnodeIndex(searchEnv, this._centrex, this._centrey);
  13027. if (subnodeIndex === -1) return this;
  13028. if (this._subnode[subnodeIndex] !== null) {
  13029. const node = this._subnode[subnodeIndex];
  13030. return node.find(searchEnv);
  13031. }
  13032. return this;
  13033. }
  13034. isSearchMatch(searchEnv) {
  13035. if (searchEnv === null) return false;
  13036. return this._env.intersects(searchEnv);
  13037. }
  13038. getSubnode(index) {
  13039. if (this._subnode[index] === null) this._subnode[index] = this.createSubnode(index);
  13040. return this._subnode[index];
  13041. }
  13042. getEnvelope() {
  13043. return this._env;
  13044. }
  13045. getNode(searchEnv) {
  13046. const subnodeIndex = NodeBase.getSubnodeIndex(searchEnv, this._centrex, this._centrey);
  13047. if (subnodeIndex !== -1) {
  13048. const node = this.getSubnode(subnodeIndex);
  13049. return node.getNode(searchEnv);
  13050. } else {
  13051. return this;
  13052. }
  13053. }
  13054. createSubnode(index) {
  13055. let minx = 0.0;
  13056. let maxx = 0.0;
  13057. let miny = 0.0;
  13058. let maxy = 0.0;
  13059. switch (index) {
  13060. case 0:
  13061. minx = this._env.getMinX();
  13062. maxx = this._centrex;
  13063. miny = this._env.getMinY();
  13064. maxy = this._centrey;
  13065. break;
  13066. case 1:
  13067. minx = this._centrex;
  13068. maxx = this._env.getMaxX();
  13069. miny = this._env.getMinY();
  13070. maxy = this._centrey;
  13071. break;
  13072. case 2:
  13073. minx = this._env.getMinX();
  13074. maxx = this._centrex;
  13075. miny = this._centrey;
  13076. maxy = this._env.getMaxY();
  13077. break;
  13078. case 3:
  13079. minx = this._centrex;
  13080. maxx = this._env.getMaxX();
  13081. miny = this._centrey;
  13082. maxy = this._env.getMaxY();
  13083. break;
  13084. }
  13085. const sqEnv = new Envelope(minx, maxx, miny, maxy);
  13086. const node = new Node$1(sqEnv, this._level - 1);
  13087. return node;
  13088. }
  13089. insertNode(node) {
  13090. Assert.isTrue(this._env === null || this._env.contains(node._env));
  13091. const index = NodeBase.getSubnodeIndex(node._env, this._centrex, this._centrey);
  13092. if (node._level === this._level - 1) {
  13093. this._subnode[index] = node;
  13094. } else {
  13095. const childNode = this.createSubnode(index);
  13096. childNode.insertNode(node);
  13097. this._subnode[index] = childNode;
  13098. }
  13099. }
  13100. }
  13101. class IntervalSize {
  13102. static isZeroWidth(min, max) {
  13103. const width = max - min;
  13104. if (width === 0.0) return true;
  13105. const maxAbs = Math.max(Math.abs(min), Math.abs(max));
  13106. const scaledInterval = width / maxAbs;
  13107. const level = DoubleBits.exponent(scaledInterval);
  13108. return level <= IntervalSize.MIN_BINARY_EXPONENT;
  13109. }
  13110. }
  13111. IntervalSize.MIN_BINARY_EXPONENT = -50;
  13112. class Root extends NodeBase {
  13113. constructor() {
  13114. super();
  13115. }
  13116. insert(itemEnv, item) {
  13117. const index = NodeBase.getSubnodeIndex(itemEnv, Root.origin.x, Root.origin.y);
  13118. if (index === -1) {
  13119. this.add(item);
  13120. return null;
  13121. }
  13122. const node = this._subnode[index];
  13123. if (node === null || !node.getEnvelope().contains(itemEnv)) {
  13124. const largerNode = Node$1.createExpanded(node, itemEnv);
  13125. this._subnode[index] = largerNode;
  13126. }
  13127. this.insertContained(this._subnode[index], itemEnv, item);
  13128. }
  13129. isSearchMatch(searchEnv) {
  13130. return true;
  13131. }
  13132. insertContained(tree, itemEnv, item) {
  13133. Assert.isTrue(tree.getEnvelope().contains(itemEnv));
  13134. const isZeroX = IntervalSize.isZeroWidth(itemEnv.getMinX(), itemEnv.getMaxX());
  13135. const isZeroY = IntervalSize.isZeroWidth(itemEnv.getMinY(), itemEnv.getMaxY());
  13136. let node = null;
  13137. if (isZeroX || isZeroY) node = tree.find(itemEnv);else node = tree.getNode(itemEnv);
  13138. node.add(item);
  13139. }
  13140. }
  13141. Root.origin = new Coordinate(0.0, 0.0);
  13142. class SpatialIndex {
  13143. insert(itemEnv, item) {}
  13144. remove(itemEnv, item) {}
  13145. query() {
  13146. }
  13147. }
  13148. class Quadtree {
  13149. constructor() {
  13150. Quadtree.constructor_.apply(this, arguments);
  13151. }
  13152. static constructor_() {
  13153. this._root = null;
  13154. this._minExtent = 1.0;
  13155. this._root = new Root();
  13156. }
  13157. static ensureExtent(itemEnv, minExtent) {
  13158. let minx = itemEnv.getMinX();
  13159. let maxx = itemEnv.getMaxX();
  13160. let miny = itemEnv.getMinY();
  13161. let maxy = itemEnv.getMaxY();
  13162. if (minx !== maxx && miny !== maxy) return itemEnv;
  13163. if (minx === maxx) {
  13164. minx = minx - minExtent / 2.0;
  13165. maxx = maxx + minExtent / 2.0;
  13166. }
  13167. if (miny === maxy) {
  13168. miny = miny - minExtent / 2.0;
  13169. maxy = maxy + minExtent / 2.0;
  13170. }
  13171. return new Envelope(minx, maxx, miny, maxy);
  13172. }
  13173. size() {
  13174. if (this._root !== null) return this._root.size();
  13175. return 0;
  13176. }
  13177. insert(itemEnv, item) {
  13178. this.collectStats(itemEnv);
  13179. const insertEnv = Quadtree.ensureExtent(itemEnv, this._minExtent);
  13180. this._root.insert(insertEnv, item);
  13181. }
  13182. query() {
  13183. if (arguments.length === 1) {
  13184. const searchEnv = arguments[0];
  13185. const visitor = new ArrayListVisitor();
  13186. this.query(searchEnv, visitor);
  13187. return visitor.getItems();
  13188. } else if (arguments.length === 2) {
  13189. const searchEnv = arguments[0],
  13190. visitor = arguments[1];
  13191. this._root.visit(searchEnv, visitor);
  13192. }
  13193. }
  13194. queryAll() {
  13195. const foundItems = new ArrayList();
  13196. this._root.addAllItems(foundItems);
  13197. return foundItems;
  13198. }
  13199. remove(itemEnv, item) {
  13200. const posEnv = Quadtree.ensureExtent(itemEnv, this._minExtent);
  13201. return this._root.remove(posEnv, item);
  13202. }
  13203. collectStats(itemEnv) {
  13204. const delX = itemEnv.getWidth();
  13205. if (delX < this._minExtent && delX > 0.0) this._minExtent = delX;
  13206. const delY = itemEnv.getHeight();
  13207. if (delY < this._minExtent && delY > 0.0) this._minExtent = delY;
  13208. }
  13209. depth() {
  13210. if (this._root !== null) return this._root.depth();
  13211. return 0;
  13212. }
  13213. isEmpty() {
  13214. if (this._root === null) return true;
  13215. return this._root.isEmpty();
  13216. }
  13217. get interfaces_() {
  13218. return [SpatialIndex, Serializable];
  13219. }
  13220. }
  13221. var quadtree = /*#__PURE__*/Object.freeze({
  13222. __proto__: null,
  13223. Quadtree: Quadtree
  13224. });
  13225. class Boundable {
  13226. getBounds() {}
  13227. }
  13228. class ItemBoundable {
  13229. constructor() {
  13230. ItemBoundable.constructor_.apply(this, arguments);
  13231. }
  13232. static constructor_() {
  13233. this._bounds = null;
  13234. this._item = null;
  13235. const bounds = arguments[0],
  13236. item = arguments[1];
  13237. this._bounds = bounds;
  13238. this._item = item;
  13239. }
  13240. getItem() {
  13241. return this._item;
  13242. }
  13243. getBounds() {
  13244. return this._bounds;
  13245. }
  13246. get interfaces_() {
  13247. return [Boundable, Serializable];
  13248. }
  13249. }
  13250. class PriorityQueue {
  13251. constructor() {
  13252. PriorityQueue.constructor_.apply(this, arguments);
  13253. }
  13254. static constructor_() {
  13255. this._size = null;
  13256. this._items = null;
  13257. this._size = 0;
  13258. this._items = new ArrayList();
  13259. this._items.add(null);
  13260. }
  13261. poll() {
  13262. if (this.isEmpty()) return null;
  13263. const minItem = this._items.get(1);
  13264. this._items.set(1, this._items.get(this._size));
  13265. this._size -= 1;
  13266. this.reorder(1);
  13267. return minItem;
  13268. }
  13269. size() {
  13270. return this._size;
  13271. }
  13272. reorder(hole) {
  13273. let child = null;
  13274. const tmp = this._items.get(hole);
  13275. for (; hole * 2 <= this._size; hole = child) {
  13276. child = hole * 2;
  13277. if (child !== this._size && this._items.get(child + 1).compareTo(this._items.get(child)) < 0) child++;
  13278. if (this._items.get(child).compareTo(tmp) < 0) this._items.set(hole, this._items.get(child));else break;
  13279. }
  13280. this._items.set(hole, tmp);
  13281. }
  13282. clear() {
  13283. this._size = 0;
  13284. this._items.clear();
  13285. }
  13286. peek() {
  13287. if (this.isEmpty()) return null;
  13288. const minItem = this._items.get(1);
  13289. return minItem;
  13290. }
  13291. isEmpty() {
  13292. return this._size === 0;
  13293. }
  13294. add(x) {
  13295. this._items.add(null);
  13296. this._size += 1;
  13297. let hole = this._size;
  13298. this._items.set(0, x);
  13299. for (; x.compareTo(this._items.get(Math.trunc(hole / 2))) < 0; hole /= 2) this._items.set(hole, this._items.get(Math.trunc(hole / 2)));
  13300. this._items.set(hole, x);
  13301. }
  13302. }
  13303. class AbstractNode {
  13304. constructor() {
  13305. AbstractNode.constructor_.apply(this, arguments);
  13306. }
  13307. static constructor_() {
  13308. this._childBoundables = new ArrayList();
  13309. this._bounds = null;
  13310. this._level = null;
  13311. if (arguments.length === 0) ; else if (arguments.length === 1) {
  13312. const level = arguments[0];
  13313. this._level = level;
  13314. }
  13315. }
  13316. getLevel() {
  13317. return this._level;
  13318. }
  13319. size() {
  13320. return this._childBoundables.size();
  13321. }
  13322. getChildBoundables() {
  13323. return this._childBoundables;
  13324. }
  13325. addChildBoundable(childBoundable) {
  13326. Assert.isTrue(this._bounds === null);
  13327. this._childBoundables.add(childBoundable);
  13328. }
  13329. isEmpty() {
  13330. return this._childBoundables.isEmpty();
  13331. }
  13332. getBounds() {
  13333. if (this._bounds === null) this._bounds = this.computeBounds();
  13334. return this._bounds;
  13335. }
  13336. get interfaces_() {
  13337. return [Boundable, Serializable];
  13338. }
  13339. }
  13340. class EnvelopeDistance {
  13341. static maxDistance(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2) {
  13342. let dist = EnvelopeDistance.distance(ax1, ay1, bx1, by1);
  13343. dist = Math.max(dist, EnvelopeDistance.distance(ax1, ay1, bx2, by2));
  13344. dist = Math.max(dist, EnvelopeDistance.distance(ax2, ay2, bx1, by1));
  13345. dist = Math.max(dist, EnvelopeDistance.distance(ax2, ay2, bx2, by2));
  13346. return dist;
  13347. }
  13348. static distance(x1, y1, x2, y2) {
  13349. const dx = x2 - x1;
  13350. const dy = y2 - y1;
  13351. return Math.sqrt(dx * dx + dy * dy);
  13352. }
  13353. static maximumDistance(env1, env2) {
  13354. const minx = Math.min(env1.getMinX(), env2.getMinX());
  13355. const miny = Math.min(env1.getMinY(), env2.getMinY());
  13356. const maxx = Math.max(env1.getMaxX(), env2.getMaxX());
  13357. const maxy = Math.max(env1.getMaxY(), env2.getMaxY());
  13358. return EnvelopeDistance.distance(minx, miny, maxx, maxy);
  13359. }
  13360. static minMaxDistance(a, b) {
  13361. const aminx = a.getMinX();
  13362. const aminy = a.getMinY();
  13363. const amaxx = a.getMaxX();
  13364. const amaxy = a.getMaxY();
  13365. const bminx = b.getMinX();
  13366. const bminy = b.getMinY();
  13367. const bmaxx = b.getMaxX();
  13368. const bmaxy = b.getMaxY();
  13369. let dist = EnvelopeDistance.maxDistance(aminx, aminy, aminx, amaxy, bminx, bminy, bminx, bmaxy);
  13370. dist = Math.min(dist, EnvelopeDistance.maxDistance(aminx, aminy, aminx, amaxy, bminx, bminy, bmaxx, bminy));
  13371. dist = Math.min(dist, EnvelopeDistance.maxDistance(aminx, aminy, aminx, amaxy, bmaxx, bmaxy, bminx, bmaxy));
  13372. dist = Math.min(dist, EnvelopeDistance.maxDistance(aminx, aminy, aminx, amaxy, bmaxx, bmaxy, bmaxx, bminy));
  13373. dist = Math.min(dist, EnvelopeDistance.maxDistance(aminx, aminy, amaxx, aminy, bminx, bminy, bminx, bmaxy));
  13374. dist = Math.min(dist, EnvelopeDistance.maxDistance(aminx, aminy, amaxx, aminy, bminx, bminy, bmaxx, bminy));
  13375. dist = Math.min(dist, EnvelopeDistance.maxDistance(aminx, aminy, amaxx, aminy, bmaxx, bmaxy, bminx, bmaxy));
  13376. dist = Math.min(dist, EnvelopeDistance.maxDistance(aminx, aminy, amaxx, aminy, bmaxx, bmaxy, bmaxx, bminy));
  13377. dist = Math.min(dist, EnvelopeDistance.maxDistance(amaxx, amaxy, aminx, amaxy, bminx, bminy, bminx, bmaxy));
  13378. dist = Math.min(dist, EnvelopeDistance.maxDistance(amaxx, amaxy, aminx, amaxy, bminx, bminy, bmaxx, bminy));
  13379. dist = Math.min(dist, EnvelopeDistance.maxDistance(amaxx, amaxy, aminx, amaxy, bmaxx, bmaxy, bminx, bmaxy));
  13380. dist = Math.min(dist, EnvelopeDistance.maxDistance(amaxx, amaxy, aminx, amaxy, bmaxx, bmaxy, bmaxx, bminy));
  13381. dist = Math.min(dist, EnvelopeDistance.maxDistance(amaxx, amaxy, amaxx, aminy, bminx, bminy, bminx, bmaxy));
  13382. dist = Math.min(dist, EnvelopeDistance.maxDistance(amaxx, amaxy, amaxx, aminy, bminx, bminy, bmaxx, bminy));
  13383. dist = Math.min(dist, EnvelopeDistance.maxDistance(amaxx, amaxy, amaxx, aminy, bmaxx, bmaxy, bminx, bmaxy));
  13384. dist = Math.min(dist, EnvelopeDistance.maxDistance(amaxx, amaxy, amaxx, aminy, bmaxx, bmaxy, bmaxx, bminy));
  13385. return dist;
  13386. }
  13387. }
  13388. class BoundablePair {
  13389. constructor() {
  13390. BoundablePair.constructor_.apply(this, arguments);
  13391. }
  13392. static constructor_() {
  13393. this._boundable1 = null;
  13394. this._boundable2 = null;
  13395. this._distance = null;
  13396. this._itemDistance = null;
  13397. const boundable1 = arguments[0],
  13398. boundable2 = arguments[1],
  13399. itemDistance = arguments[2];
  13400. this._boundable1 = boundable1;
  13401. this._boundable2 = boundable2;
  13402. this._itemDistance = itemDistance;
  13403. this._distance = this.distance();
  13404. }
  13405. static area(b) {
  13406. return b.getBounds().getArea();
  13407. }
  13408. static isComposite(item) {
  13409. return item instanceof AbstractNode;
  13410. }
  13411. maximumDistance() {
  13412. return EnvelopeDistance.maximumDistance(this._boundable1.getBounds(), this._boundable2.getBounds());
  13413. }
  13414. expandToQueue(priQ, minDistance) {
  13415. const isComp1 = BoundablePair.isComposite(this._boundable1);
  13416. const isComp2 = BoundablePair.isComposite(this._boundable2);
  13417. if (isComp1 && isComp2) {
  13418. if (BoundablePair.area(this._boundable1) > BoundablePair.area(this._boundable2)) {
  13419. this.expand(this._boundable1, this._boundable2, false, priQ, minDistance);
  13420. return null;
  13421. } else {
  13422. this.expand(this._boundable2, this._boundable1, true, priQ, minDistance);
  13423. return null;
  13424. }
  13425. } else if (isComp1) {
  13426. this.expand(this._boundable1, this._boundable2, false, priQ, minDistance);
  13427. return null;
  13428. } else if (isComp2) {
  13429. this.expand(this._boundable2, this._boundable1, true, priQ, minDistance);
  13430. return null;
  13431. }
  13432. throw new IllegalArgumentException('neither boundable is composite');
  13433. }
  13434. isLeaves() {
  13435. return !(BoundablePair.isComposite(this._boundable1) || BoundablePair.isComposite(this._boundable2));
  13436. }
  13437. compareTo(o) {
  13438. const nd = o;
  13439. if (this._distance < nd._distance) return -1;
  13440. if (this._distance > nd._distance) return 1;
  13441. return 0;
  13442. }
  13443. expand(bndComposite, bndOther, isFlipped, priQ, minDistance) {
  13444. const children = bndComposite.getChildBoundables();
  13445. for (let i = children.iterator(); i.hasNext();) {
  13446. const child = i.next();
  13447. let bp = null;
  13448. if (isFlipped) bp = new BoundablePair(bndOther, child, this._itemDistance);else bp = new BoundablePair(child, bndOther, this._itemDistance);
  13449. if (bp.getDistance() < minDistance) priQ.add(bp);
  13450. }
  13451. }
  13452. getBoundable(i) {
  13453. if (i === 0) return this._boundable1;
  13454. return this._boundable2;
  13455. }
  13456. getDistance() {
  13457. return this._distance;
  13458. }
  13459. distance() {
  13460. if (this.isLeaves()) return this._itemDistance.distance(this._boundable1, this._boundable2);
  13461. return this._boundable1.getBounds().distance(this._boundable2.getBounds());
  13462. }
  13463. get interfaces_() {
  13464. return [Comparable];
  13465. }
  13466. }
  13467. class AbstractSTRtree {
  13468. constructor() {
  13469. AbstractSTRtree.constructor_.apply(this, arguments);
  13470. }
  13471. static constructor_() {
  13472. this._root = null;
  13473. this._built = false;
  13474. this._itemBoundables = new ArrayList();
  13475. this._nodeCapacity = null;
  13476. if (arguments.length === 0) {
  13477. AbstractSTRtree.constructor_.call(this, AbstractSTRtree.DEFAULT_NODE_CAPACITY);
  13478. } else if (arguments.length === 1) {
  13479. const nodeCapacity = arguments[0];
  13480. Assert.isTrue(nodeCapacity > 1, 'Node capacity must be greater than 1');
  13481. this._nodeCapacity = nodeCapacity;
  13482. }
  13483. }
  13484. static compareDoubles(a, b) {
  13485. return a > b ? 1 : a < b ? -1 : 0;
  13486. }
  13487. queryInternal() {
  13488. if (hasInterface(arguments[2], ItemVisitor) && arguments[0] instanceof Object && arguments[1] instanceof AbstractNode) {
  13489. const searchBounds = arguments[0],
  13490. node = arguments[1],
  13491. visitor = arguments[2];
  13492. const childBoundables = node.getChildBoundables();
  13493. for (let i = 0; i < childBoundables.size(); i++) {
  13494. const childBoundable = childBoundables.get(i);
  13495. if (!this.getIntersectsOp().intersects(childBoundable.getBounds(), searchBounds)) continue;
  13496. if (childBoundable instanceof AbstractNode) this.queryInternal(searchBounds, childBoundable, visitor);else if (childBoundable instanceof ItemBoundable) visitor.visitItem(childBoundable.getItem());else Assert.shouldNeverReachHere();
  13497. }
  13498. } else if (hasInterface(arguments[2], List) && arguments[0] instanceof Object && arguments[1] instanceof AbstractNode) {
  13499. const searchBounds = arguments[0],
  13500. node = arguments[1],
  13501. matches = arguments[2];
  13502. const childBoundables = node.getChildBoundables();
  13503. for (let i = 0; i < childBoundables.size(); i++) {
  13504. const childBoundable = childBoundables.get(i);
  13505. if (!this.getIntersectsOp().intersects(childBoundable.getBounds(), searchBounds)) continue;
  13506. if (childBoundable instanceof AbstractNode) this.queryInternal(searchBounds, childBoundable, matches);else if (childBoundable instanceof ItemBoundable) matches.add(childBoundable.getItem());else Assert.shouldNeverReachHere();
  13507. }
  13508. }
  13509. }
  13510. getNodeCapacity() {
  13511. return this._nodeCapacity;
  13512. }
  13513. lastNode(nodes) {
  13514. return nodes.get(nodes.size() - 1);
  13515. }
  13516. size() {
  13517. if (arguments.length === 0) {
  13518. if (this.isEmpty()) return 0;
  13519. this.build();
  13520. return this.size(this._root);
  13521. } else if (arguments.length === 1) {
  13522. const node = arguments[0];
  13523. let size = 0;
  13524. for (let i = node.getChildBoundables().iterator(); i.hasNext();) {
  13525. const childBoundable = i.next();
  13526. if (childBoundable instanceof AbstractNode) size += this.size(childBoundable);else if (childBoundable instanceof ItemBoundable) size += 1;
  13527. }
  13528. return size;
  13529. }
  13530. }
  13531. removeItem(node, item) {
  13532. let childToRemove = null;
  13533. for (let i = node.getChildBoundables().iterator(); i.hasNext();) {
  13534. const childBoundable = i.next();
  13535. if (childBoundable instanceof ItemBoundable) if (childBoundable.getItem() === item) childToRemove = childBoundable;
  13536. }
  13537. if (childToRemove !== null) {
  13538. node.getChildBoundables().remove(childToRemove);
  13539. return true;
  13540. }
  13541. return false;
  13542. }
  13543. itemsTree() {
  13544. if (arguments.length === 0) {
  13545. this.build();
  13546. const valuesTree = this.itemsTree(this._root);
  13547. if (valuesTree === null) return new ArrayList();
  13548. return valuesTree;
  13549. } else if (arguments.length === 1) {
  13550. const node = arguments[0];
  13551. const valuesTreeForNode = new ArrayList();
  13552. for (let i = node.getChildBoundables().iterator(); i.hasNext();) {
  13553. const childBoundable = i.next();
  13554. if (childBoundable instanceof AbstractNode) {
  13555. const valuesTreeForChild = this.itemsTree(childBoundable);
  13556. if (valuesTreeForChild !== null) valuesTreeForNode.add(valuesTreeForChild);
  13557. } else if (childBoundable instanceof ItemBoundable) {
  13558. valuesTreeForNode.add(childBoundable.getItem());
  13559. } else {
  13560. Assert.shouldNeverReachHere();
  13561. }
  13562. }
  13563. if (valuesTreeForNode.size() <= 0) return null;
  13564. return valuesTreeForNode;
  13565. }
  13566. }
  13567. insert(bounds, item) {
  13568. Assert.isTrue(!this._built, 'Cannot insert items into an STR packed R-tree after it has been built.');
  13569. this._itemBoundables.add(new ItemBoundable(bounds, item));
  13570. }
  13571. boundablesAtLevel() {
  13572. if (arguments.length === 1) {
  13573. const level = arguments[0];
  13574. const boundables = new ArrayList();
  13575. this.boundablesAtLevel(level, this._root, boundables);
  13576. return boundables;
  13577. } else if (arguments.length === 3) {
  13578. const level = arguments[0],
  13579. top = arguments[1],
  13580. boundables = arguments[2];
  13581. Assert.isTrue(level > -2);
  13582. if (top.getLevel() === level) {
  13583. boundables.add(top);
  13584. return null;
  13585. }
  13586. for (let i = top.getChildBoundables().iterator(); i.hasNext();) {
  13587. const boundable = i.next();
  13588. if (boundable instanceof AbstractNode) {
  13589. this.boundablesAtLevel(level, boundable, boundables);
  13590. } else {
  13591. Assert.isTrue(boundable instanceof ItemBoundable);
  13592. if (level === -1) boundables.add(boundable);
  13593. }
  13594. }
  13595. return null;
  13596. }
  13597. }
  13598. query() {
  13599. if (arguments.length === 1) {
  13600. const searchBounds = arguments[0];
  13601. this.build();
  13602. const matches = new ArrayList();
  13603. if (this.isEmpty()) return matches;
  13604. if (this.getIntersectsOp().intersects(this._root.getBounds(), searchBounds)) this.queryInternal(searchBounds, this._root, matches);
  13605. return matches;
  13606. } else if (arguments.length === 2) {
  13607. const searchBounds = arguments[0],
  13608. visitor = arguments[1];
  13609. this.build();
  13610. if (this.isEmpty()) return null;
  13611. if (this.getIntersectsOp().intersects(this._root.getBounds(), searchBounds)) this.queryInternal(searchBounds, this._root, visitor);
  13612. }
  13613. }
  13614. build() {
  13615. if (this._built) return null;
  13616. this._root = this._itemBoundables.isEmpty() ? this.createNode(0) : this.createHigherLevels(this._itemBoundables, -1);
  13617. this._itemBoundables = null;
  13618. this._built = true;
  13619. }
  13620. getRoot() {
  13621. this.build();
  13622. return this._root;
  13623. }
  13624. remove() {
  13625. if (arguments.length === 2) {
  13626. const searchBounds = arguments[0],
  13627. item = arguments[1];
  13628. this.build();
  13629. if (this.getIntersectsOp().intersects(this._root.getBounds(), searchBounds)) return this.remove(searchBounds, this._root, item);
  13630. return false;
  13631. } else if (arguments.length === 3) {
  13632. const searchBounds = arguments[0],
  13633. node = arguments[1],
  13634. item = arguments[2];
  13635. let found = this.removeItem(node, item);
  13636. if (found) return true;
  13637. let childToPrune = null;
  13638. for (let i = node.getChildBoundables().iterator(); i.hasNext();) {
  13639. const childBoundable = i.next();
  13640. if (!this.getIntersectsOp().intersects(childBoundable.getBounds(), searchBounds)) continue;
  13641. if (childBoundable instanceof AbstractNode) {
  13642. found = this.remove(searchBounds, childBoundable, item);
  13643. if (found) {
  13644. childToPrune = childBoundable;
  13645. break;
  13646. }
  13647. }
  13648. }
  13649. if (childToPrune !== null) if (childToPrune.getChildBoundables().isEmpty()) node.getChildBoundables().remove(childToPrune);
  13650. return found;
  13651. }
  13652. }
  13653. createHigherLevels(boundablesOfALevel, level) {
  13654. Assert.isTrue(!boundablesOfALevel.isEmpty());
  13655. const parentBoundables = this.createParentBoundables(boundablesOfALevel, level + 1);
  13656. if (parentBoundables.size() === 1) return parentBoundables.get(0);
  13657. return this.createHigherLevels(parentBoundables, level + 1);
  13658. }
  13659. depth() {
  13660. if (arguments.length === 0) {
  13661. if (this.isEmpty()) return 0;
  13662. this.build();
  13663. return this.depth(this._root);
  13664. } else if (arguments.length === 1) {
  13665. const node = arguments[0];
  13666. let maxChildDepth = 0;
  13667. for (let i = node.getChildBoundables().iterator(); i.hasNext();) {
  13668. const childBoundable = i.next();
  13669. if (childBoundable instanceof AbstractNode) {
  13670. const childDepth = this.depth(childBoundable);
  13671. if (childDepth > maxChildDepth) maxChildDepth = childDepth;
  13672. }
  13673. }
  13674. return maxChildDepth + 1;
  13675. }
  13676. }
  13677. createParentBoundables(childBoundables, newLevel) {
  13678. Assert.isTrue(!childBoundables.isEmpty());
  13679. const parentBoundables = new ArrayList();
  13680. parentBoundables.add(this.createNode(newLevel));
  13681. const sortedChildBoundables = new ArrayList(childBoundables);
  13682. Collections.sort(sortedChildBoundables, this.getComparator());
  13683. for (let i = sortedChildBoundables.iterator(); i.hasNext();) {
  13684. const childBoundable = i.next();
  13685. if (this.lastNode(parentBoundables).getChildBoundables().size() === this.getNodeCapacity()) parentBoundables.add(this.createNode(newLevel));
  13686. this.lastNode(parentBoundables).addChildBoundable(childBoundable);
  13687. }
  13688. return parentBoundables;
  13689. }
  13690. isEmpty() {
  13691. if (!this._built) return this._itemBoundables.isEmpty();
  13692. return this._root.isEmpty();
  13693. }
  13694. get interfaces_() {
  13695. return [Serializable];
  13696. }
  13697. }
  13698. function IntersectsOp$1() {}
  13699. AbstractSTRtree.IntersectsOp = IntersectsOp$1;
  13700. AbstractSTRtree.DEFAULT_NODE_CAPACITY = 10;
  13701. class ItemDistance {
  13702. distance(item1, item2) {}
  13703. }
  13704. class STRtree extends AbstractSTRtree {
  13705. constructor() {
  13706. super();
  13707. STRtree.constructor_.apply(this, arguments);
  13708. }
  13709. static constructor_() {
  13710. if (arguments.length === 0) {
  13711. STRtree.constructor_.call(this, STRtree.DEFAULT_NODE_CAPACITY);
  13712. } else if (arguments.length === 1) {
  13713. const nodeCapacity = arguments[0];
  13714. AbstractSTRtree.constructor_.call(this, nodeCapacity);
  13715. }
  13716. }
  13717. static centreX(e) {
  13718. return STRtree.avg(e.getMinX(), e.getMaxX());
  13719. }
  13720. static avg(a, b) {
  13721. return (a + b) / 2;
  13722. }
  13723. static getItems(kNearestNeighbors) {
  13724. const items = new Array(kNearestNeighbors.size()).fill(null);
  13725. let count = 0;
  13726. while (!kNearestNeighbors.isEmpty()) {
  13727. const bp = kNearestNeighbors.poll();
  13728. items[count] = bp.getBoundable(0).getItem();
  13729. count++;
  13730. }
  13731. return items;
  13732. }
  13733. static centreY(e) {
  13734. return STRtree.avg(e.getMinY(), e.getMaxY());
  13735. }
  13736. createParentBoundablesFromVerticalSlices(verticalSlices, newLevel) {
  13737. Assert.isTrue(verticalSlices.length > 0);
  13738. const parentBoundables = new ArrayList();
  13739. for (let i = 0; i < verticalSlices.length; i++) parentBoundables.addAll(this.createParentBoundablesFromVerticalSlice(verticalSlices[i], newLevel));
  13740. return parentBoundables;
  13741. }
  13742. nearestNeighbourK() {
  13743. if (arguments.length === 2) {
  13744. const initBndPair = arguments[0],
  13745. k = arguments[1];
  13746. return this.nearestNeighbourK(initBndPair, Double.POSITIVE_INFINITY, k);
  13747. } else if (arguments.length === 3) {
  13748. const initBndPair = arguments[0],
  13749. maxDistance = arguments[1],
  13750. k = arguments[2];
  13751. let distanceLowerBound = maxDistance;
  13752. const priQ = new PriorityQueue();
  13753. priQ.add(initBndPair);
  13754. const kNearestNeighbors = new PriorityQueue();
  13755. while (!priQ.isEmpty() && distanceLowerBound >= 0.0) {
  13756. const bndPair = priQ.poll();
  13757. const pairDistance = bndPair.getDistance();
  13758. if (pairDistance >= distanceLowerBound) break;
  13759. if (bndPair.isLeaves()) {
  13760. if (kNearestNeighbors.size() < k) {
  13761. kNearestNeighbors.add(bndPair);
  13762. } else {
  13763. const bp1 = kNearestNeighbors.peek();
  13764. if (bp1.getDistance() > pairDistance) {
  13765. kNearestNeighbors.poll();
  13766. kNearestNeighbors.add(bndPair);
  13767. }
  13768. const bp2 = kNearestNeighbors.peek();
  13769. distanceLowerBound = bp2.getDistance();
  13770. }
  13771. } else bndPair.expandToQueue(priQ, distanceLowerBound);
  13772. }
  13773. return STRtree.getItems(kNearestNeighbors);
  13774. }
  13775. }
  13776. createNode(level) {
  13777. return new STRtreeNode(level);
  13778. }
  13779. size() {
  13780. if (arguments.length === 0) return super.size.call(this);else return super.size.apply(this, arguments);
  13781. }
  13782. insert() {
  13783. if (arguments.length === 2 && arguments[1] instanceof Object && arguments[0] instanceof Envelope) {
  13784. const itemEnv = arguments[0],
  13785. item = arguments[1];
  13786. if (itemEnv.isNull()) return null;
  13787. super.insert.call(this, itemEnv, item);
  13788. } else {
  13789. return super.insert.apply(this, arguments);
  13790. }
  13791. }
  13792. getIntersectsOp() {
  13793. return STRtree.intersectsOp;
  13794. }
  13795. verticalSlices(childBoundables, sliceCount) {
  13796. const sliceCapacity = Math.trunc(Math.ceil(childBoundables.size() / sliceCount));
  13797. const slices = new Array(sliceCount).fill(null);
  13798. const i = childBoundables.iterator();
  13799. for (let j = 0; j < sliceCount; j++) {
  13800. slices[j] = new ArrayList();
  13801. let boundablesAddedToSlice = 0;
  13802. while (i.hasNext() && boundablesAddedToSlice < sliceCapacity) {
  13803. const childBoundable = i.next();
  13804. slices[j].add(childBoundable);
  13805. boundablesAddedToSlice++;
  13806. }
  13807. }
  13808. return slices;
  13809. }
  13810. query() {
  13811. if (arguments.length === 1) {
  13812. const searchEnv = arguments[0];
  13813. return super.query.call(this, searchEnv);
  13814. } else if (arguments.length === 2) {
  13815. const searchEnv = arguments[0],
  13816. visitor = arguments[1];
  13817. super.query.call(this, searchEnv, visitor);
  13818. }
  13819. }
  13820. getComparator() {
  13821. return STRtree.yComparator;
  13822. }
  13823. createParentBoundablesFromVerticalSlice(childBoundables, newLevel) {
  13824. return super.createParentBoundables.call(this, childBoundables, newLevel);
  13825. }
  13826. remove() {
  13827. if (arguments.length === 2 && arguments[1] instanceof Object && arguments[0] instanceof Envelope) {
  13828. const itemEnv = arguments[0],
  13829. item = arguments[1];
  13830. return super.remove.call(this, itemEnv, item);
  13831. } else {
  13832. return super.remove.apply(this, arguments);
  13833. }
  13834. }
  13835. depth() {
  13836. if (arguments.length === 0) return super.depth.call(this);else return super.depth.apply(this, arguments);
  13837. }
  13838. createParentBoundables(childBoundables, newLevel) {
  13839. Assert.isTrue(!childBoundables.isEmpty());
  13840. const minLeafCount = Math.trunc(Math.ceil(childBoundables.size() / this.getNodeCapacity()));
  13841. const sortedChildBoundables = new ArrayList(childBoundables);
  13842. Collections.sort(sortedChildBoundables, STRtree.xComparator);
  13843. const verticalSlices = this.verticalSlices(sortedChildBoundables, Math.trunc(Math.ceil(Math.sqrt(minLeafCount))));
  13844. return this.createParentBoundablesFromVerticalSlices(verticalSlices, newLevel);
  13845. }
  13846. nearestNeighbour() {
  13847. if (arguments.length === 1) {
  13848. if (hasInterface(arguments[0], ItemDistance)) {
  13849. const itemDist = arguments[0];
  13850. if (this.isEmpty()) return null;
  13851. const bp = new BoundablePair(this.getRoot(), this.getRoot(), itemDist);
  13852. return this.nearestNeighbour(bp);
  13853. } else if (arguments[0] instanceof BoundablePair) {
  13854. const initBndPair = arguments[0];
  13855. let distanceLowerBound = Double.POSITIVE_INFINITY;
  13856. let minPair = null;
  13857. const priQ = new PriorityQueue();
  13858. priQ.add(initBndPair);
  13859. while (!priQ.isEmpty() && distanceLowerBound > 0.0) {
  13860. const bndPair = priQ.poll();
  13861. const pairDistance = bndPair.getDistance();
  13862. if (pairDistance >= distanceLowerBound) break;
  13863. if (bndPair.isLeaves()) {
  13864. distanceLowerBound = pairDistance;
  13865. minPair = bndPair;
  13866. } else {
  13867. bndPair.expandToQueue(priQ, distanceLowerBound);
  13868. }
  13869. }
  13870. if (minPair === null) return null;
  13871. return [minPair.getBoundable(0).getItem(), minPair.getBoundable(1).getItem()];
  13872. }
  13873. } else if (arguments.length === 2) {
  13874. const tree = arguments[0],
  13875. itemDist = arguments[1];
  13876. if (this.isEmpty() || tree.isEmpty()) return null;
  13877. const bp = new BoundablePair(this.getRoot(), tree.getRoot(), itemDist);
  13878. return this.nearestNeighbour(bp);
  13879. } else if (arguments.length === 3) {
  13880. const env = arguments[0],
  13881. item = arguments[1],
  13882. itemDist = arguments[2];
  13883. const bnd = new ItemBoundable(env, item);
  13884. const bp = new BoundablePair(this.getRoot(), bnd, itemDist);
  13885. return this.nearestNeighbour(bp)[0];
  13886. } else if (arguments.length === 4) {
  13887. const env = arguments[0],
  13888. item = arguments[1],
  13889. itemDist = arguments[2],
  13890. k = arguments[3];
  13891. const bnd = new ItemBoundable(env, item);
  13892. const bp = new BoundablePair(this.getRoot(), bnd, itemDist);
  13893. return this.nearestNeighbourK(bp, k);
  13894. }
  13895. }
  13896. isWithinDistance() {
  13897. if (arguments.length === 2) {
  13898. const initBndPair = arguments[0],
  13899. maxDistance = arguments[1];
  13900. let distanceUpperBound = Double.POSITIVE_INFINITY;
  13901. const priQ = new PriorityQueue();
  13902. priQ.add(initBndPair);
  13903. while (!priQ.isEmpty()) {
  13904. const bndPair = priQ.poll();
  13905. const pairDistance = bndPair.getDistance();
  13906. if (pairDistance > maxDistance) return false;
  13907. if (bndPair.maximumDistance() <= maxDistance) return true;
  13908. if (bndPair.isLeaves()) {
  13909. distanceUpperBound = pairDistance;
  13910. if (distanceUpperBound <= maxDistance) return true;
  13911. } else {
  13912. bndPair.expandToQueue(priQ, distanceUpperBound);
  13913. }
  13914. }
  13915. return false;
  13916. } else if (arguments.length === 3) {
  13917. const tree = arguments[0],
  13918. itemDist = arguments[1],
  13919. maxDistance = arguments[2];
  13920. const bp = new BoundablePair(this.getRoot(), tree.getRoot(), itemDist);
  13921. return this.isWithinDistance(bp, maxDistance);
  13922. }
  13923. }
  13924. get interfaces_() {
  13925. return [SpatialIndex, Serializable];
  13926. }
  13927. }
  13928. class STRtreeNode extends AbstractNode {
  13929. constructor() {
  13930. super();
  13931. STRtreeNode.constructor_.apply(this, arguments);
  13932. }
  13933. static constructor_() {
  13934. const level = arguments[0];
  13935. AbstractNode.constructor_.call(this, level);
  13936. }
  13937. computeBounds() {
  13938. let bounds = null;
  13939. for (let i = this.getChildBoundables().iterator(); i.hasNext();) {
  13940. const childBoundable = i.next();
  13941. if (bounds === null) bounds = new Envelope(childBoundable.getBounds());else bounds.expandToInclude(childBoundable.getBounds());
  13942. }
  13943. return bounds;
  13944. }
  13945. }
  13946. STRtree.STRtreeNode = STRtreeNode;
  13947. STRtree.xComparator = new class {
  13948. get interfaces_() {
  13949. return [Comparator];
  13950. }
  13951. compare(o1, o2) {
  13952. return AbstractSTRtree.compareDoubles(STRtree.centreX(o1.getBounds()), STRtree.centreX(o2.getBounds()));
  13953. }
  13954. }();
  13955. STRtree.yComparator = new class {
  13956. get interfaces_() {
  13957. return [Comparator];
  13958. }
  13959. compare(o1, o2) {
  13960. return AbstractSTRtree.compareDoubles(STRtree.centreY(o1.getBounds()), STRtree.centreY(o2.getBounds()));
  13961. }
  13962. }();
  13963. STRtree.intersectsOp = new class {
  13964. get interfaces_() {
  13965. return [IntersectsOp];
  13966. }
  13967. intersects(aBounds, bBounds) {
  13968. return aBounds.intersects(bBounds);
  13969. }
  13970. }();
  13971. STRtree.DEFAULT_NODE_CAPACITY = 10;
  13972. var strtree = /*#__PURE__*/Object.freeze({
  13973. __proto__: null,
  13974. STRtree: STRtree
  13975. });
  13976. var index = /*#__PURE__*/Object.freeze({
  13977. __proto__: null,
  13978. kdtree: kdtree,
  13979. quadtree: quadtree,
  13980. strtree: strtree
  13981. });
  13982. const geometryTypes = ['Point', 'MultiPoint', 'LineString', 'MultiLineString', 'Polygon', 'MultiPolygon'];
  13983. /**
  13984. * Class for reading and writing Well-Known Text.Create a new parser for GeoJSON
  13985. * NOTE: Adapted from OpenLayers 2.11 implementation.
  13986. */
  13987. /**
  13988. * Create a new parser for GeoJSON
  13989. *
  13990. * @param {GeometryFactory} geometryFactory
  13991. * @return An instance of GeoJsonParser.
  13992. * @constructor
  13993. * @private
  13994. */
  13995. class GeoJSONParser {
  13996. constructor(geometryFactory) {
  13997. this.geometryFactory = geometryFactory || new GeometryFactory();
  13998. }
  13999. /**
  14000. * Deserialize a GeoJSON object and return the Geometry or Feature(Collection) with JSTS Geometries
  14001. *
  14002. * @param {}
  14003. * A GeoJSON object.
  14004. * @return {} A Geometry instance or object representing a Feature(Collection) with Geometry instances.
  14005. * @private
  14006. */
  14007. read(json) {
  14008. let obj;
  14009. if (typeof json === 'string') obj = JSON.parse(json);else obj = json;
  14010. const type = obj.type;
  14011. if (!parse[type]) throw new Error('Unknown GeoJSON type: ' + obj.type);
  14012. if (geometryTypes.indexOf(type) !== -1) return parse[type].call(this, obj.coordinates);else if (type === 'GeometryCollection') return parse[type].call(this, obj.geometries); // feature or feature collection
  14013. return parse[type].call(this, obj);
  14014. }
  14015. /**
  14016. * Serialize a Geometry object into GeoJSON
  14017. *
  14018. * @param {Geometry}
  14019. * geometry A Geometry or array of Geometries.
  14020. * @return {Object} A GeoJSON object represting the input Geometry/Geometries.
  14021. * @private
  14022. */
  14023. write(geometry) {
  14024. const type = geometry.getGeometryType();
  14025. if (!extract[type]) throw new Error('Geometry is not supported');
  14026. return extract[type].call(this, geometry);
  14027. }
  14028. }
  14029. const parse = {
  14030. /**
  14031. * Parse a GeoJSON Feature object
  14032. *
  14033. * @param {Object}
  14034. * obj Object to parse.
  14035. *
  14036. * @return {Object} Feature with geometry/bbox converted to JSTS Geometries.
  14037. */
  14038. Feature: function (obj) {
  14039. const feature = {};
  14040. for (const key in obj) feature[key] = obj[key];
  14041. if (obj.geometry) {
  14042. const type = obj.geometry.type;
  14043. if (!parse[type]) throw new Error('Unknown GeoJSON type: ' + obj.type);
  14044. feature.geometry = this.read(obj.geometry);
  14045. }
  14046. if (obj.bbox) feature.bbox = parse.bbox.call(this, obj.bbox);
  14047. return feature;
  14048. },
  14049. /**
  14050. * Parse a GeoJSON FeatureCollection object
  14051. *
  14052. * @param {Object}
  14053. * obj Object to parse.
  14054. *
  14055. * @return {Object} FeatureCollection with geometry/bbox converted to JSTS Geometries.
  14056. */
  14057. FeatureCollection: function (obj) {
  14058. const featureCollection = {};
  14059. if (obj.features) {
  14060. featureCollection.features = [];
  14061. for (let i = 0; i < obj.features.length; ++i) featureCollection.features.push(this.read(obj.features[i]));
  14062. }
  14063. if (obj.bbox) featureCollection.bbox = this.parse.bbox.call(this, obj.bbox);
  14064. return featureCollection;
  14065. },
  14066. /**
  14067. * Convert the ordinates in an array to an array of Coordinates
  14068. *
  14069. * @param {Array}
  14070. * array Array with {Number}s.
  14071. *
  14072. * @return {Array} Array with Coordinates.
  14073. */
  14074. coordinates: function (array) {
  14075. const coordinates = [];
  14076. for (let i = 0; i < array.length; ++i) {
  14077. const sub = array[i];
  14078. coordinates.push(new Coordinate(...sub));
  14079. }
  14080. return coordinates;
  14081. },
  14082. /**
  14083. * Convert the bbox to a LinearRing
  14084. *
  14085. * @param {Array}
  14086. * array Array with [xMin, yMin, xMax, yMax].
  14087. *
  14088. * @return {Array} Array with Coordinates.
  14089. */
  14090. bbox: function (array) {
  14091. return this.geometryFactory.createLinearRing([new Coordinate(array[0], array[1]), new Coordinate(array[2], array[1]), new Coordinate(array[2], array[3]), new Coordinate(array[0], array[3]), new Coordinate(array[0], array[1])]);
  14092. },
  14093. /**
  14094. * Convert an Array with ordinates to a Point
  14095. *
  14096. * @param {Array}
  14097. * array Array with ordinates.
  14098. *
  14099. * @return {Point} Point.
  14100. */
  14101. Point: function (array) {
  14102. const coordinate = new Coordinate(...array);
  14103. return this.geometryFactory.createPoint(coordinate);
  14104. },
  14105. /**
  14106. * Convert an Array with coordinates to a MultiPoint
  14107. *
  14108. * @param {Array}
  14109. * array Array with coordinates.
  14110. *
  14111. * @return {MultiPoint} MultiPoint.
  14112. */
  14113. MultiPoint: function (array) {
  14114. const points = [];
  14115. for (let i = 0; i < array.length; ++i) points.push(parse.Point.call(this, array[i]));
  14116. return this.geometryFactory.createMultiPoint(points);
  14117. },
  14118. /**
  14119. * Convert an Array with coordinates to a LineString
  14120. *
  14121. * @param {Array}
  14122. * array Array with coordinates.
  14123. *
  14124. * @return {LineString} LineString.
  14125. */
  14126. LineString: function (array) {
  14127. const coordinates = parse.coordinates.call(this, array);
  14128. return this.geometryFactory.createLineString(coordinates);
  14129. },
  14130. /**
  14131. * Convert an Array with coordinates to a MultiLineString
  14132. *
  14133. * @param {Array}
  14134. * array Array with coordinates.
  14135. *
  14136. * @return {MultiLineString} MultiLineString.
  14137. */
  14138. MultiLineString: function (array) {
  14139. const lineStrings = [];
  14140. for (let i = 0; i < array.length; ++i) lineStrings.push(parse.LineString.call(this, array[i]));
  14141. return this.geometryFactory.createMultiLineString(lineStrings);
  14142. },
  14143. /**
  14144. * Convert an Array to a Polygon
  14145. *
  14146. * @param {Array}
  14147. * array Array with shell and holes.
  14148. *
  14149. * @return {Polygon} Polygon.
  14150. */
  14151. Polygon: function (array) {
  14152. const shellCoordinates = parse.coordinates.call(this, array[0]);
  14153. const shell = this.geometryFactory.createLinearRing(shellCoordinates);
  14154. const holes = [];
  14155. for (let i = 1; i < array.length; ++i) {
  14156. const hole = array[i];
  14157. const coordinates = parse.coordinates.call(this, hole);
  14158. const linearRing = this.geometryFactory.createLinearRing(coordinates);
  14159. holes.push(linearRing);
  14160. }
  14161. return this.geometryFactory.createPolygon(shell, holes);
  14162. },
  14163. /**
  14164. * Convert an Array to a MultiPolygon
  14165. *
  14166. * @param {Array}
  14167. * array Array of arrays with shell and rings.
  14168. *
  14169. * @return {MultiPolygon} MultiPolygon.
  14170. */
  14171. MultiPolygon: function (array) {
  14172. const polygons = [];
  14173. for (let i = 0; i < array.length; ++i) {
  14174. const polygon = array[i];
  14175. polygons.push(parse.Polygon.call(this, polygon));
  14176. }
  14177. return this.geometryFactory.createMultiPolygon(polygons);
  14178. },
  14179. /**
  14180. * Convert an Array to a GeometryCollection
  14181. *
  14182. * @param {Array}
  14183. * array Array of GeoJSON geometries.
  14184. *
  14185. * @return {GeometryCollection} GeometryCollection.
  14186. */
  14187. GeometryCollection: function (array) {
  14188. const geometries = [];
  14189. for (let i = 0; i < array.length; ++i) {
  14190. const geometry = array[i];
  14191. geometries.push(this.read(geometry));
  14192. }
  14193. return this.geometryFactory.createGeometryCollection(geometries);
  14194. }
  14195. };
  14196. const extract = {
  14197. /**
  14198. * Convert a Coordinate to an Array
  14199. *
  14200. * @param {Coordinate}
  14201. * coordinate Coordinate to convert.
  14202. *
  14203. * @return {Array} Array of ordinates.
  14204. */
  14205. coordinate: function (coordinate) {
  14206. const a = [coordinate.x, coordinate.y];
  14207. if (coordinate.z) a.push(coordinate.z);
  14208. if (coordinate.m) a.push(coordinate.m);
  14209. return a;
  14210. },
  14211. /**
  14212. * Convert a Point to a GeoJSON object
  14213. *
  14214. * @param {Point}
  14215. * point Point to convert.
  14216. *
  14217. * @return {Array} Array of 2 ordinates (paired to a coordinate).
  14218. */
  14219. Point: function (point) {
  14220. const array = extract.coordinate.call(this, point.getCoordinate());
  14221. return {
  14222. type: 'Point',
  14223. coordinates: array
  14224. };
  14225. },
  14226. /**
  14227. * Convert a MultiPoint to a GeoJSON object
  14228. *
  14229. * @param {MultiPoint}
  14230. * multipoint MultiPoint to convert.
  14231. *
  14232. * @return {Array} Array of coordinates.
  14233. */
  14234. MultiPoint: function (multipoint) {
  14235. const array = [];
  14236. for (let i = 0; i < multipoint._geometries.length; ++i) {
  14237. const point = multipoint._geometries[i];
  14238. const geoJson = extract.Point.call(this, point);
  14239. array.push(geoJson.coordinates);
  14240. }
  14241. return {
  14242. type: 'MultiPoint',
  14243. coordinates: array
  14244. };
  14245. },
  14246. /**
  14247. * Convert a LineString to a GeoJSON object
  14248. *
  14249. * @param {LineString}
  14250. * linestring LineString to convert.
  14251. *
  14252. * @return {Array} Array of coordinates.
  14253. */
  14254. LineString: function (linestring) {
  14255. const array = [];
  14256. const coordinates = linestring.getCoordinates();
  14257. for (let i = 0; i < coordinates.length; ++i) {
  14258. const coordinate = coordinates[i];
  14259. array.push(extract.coordinate.call(this, coordinate));
  14260. }
  14261. return {
  14262. type: 'LineString',
  14263. coordinates: array
  14264. };
  14265. },
  14266. /**
  14267. * Convert a MultiLineString to a GeoJSON object
  14268. *
  14269. * @param {MultiLineString}
  14270. * multilinestring MultiLineString to convert.
  14271. *
  14272. * @return {Array} Array of Array of coordinates.
  14273. */
  14274. MultiLineString: function (multilinestring) {
  14275. const array = [];
  14276. for (let i = 0; i < multilinestring._geometries.length; ++i) {
  14277. const linestring = multilinestring._geometries[i];
  14278. const geoJson = extract.LineString.call(this, linestring);
  14279. array.push(geoJson.coordinates);
  14280. }
  14281. return {
  14282. type: 'MultiLineString',
  14283. coordinates: array
  14284. };
  14285. },
  14286. /**
  14287. * Convert a Polygon to a GeoJSON object
  14288. *
  14289. * @param {Polygon}
  14290. * polygon Polygon to convert.
  14291. *
  14292. * @return {Array} Array with shell, holes.
  14293. */
  14294. Polygon: function (polygon) {
  14295. const array = [];
  14296. const shellGeoJson = extract.LineString.call(this, polygon._shell);
  14297. array.push(shellGeoJson.coordinates);
  14298. for (let i = 0; i < polygon._holes.length; ++i) {
  14299. const hole = polygon._holes[i];
  14300. const holeGeoJson = extract.LineString.call(this, hole);
  14301. array.push(holeGeoJson.coordinates);
  14302. }
  14303. return {
  14304. type: 'Polygon',
  14305. coordinates: array
  14306. };
  14307. },
  14308. /**
  14309. * Convert a MultiPolygon to a GeoJSON object
  14310. *
  14311. * @param {MultiPolygon}
  14312. * multipolygon MultiPolygon to convert.
  14313. *
  14314. * @return {Array} Array of polygons.
  14315. */
  14316. MultiPolygon: function (multipolygon) {
  14317. const array = [];
  14318. for (let i = 0; i < multipolygon._geometries.length; ++i) {
  14319. const polygon = multipolygon._geometries[i];
  14320. const geoJson = extract.Polygon.call(this, polygon);
  14321. array.push(geoJson.coordinates);
  14322. }
  14323. return {
  14324. type: 'MultiPolygon',
  14325. coordinates: array
  14326. };
  14327. },
  14328. /**
  14329. * Convert a GeometryCollection to a GeoJSON object
  14330. *
  14331. * @param {GeometryCollection}
  14332. * collection GeometryCollection to convert.
  14333. *
  14334. * @return {Array} Array of geometries.
  14335. */
  14336. GeometryCollection: function (collection) {
  14337. const array = [];
  14338. for (let i = 0; i < collection._geometries.length; ++i) {
  14339. const geometry = collection._geometries[i];
  14340. const type = geometry.getGeometryType();
  14341. array.push(extract[type].call(this, geometry));
  14342. }
  14343. return {
  14344. type: 'GeometryCollection',
  14345. geometries: array
  14346. };
  14347. }
  14348. };
  14349. /**
  14350. * @module org/locationtech/jts/io/GeoJSONReader
  14351. */
  14352. /**
  14353. * Converts a geometry in GeoJSON to a {@link Geometry}.
  14354. */
  14355. class GeoJSONReader {
  14356. /**
  14357. * A <code>GeoJSONReader</code> is parameterized by a <code>GeometryFactory</code>,
  14358. * to allow it to create <code>Geometry</code> objects of the appropriate
  14359. * implementation. In particular, the <code>GeometryFactory</code> determines
  14360. * the <code>PrecisionModel</code> and <code>SRID</code> that is used.
  14361. *
  14362. * @param {GeometryFactory} geometryFactory
  14363. */
  14364. constructor(geometryFactory) {
  14365. this.parser = new GeoJSONParser(geometryFactory || new GeometryFactory());
  14366. }
  14367. /**
  14368. * Reads a GeoJSON representation of a {@link Geometry}
  14369. *
  14370. * Will also parse GeoJSON Features/FeatureCollections as custom objects.
  14371. *
  14372. * @param {Object|String} geoJson a GeoJSON Object or String.
  14373. * @return {Geometry|Object} a <code>Geometry or Feature/FeatureCollection representation.</code>
  14374. * @memberof module:org/locationtech/jts/io/GeoJSONReader#
  14375. */
  14376. read(geoJson) {
  14377. const geometry = this.parser.read(geoJson);
  14378. return geometry;
  14379. }
  14380. }
  14381. /**
  14382. * @module org/locationtech/jts/io/GeoJSONWriter
  14383. */
  14384. /**
  14385. * Writes the GeoJSON representation of a {@link Geometry}. The
  14386. * The GeoJSON format is defined <A
  14387. * HREF="http://geojson.org/geojson-spec.html">here</A>.
  14388. */
  14389. class GeoJSONWriter {
  14390. /**
  14391. * The <code>GeoJSONWriter</code> outputs coordinates rounded to the precision
  14392. * model. Only the maximum number of decimal places necessary to represent the
  14393. * ordinates to the required precision will be output.
  14394. *
  14395. * @param {GeometryFactory} geometryFactory
  14396. * @constructor
  14397. */
  14398. constructor() {
  14399. this.parser = new GeoJSONParser(this.geometryFactory);
  14400. }
  14401. /**
  14402. * Converts a <code>Geometry</code> to its GeoJSON representation.
  14403. *
  14404. * @param {Geometry}
  14405. * geometry a <code>Geometry</code> to process.
  14406. * @return {Object} The GeoJSON representation of the Geometry.
  14407. * @memberof module:org/locationtech/jts/io/GeoJSONWriter#
  14408. */
  14409. write(geometry) {
  14410. return this.parser.write(geometry);
  14411. }
  14412. }
  14413. /**
  14414. * @module org/locationtech/jts/io/WKTReader
  14415. */
  14416. /**
  14417. * Converts a geometry in Well-Known Text format to a {@link Geometry}.
  14418. * <p>
  14419. * <code>WKTReader</code> supports extracting <code>Geometry</code> objects
  14420. * from either {@link Reader}s or {@link String}s. This allows it to function
  14421. * as a parser to read <code>Geometry</code> objects from text blocks embedded
  14422. * in other data formats (e.g. XML).
  14423. */
  14424. class WKTReader {
  14425. /**
  14426. * A <code>WKTReader</code> is parameterized by a <code>GeometryFactory</code>,
  14427. * to allow it to create <code>Geometry</code> objects of the appropriate
  14428. * implementation. In particular, the <code>GeometryFactory</code> determines
  14429. * the <code>PrecisionModel</code> and <code>SRID</code> that is used.
  14430. * @param {GeometryFactory} geometryFactory
  14431. */
  14432. constructor(geometryFactory) {
  14433. this.parser = new WKTParser(geometryFactory || new GeometryFactory());
  14434. }
  14435. /**
  14436. * Reads a Well-Known Text representation of a {@link Geometry}
  14437. *
  14438. * @param {string}
  14439. * wkt a <Geometry Tagged Text> string (see the OpenGIS Simple Features
  14440. * Specification).
  14441. * @return {Geometry} a <code>Geometry</code> read from
  14442. * <code>string.</code>
  14443. * @memberof module:org/locationtech/jts/io/WKTReader#
  14444. */
  14445. read(wkt) {
  14446. return this.parser.read(wkt);
  14447. }
  14448. }
  14449. /* eslint-disable no-undef */
  14450. function p2c(p) {
  14451. return [p.x, p.y];
  14452. }
  14453. class OL3Parser {
  14454. /**
  14455. * OpenLayers Geometry parser and writer
  14456. * @param {GeometryFactory} geometryFactory
  14457. * @param {ol} olReference
  14458. */
  14459. constructor(geometryFactory, olReference) {
  14460. this.geometryFactory = geometryFactory || new GeometryFactory();
  14461. this.ol = olReference || typeof ol !== 'undefined' && ol;
  14462. }
  14463. /**
  14464. * Inject OpenLayers geom classes
  14465. */
  14466. inject(Point, LineString, LinearRing, Polygon, MultiPoint, MultiLineString, MultiPolygon, GeometryCollection) {
  14467. this.ol = {
  14468. geom: {
  14469. Point,
  14470. LineString,
  14471. LinearRing,
  14472. Polygon,
  14473. MultiPoint,
  14474. MultiLineString,
  14475. MultiPolygon,
  14476. GeometryCollection
  14477. }
  14478. };
  14479. }
  14480. /**
  14481. * @param geometry {ol.geom.Geometry}
  14482. * @return {Geometry}
  14483. * @memberof module:org/locationtech/jts/io/OL3Parser#
  14484. */
  14485. read(geometry) {
  14486. const ol = this.ol;
  14487. if (geometry instanceof ol.geom.Point) return this.convertFromPoint(geometry);else if (geometry instanceof ol.geom.LineString) return this.convertFromLineString(geometry);else if (geometry instanceof ol.geom.LinearRing) return this.convertFromLinearRing(geometry);else if (geometry instanceof ol.geom.Polygon) return this.convertFromPolygon(geometry);else if (geometry instanceof ol.geom.MultiPoint) return this.convertFromMultiPoint(geometry);else if (geometry instanceof ol.geom.MultiLineString) return this.convertFromMultiLineString(geometry);else if (geometry instanceof ol.geom.MultiPolygon) return this.convertFromMultiPolygon(geometry);else if (geometry instanceof ol.geom.GeometryCollection) return this.convertFromCollection(geometry);
  14488. }
  14489. convertFromPoint(point) {
  14490. const coordinates = point.getCoordinates();
  14491. return this.geometryFactory.createPoint(new Coordinate(coordinates[0], coordinates[1]));
  14492. }
  14493. convertFromLineString(lineString) {
  14494. return this.geometryFactory.createLineString(lineString.getCoordinates().map(function (coordinates) {
  14495. return new Coordinate(coordinates[0], coordinates[1]);
  14496. }));
  14497. }
  14498. convertFromLinearRing(linearRing) {
  14499. return this.geometryFactory.createLinearRing(linearRing.getCoordinates().map(function (coordinates) {
  14500. return new Coordinate(coordinates[0], coordinates[1]);
  14501. }));
  14502. }
  14503. convertFromPolygon(polygon) {
  14504. const linearRings = polygon.getLinearRings();
  14505. let shell = null;
  14506. const holes = [];
  14507. for (let i = 0; i < linearRings.length; i++) {
  14508. const linearRing = this.convertFromLinearRing(linearRings[i]);
  14509. if (i === 0) shell = linearRing;else holes.push(linearRing);
  14510. }
  14511. return this.geometryFactory.createPolygon(shell, holes);
  14512. }
  14513. convertFromMultiPoint(multiPoint) {
  14514. const points = multiPoint.getPoints().map(function (point) {
  14515. return this.convertFromPoint(point);
  14516. }, this);
  14517. return this.geometryFactory.createMultiPoint(points);
  14518. }
  14519. convertFromMultiLineString(multiLineString) {
  14520. const lineStrings = multiLineString.getLineStrings().map(function (lineString) {
  14521. return this.convertFromLineString(lineString);
  14522. }, this);
  14523. return this.geometryFactory.createMultiLineString(lineStrings);
  14524. }
  14525. convertFromMultiPolygon(multiPolygon) {
  14526. const polygons = multiPolygon.getPolygons().map(function (polygon) {
  14527. return this.convertFromPolygon(polygon);
  14528. }, this);
  14529. return this.geometryFactory.createMultiPolygon(polygons);
  14530. }
  14531. convertFromCollection(collection) {
  14532. const geometries = collection.getGeometries().map(function (geometry) {
  14533. return this.read(geometry);
  14534. }, this);
  14535. return this.geometryFactory.createGeometryCollection(geometries);
  14536. }
  14537. /**
  14538. * @param geometry
  14539. * {Geometry}
  14540. * @return {ol.geom.Geometry}
  14541. * @memberof module:org/locationtech/jts/io/OL3Parser#
  14542. */
  14543. write(geometry) {
  14544. if (geometry.getGeometryType() === 'Point') return this.convertToPoint(geometry.getCoordinate());else if (geometry.getGeometryType() === 'LineString') return this.convertToLineString(geometry);else if (geometry.getGeometryType() === 'LinearRing') return this.convertToLinearRing(geometry);else if (geometry.getGeometryType() === 'Polygon') return this.convertToPolygon(geometry);else if (geometry.getGeometryType() === 'MultiPoint') return this.convertToMultiPoint(geometry);else if (geometry.getGeometryType() === 'MultiLineString') return this.convertToMultiLineString(geometry);else if (geometry.getGeometryType() === 'MultiPolygon') return this.convertToMultiPolygon(geometry);else if (geometry.getGeometryType() === 'GeometryCollection') return this.convertToCollection(geometry);
  14545. }
  14546. convertToPoint(coordinate) {
  14547. return new this.ol.geom.Point([coordinate.x, coordinate.y]);
  14548. }
  14549. convertToLineString(lineString) {
  14550. const points = lineString._points._coordinates.map(p2c);
  14551. return new this.ol.geom.LineString(points);
  14552. }
  14553. convertToLinearRing(linearRing) {
  14554. const points = linearRing._points._coordinates.map(p2c);
  14555. return new this.ol.geom.LinearRing(points);
  14556. }
  14557. convertToPolygon(polygon) {
  14558. const rings = [polygon._shell._points._coordinates.map(p2c)];
  14559. for (let i = 0; i < polygon._holes.length; i++) rings.push(polygon._holes[i]._points._coordinates.map(p2c));
  14560. return new this.ol.geom.Polygon(rings);
  14561. }
  14562. convertToMultiPoint(multiPoint) {
  14563. return new this.ol.geom.MultiPoint(multiPoint.getCoordinates().map(p2c));
  14564. }
  14565. convertToMultiLineString(multiLineString) {
  14566. const lineStrings = [];
  14567. for (let i = 0; i < multiLineString._geometries.length; i++) lineStrings.push(this.convertToLineString(multiLineString._geometries[i]).getCoordinates());
  14568. return new this.ol.geom.MultiLineString(lineStrings);
  14569. }
  14570. convertToMultiPolygon(multiPolygon) {
  14571. const polygons = [];
  14572. for (let i = 0; i < multiPolygon._geometries.length; i++) polygons.push(this.convertToPolygon(multiPolygon._geometries[i]).getCoordinates());
  14573. return new this.ol.geom.MultiPolygon(polygons);
  14574. }
  14575. convertToCollection(geometryCollection) {
  14576. const geometries = [];
  14577. for (let i = 0; i < geometryCollection._geometries.length; i++) {
  14578. const geometry = geometryCollection._geometries[i];
  14579. geometries.push(this.write(geometry));
  14580. }
  14581. return new this.ol.geom.GeometryCollection(geometries);
  14582. }
  14583. }
  14584. var io = /*#__PURE__*/Object.freeze({
  14585. __proto__: null,
  14586. GeoJSONReader: GeoJSONReader,
  14587. GeoJSONWriter: GeoJSONWriter,
  14588. OL3Parser: OL3Parser,
  14589. WKTReader: WKTReader,
  14590. WKTWriter: WKTWriter
  14591. });
  14592. class SegmentPointComparator {
  14593. static relativeSign(x0, x1) {
  14594. if (x0 < x1) return -1;
  14595. if (x0 > x1) return 1;
  14596. return 0;
  14597. }
  14598. static compare(octant, p0, p1) {
  14599. if (p0.equals2D(p1)) return 0;
  14600. const xSign = SegmentPointComparator.relativeSign(p0.x, p1.x);
  14601. const ySign = SegmentPointComparator.relativeSign(p0.y, p1.y);
  14602. switch (octant) {
  14603. case 0:
  14604. return SegmentPointComparator.compareValue(xSign, ySign);
  14605. case 1:
  14606. return SegmentPointComparator.compareValue(ySign, xSign);
  14607. case 2:
  14608. return SegmentPointComparator.compareValue(ySign, -xSign);
  14609. case 3:
  14610. return SegmentPointComparator.compareValue(-xSign, ySign);
  14611. case 4:
  14612. return SegmentPointComparator.compareValue(-xSign, -ySign);
  14613. case 5:
  14614. return SegmentPointComparator.compareValue(-ySign, -xSign);
  14615. case 6:
  14616. return SegmentPointComparator.compareValue(-ySign, xSign);
  14617. case 7:
  14618. return SegmentPointComparator.compareValue(xSign, -ySign);
  14619. }
  14620. Assert.shouldNeverReachHere('invalid octant value');
  14621. return 0;
  14622. }
  14623. static compareValue(compareSign0, compareSign1) {
  14624. if (compareSign0 < 0) return -1;
  14625. if (compareSign0 > 0) return 1;
  14626. if (compareSign1 < 0) return -1;
  14627. if (compareSign1 > 0) return 1;
  14628. return 0;
  14629. }
  14630. }
  14631. class SegmentNode {
  14632. constructor() {
  14633. SegmentNode.constructor_.apply(this, arguments);
  14634. }
  14635. static constructor_() {
  14636. this._segString = null;
  14637. this.coord = null;
  14638. this.segmentIndex = null;
  14639. this._segmentOctant = null;
  14640. this._isInterior = null;
  14641. const segString = arguments[0],
  14642. coord = arguments[1],
  14643. segmentIndex = arguments[2],
  14644. segmentOctant = arguments[3];
  14645. this._segString = segString;
  14646. this.coord = new Coordinate(coord);
  14647. this.segmentIndex = segmentIndex;
  14648. this._segmentOctant = segmentOctant;
  14649. this._isInterior = !coord.equals2D(segString.getCoordinate(segmentIndex));
  14650. }
  14651. getCoordinate() {
  14652. return this.coord;
  14653. }
  14654. print(out) {
  14655. out.print(this.coord);
  14656. out.print(' seg # = ' + this.segmentIndex);
  14657. }
  14658. compareTo(obj) {
  14659. const other = obj;
  14660. if (this.segmentIndex < other.segmentIndex) return -1;
  14661. if (this.segmentIndex > other.segmentIndex) return 1;
  14662. if (this.coord.equals2D(other.coord)) return 0;
  14663. if (!this._isInterior) return -1;
  14664. if (!other._isInterior) return 1;
  14665. return SegmentPointComparator.compare(this._segmentOctant, this.coord, other.coord);
  14666. }
  14667. isEndPoint(maxSegmentIndex) {
  14668. if (this.segmentIndex === 0 && !this._isInterior) return true;
  14669. if (this.segmentIndex === maxSegmentIndex) return true;
  14670. return false;
  14671. }
  14672. toString() {
  14673. return this.segmentIndex + ':' + this.coord.toString();
  14674. }
  14675. isInterior() {
  14676. return this._isInterior;
  14677. }
  14678. get interfaces_() {
  14679. return [Comparable];
  14680. }
  14681. }
  14682. class SegmentNodeList {
  14683. constructor() {
  14684. SegmentNodeList.constructor_.apply(this, arguments);
  14685. }
  14686. static constructor_() {
  14687. this._nodeMap = new TreeMap();
  14688. this._edge = null;
  14689. const edge = arguments[0];
  14690. this._edge = edge;
  14691. }
  14692. getSplitCoordinates() {
  14693. const coordList = new CoordinateList();
  14694. this.addEndpoints();
  14695. const it = this.iterator();
  14696. let eiPrev = it.next();
  14697. while (it.hasNext()) {
  14698. const ei = it.next();
  14699. this.addEdgeCoordinates(eiPrev, ei, coordList);
  14700. eiPrev = ei;
  14701. }
  14702. return coordList.toCoordinateArray();
  14703. }
  14704. addCollapsedNodes() {
  14705. const collapsedVertexIndexes = new ArrayList();
  14706. this.findCollapsesFromInsertedNodes(collapsedVertexIndexes);
  14707. this.findCollapsesFromExistingVertices(collapsedVertexIndexes);
  14708. for (let it = collapsedVertexIndexes.iterator(); it.hasNext();) {
  14709. const vertexIndex = it.next().intValue();
  14710. this.add(this._edge.getCoordinate(vertexIndex), vertexIndex);
  14711. }
  14712. }
  14713. createSplitEdgePts(ei0, ei1) {
  14714. let npts = ei1.segmentIndex - ei0.segmentIndex + 2;
  14715. if (npts === 2) return [new Coordinate(ei0.coord), new Coordinate(ei1.coord)];
  14716. const lastSegStartPt = this._edge.getCoordinate(ei1.segmentIndex);
  14717. const useIntPt1 = ei1.isInterior() || !ei1.coord.equals2D(lastSegStartPt);
  14718. if (!useIntPt1) npts--;
  14719. const pts = new Array(npts).fill(null);
  14720. let ipt = 0;
  14721. pts[ipt++] = new Coordinate(ei0.coord);
  14722. for (let i = ei0.segmentIndex + 1; i <= ei1.segmentIndex; i++) pts[ipt++] = this._edge.getCoordinate(i);
  14723. if (useIntPt1) pts[ipt] = new Coordinate(ei1.coord);
  14724. return pts;
  14725. }
  14726. print(out) {
  14727. out.println('Intersections:');
  14728. for (let it = this.iterator(); it.hasNext();) {
  14729. const ei = it.next();
  14730. ei.print(out);
  14731. }
  14732. }
  14733. findCollapsesFromExistingVertices(collapsedVertexIndexes) {
  14734. for (let i = 0; i < this._edge.size() - 2; i++) {
  14735. const p0 = this._edge.getCoordinate(i);
  14736. this._edge.getCoordinate(i + 1);
  14737. const p2 = this._edge.getCoordinate(i + 2);
  14738. if (p0.equals2D(p2)) collapsedVertexIndexes.add(Integer.valueOf(i + 1));
  14739. }
  14740. }
  14741. addEdgeCoordinates(ei0, ei1, coordList) {
  14742. const pts = this.createSplitEdgePts(ei0, ei1);
  14743. coordList.add(pts, false);
  14744. }
  14745. iterator() {
  14746. return this._nodeMap.values().iterator();
  14747. }
  14748. addSplitEdges(edgeList) {
  14749. this.addEndpoints();
  14750. this.addCollapsedNodes();
  14751. const it = this.iterator();
  14752. let eiPrev = it.next();
  14753. while (it.hasNext()) {
  14754. const ei = it.next();
  14755. const newEdge = this.createSplitEdge(eiPrev, ei);
  14756. edgeList.add(newEdge);
  14757. eiPrev = ei;
  14758. }
  14759. }
  14760. findCollapseIndex(ei0, ei1, collapsedVertexIndex) {
  14761. if (!ei0.coord.equals2D(ei1.coord)) return false;
  14762. let numVerticesBetween = ei1.segmentIndex - ei0.segmentIndex;
  14763. if (!ei1.isInterior()) numVerticesBetween--;
  14764. if (numVerticesBetween === 1) {
  14765. collapsedVertexIndex[0] = ei0.segmentIndex + 1;
  14766. return true;
  14767. }
  14768. return false;
  14769. }
  14770. findCollapsesFromInsertedNodes(collapsedVertexIndexes) {
  14771. const collapsedVertexIndex = new Array(1).fill(null);
  14772. const it = this.iterator();
  14773. let eiPrev = it.next();
  14774. while (it.hasNext()) {
  14775. const ei = it.next();
  14776. const isCollapsed = this.findCollapseIndex(eiPrev, ei, collapsedVertexIndex);
  14777. if (isCollapsed) collapsedVertexIndexes.add(Integer.valueOf(collapsedVertexIndex[0]));
  14778. eiPrev = ei;
  14779. }
  14780. }
  14781. getEdge() {
  14782. return this._edge;
  14783. }
  14784. addEndpoints() {
  14785. const maxSegIndex = this._edge.size() - 1;
  14786. this.add(this._edge.getCoordinate(0), 0);
  14787. this.add(this._edge.getCoordinate(maxSegIndex), maxSegIndex);
  14788. }
  14789. createSplitEdge(ei0, ei1) {
  14790. const pts = this.createSplitEdgePts(ei0, ei1);
  14791. return new NodedSegmentString(pts, this._edge.getData());
  14792. }
  14793. add(intPt, segmentIndex) {
  14794. const eiNew = new SegmentNode(this._edge, intPt, segmentIndex, this._edge.getSegmentOctant(segmentIndex));
  14795. const ei = this._nodeMap.get(eiNew);
  14796. if (ei !== null) {
  14797. Assert.isTrue(ei.coord.equals2D(intPt), 'Found equal nodes with different coordinates');
  14798. return ei;
  14799. }
  14800. this._nodeMap.put(eiNew, eiNew);
  14801. return eiNew;
  14802. }
  14803. checkSplitEdgesCorrectness(splitEdges) {
  14804. const edgePts = this._edge.getCoordinates();
  14805. const split0 = splitEdges.get(0);
  14806. const pt0 = split0.getCoordinate(0);
  14807. if (!pt0.equals2D(edgePts[0])) throw new RuntimeException('bad split edge start point at ' + pt0);
  14808. const splitn = splitEdges.get(splitEdges.size() - 1);
  14809. const splitnPts = splitn.getCoordinates();
  14810. const ptn = splitnPts[splitnPts.length - 1];
  14811. if (!ptn.equals2D(edgePts[edgePts.length - 1])) throw new RuntimeException('bad split edge end point at ' + ptn);
  14812. }
  14813. }
  14814. class Octant {
  14815. static octant() {
  14816. if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') {
  14817. const dx = arguments[0],
  14818. dy = arguments[1];
  14819. if (dx === 0.0 && dy === 0.0) throw new IllegalArgumentException('Cannot compute the octant for point ( ' + dx + ', ' + dy + ' )');
  14820. const adx = Math.abs(dx);
  14821. const ady = Math.abs(dy);
  14822. if (dx >= 0) {
  14823. if (dy >= 0) {
  14824. if (adx >= ady) return 0;else return 1;
  14825. } else if (adx >= ady) return 7;else return 6;
  14826. } else if (dy >= 0) {
  14827. if (adx >= ady) return 3;else return 2;
  14828. } else if (adx >= ady) return 4;else return 5;
  14829. } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Coordinate) {
  14830. const p0 = arguments[0],
  14831. p1 = arguments[1];
  14832. const dx = p1.x - p0.x;
  14833. const dy = p1.y - p0.y;
  14834. if (dx === 0.0 && dy === 0.0) throw new IllegalArgumentException('Cannot compute the octant for two identical points ' + p0);
  14835. return Octant.octant(dx, dy);
  14836. }
  14837. }
  14838. }
  14839. class SegmentString {
  14840. getCoordinates() {}
  14841. size() {}
  14842. getCoordinate(i) {}
  14843. isClosed() {}
  14844. setData(data) {}
  14845. getData() {}
  14846. }
  14847. class NodableSegmentString {
  14848. addIntersection(intPt, segmentIndex) {}
  14849. get interfaces_() {
  14850. return [SegmentString];
  14851. }
  14852. }
  14853. class NodedSegmentString {
  14854. constructor() {
  14855. NodedSegmentString.constructor_.apply(this, arguments);
  14856. }
  14857. static constructor_() {
  14858. this._nodeList = new SegmentNodeList(this);
  14859. this._pts = null;
  14860. this._data = null;
  14861. const pts = arguments[0],
  14862. data = arguments[1];
  14863. this._pts = pts;
  14864. this._data = data;
  14865. }
  14866. static getNodedSubstrings() {
  14867. if (arguments.length === 1) {
  14868. const segStrings = arguments[0];
  14869. const resultEdgelist = new ArrayList();
  14870. NodedSegmentString.getNodedSubstrings(segStrings, resultEdgelist);
  14871. return resultEdgelist;
  14872. } else if (arguments.length === 2) {
  14873. const segStrings = arguments[0],
  14874. resultEdgelist = arguments[1];
  14875. for (let i = segStrings.iterator(); i.hasNext();) {
  14876. const ss = i.next();
  14877. ss.getNodeList().addSplitEdges(resultEdgelist);
  14878. }
  14879. }
  14880. }
  14881. getCoordinates() {
  14882. return this._pts;
  14883. }
  14884. size() {
  14885. return this._pts.length;
  14886. }
  14887. getCoordinate(i) {
  14888. return this._pts[i];
  14889. }
  14890. isClosed() {
  14891. return this._pts[0].equals(this._pts[this._pts.length - 1]);
  14892. }
  14893. getSegmentOctant(index) {
  14894. if (index === this._pts.length - 1) return -1;
  14895. return this.safeOctant(this.getCoordinate(index), this.getCoordinate(index + 1));
  14896. }
  14897. setData(data) {
  14898. this._data = data;
  14899. }
  14900. safeOctant(p0, p1) {
  14901. if (p0.equals2D(p1)) return 0;
  14902. return Octant.octant(p0, p1);
  14903. }
  14904. getData() {
  14905. return this._data;
  14906. }
  14907. addIntersection() {
  14908. if (arguments.length === 2) {
  14909. const intPt = arguments[0],
  14910. segmentIndex = arguments[1];
  14911. this.addIntersectionNode(intPt, segmentIndex);
  14912. } else if (arguments.length === 4) {
  14913. const li = arguments[0],
  14914. segmentIndex = arguments[1],
  14915. intIndex = arguments[3];
  14916. const intPt = new Coordinate(li.getIntersection(intIndex));
  14917. this.addIntersection(intPt, segmentIndex);
  14918. }
  14919. }
  14920. toString() {
  14921. return WKTWriter.toLineString(new CoordinateArraySequence(this._pts));
  14922. }
  14923. getNodeList() {
  14924. return this._nodeList;
  14925. }
  14926. addIntersectionNode(intPt, segmentIndex) {
  14927. let normalizedSegmentIndex = segmentIndex;
  14928. const nextSegIndex = normalizedSegmentIndex + 1;
  14929. if (nextSegIndex < this._pts.length) {
  14930. const nextPt = this._pts[nextSegIndex];
  14931. if (intPt.equals2D(nextPt)) normalizedSegmentIndex = nextSegIndex;
  14932. }
  14933. const ei = this._nodeList.add(intPt, normalizedSegmentIndex);
  14934. return ei;
  14935. }
  14936. addIntersections(li, segmentIndex, geomIndex) {
  14937. for (let i = 0; i < li.getIntersectionNum(); i++) this.addIntersection(li, segmentIndex, geomIndex, i);
  14938. }
  14939. get interfaces_() {
  14940. return [NodableSegmentString];
  14941. }
  14942. }
  14943. class MonotoneChainOverlapAction {
  14944. constructor() {
  14945. MonotoneChainOverlapAction.constructor_.apply(this, arguments);
  14946. }
  14947. static constructor_() {
  14948. this._overlapSeg1 = new LineSegment();
  14949. this._overlapSeg2 = new LineSegment();
  14950. }
  14951. overlap() {
  14952. if (arguments.length === 2) ; else if (arguments.length === 4) {
  14953. const mc1 = arguments[0],
  14954. start1 = arguments[1],
  14955. mc2 = arguments[2],
  14956. start2 = arguments[3];
  14957. mc1.getLineSegment(start1, this._overlapSeg1);
  14958. mc2.getLineSegment(start2, this._overlapSeg2);
  14959. this.overlap(this._overlapSeg1, this._overlapSeg2);
  14960. }
  14961. }
  14962. }
  14963. class MonotoneChain {
  14964. constructor() {
  14965. MonotoneChain.constructor_.apply(this, arguments);
  14966. }
  14967. static constructor_() {
  14968. this._pts = null;
  14969. this._start = null;
  14970. this._end = null;
  14971. this._env = null;
  14972. this._context = null;
  14973. this._id = null;
  14974. const pts = arguments[0],
  14975. start = arguments[1],
  14976. end = arguments[2],
  14977. context = arguments[3];
  14978. this._pts = pts;
  14979. this._start = start;
  14980. this._end = end;
  14981. this._context = context;
  14982. }
  14983. getLineSegment(index, ls) {
  14984. ls.p0 = this._pts[index];
  14985. ls.p1 = this._pts[index + 1];
  14986. }
  14987. computeSelect(searchEnv, start0, end0, mcs) {
  14988. const p0 = this._pts[start0];
  14989. const p1 = this._pts[end0];
  14990. if (end0 - start0 === 1) {
  14991. mcs.select(this, start0);
  14992. return null;
  14993. }
  14994. if (!searchEnv.intersects(p0, p1)) return null;
  14995. const mid = Math.trunc((start0 + end0) / 2);
  14996. if (start0 < mid) this.computeSelect(searchEnv, start0, mid, mcs);
  14997. if (mid < end0) this.computeSelect(searchEnv, mid, end0, mcs);
  14998. }
  14999. getCoordinates() {
  15000. const coord = new Array(this._end - this._start + 1).fill(null);
  15001. let index = 0;
  15002. for (let i = this._start; i <= this._end; i++) coord[index++] = this._pts[i];
  15003. return coord;
  15004. }
  15005. computeOverlaps() {
  15006. if (arguments.length === 2) {
  15007. const mc = arguments[0],
  15008. mco = arguments[1];
  15009. this.computeOverlaps(this._start, this._end, mc, mc._start, mc._end, mco);
  15010. } else if (arguments.length === 6) {
  15011. const start0 = arguments[0],
  15012. end0 = arguments[1],
  15013. mc = arguments[2],
  15014. start1 = arguments[3],
  15015. end1 = arguments[4],
  15016. mco = arguments[5];
  15017. if (end0 - start0 === 1 && end1 - start1 === 1) {
  15018. mco.overlap(this, start0, mc, start1);
  15019. return null;
  15020. }
  15021. if (!this.overlaps(start0, end0, mc, start1, end1)) return null;
  15022. const mid0 = Math.trunc((start0 + end0) / 2);
  15023. const mid1 = Math.trunc((start1 + end1) / 2);
  15024. if (start0 < mid0) {
  15025. if (start1 < mid1) this.computeOverlaps(start0, mid0, mc, start1, mid1, mco);
  15026. if (mid1 < end1) this.computeOverlaps(start0, mid0, mc, mid1, end1, mco);
  15027. }
  15028. if (mid0 < end0) {
  15029. if (start1 < mid1) this.computeOverlaps(mid0, end0, mc, start1, mid1, mco);
  15030. if (mid1 < end1) this.computeOverlaps(mid0, end0, mc, mid1, end1, mco);
  15031. }
  15032. }
  15033. }
  15034. setId(id) {
  15035. this._id = id;
  15036. }
  15037. select(searchEnv, mcs) {
  15038. this.computeSelect(searchEnv, this._start, this._end, mcs);
  15039. }
  15040. getEnvelope() {
  15041. if (this._env === null) {
  15042. const p0 = this._pts[this._start];
  15043. const p1 = this._pts[this._end];
  15044. this._env = new Envelope(p0, p1);
  15045. }
  15046. return this._env;
  15047. }
  15048. overlaps(start0, end0, mc, start1, end1) {
  15049. return Envelope.intersects(this._pts[start0], this._pts[end0], mc._pts[start1], mc._pts[end1]);
  15050. }
  15051. getEndIndex() {
  15052. return this._end;
  15053. }
  15054. getStartIndex() {
  15055. return this._start;
  15056. }
  15057. getContext() {
  15058. return this._context;
  15059. }
  15060. getId() {
  15061. return this._id;
  15062. }
  15063. }
  15064. class MonotoneChainBuilder {
  15065. static findChainEnd(pts, start) {
  15066. let safeStart = start;
  15067. while (safeStart < pts.length - 1 && pts[safeStart].equals2D(pts[safeStart + 1])) safeStart++;
  15068. if (safeStart >= pts.length - 1) return pts.length - 1;
  15069. const chainQuad = Quadrant.quadrant(pts[safeStart], pts[safeStart + 1]);
  15070. let last = start + 1;
  15071. while (last < pts.length) {
  15072. if (!pts[last - 1].equals2D(pts[last])) {
  15073. const quad = Quadrant.quadrant(pts[last - 1], pts[last]);
  15074. if (quad !== chainQuad) break;
  15075. }
  15076. last++;
  15077. }
  15078. return last - 1;
  15079. }
  15080. static getChains() {
  15081. if (arguments.length === 1) {
  15082. const pts = arguments[0];
  15083. return MonotoneChainBuilder.getChains(pts, null);
  15084. } else if (arguments.length === 2) {
  15085. const pts = arguments[0],
  15086. context = arguments[1];
  15087. const mcList = new ArrayList();
  15088. let chainStart = 0;
  15089. do {
  15090. const chainEnd = MonotoneChainBuilder.findChainEnd(pts, chainStart);
  15091. const mc = new MonotoneChain(pts, chainStart, chainEnd, context);
  15092. mcList.add(mc);
  15093. chainStart = chainEnd;
  15094. } while (chainStart < pts.length - 1);
  15095. return mcList;
  15096. }
  15097. }
  15098. }
  15099. class Noder {
  15100. computeNodes(segStrings) {}
  15101. getNodedSubstrings() {}
  15102. }
  15103. class SinglePassNoder {
  15104. constructor() {
  15105. SinglePassNoder.constructor_.apply(this, arguments);
  15106. }
  15107. static constructor_() {
  15108. this._segInt = null;
  15109. if (arguments.length === 0) ; else if (arguments.length === 1) {
  15110. const segInt = arguments[0];
  15111. this.setSegmentIntersector(segInt);
  15112. }
  15113. }
  15114. setSegmentIntersector(segInt) {
  15115. this._segInt = segInt;
  15116. }
  15117. get interfaces_() {
  15118. return [Noder];
  15119. }
  15120. }
  15121. class MCIndexNoder extends SinglePassNoder {
  15122. constructor() {
  15123. super();
  15124. MCIndexNoder.constructor_.apply(this, arguments);
  15125. }
  15126. static constructor_() {
  15127. this._monoChains = new ArrayList();
  15128. this._index = new STRtree();
  15129. this._idCounter = 0;
  15130. this._nodedSegStrings = null;
  15131. this._nOverlaps = 0;
  15132. if (arguments.length === 0) ; else if (arguments.length === 1) {
  15133. const si = arguments[0];
  15134. SinglePassNoder.constructor_.call(this, si);
  15135. }
  15136. }
  15137. getMonotoneChains() {
  15138. return this._monoChains;
  15139. }
  15140. getNodedSubstrings() {
  15141. return NodedSegmentString.getNodedSubstrings(this._nodedSegStrings);
  15142. }
  15143. getIndex() {
  15144. return this._index;
  15145. }
  15146. add(segStr) {
  15147. const segChains = MonotoneChainBuilder.getChains(segStr.getCoordinates(), segStr);
  15148. for (let i = segChains.iterator(); i.hasNext();) {
  15149. const mc = i.next();
  15150. mc.setId(this._idCounter++);
  15151. this._index.insert(mc.getEnvelope(), mc);
  15152. this._monoChains.add(mc);
  15153. }
  15154. }
  15155. computeNodes(inputSegStrings) {
  15156. this._nodedSegStrings = inputSegStrings;
  15157. for (let i = inputSegStrings.iterator(); i.hasNext();) this.add(i.next());
  15158. this.intersectChains();
  15159. }
  15160. intersectChains() {
  15161. const overlapAction = new SegmentOverlapAction(this._segInt);
  15162. for (let i = this._monoChains.iterator(); i.hasNext();) {
  15163. const queryChain = i.next();
  15164. const overlapChains = this._index.query(queryChain.getEnvelope());
  15165. for (let j = overlapChains.iterator(); j.hasNext();) {
  15166. const testChain = j.next();
  15167. if (testChain.getId() > queryChain.getId()) {
  15168. queryChain.computeOverlaps(testChain, overlapAction);
  15169. this._nOverlaps++;
  15170. }
  15171. if (this._segInt.isDone()) return null;
  15172. }
  15173. }
  15174. }
  15175. }
  15176. class SegmentOverlapAction extends MonotoneChainOverlapAction {
  15177. constructor() {
  15178. super();
  15179. SegmentOverlapAction.constructor_.apply(this, arguments);
  15180. }
  15181. static constructor_() {
  15182. this._si = null;
  15183. const si = arguments[0];
  15184. this._si = si;
  15185. }
  15186. overlap() {
  15187. if (arguments.length === 4) {
  15188. const mc1 = arguments[0],
  15189. start1 = arguments[1],
  15190. mc2 = arguments[2],
  15191. start2 = arguments[3];
  15192. const ss1 = mc1.getContext();
  15193. const ss2 = mc2.getContext();
  15194. this._si.processIntersections(ss1, start1, ss2, start2);
  15195. } else {
  15196. return super.overlap.apply(this, arguments);
  15197. }
  15198. }
  15199. }
  15200. MCIndexNoder.SegmentOverlapAction = SegmentOverlapAction;
  15201. class ScaledNoder {
  15202. constructor() {
  15203. ScaledNoder.constructor_.apply(this, arguments);
  15204. }
  15205. static constructor_() {
  15206. this._noder = null;
  15207. this._scaleFactor = null;
  15208. this._offsetX = null;
  15209. this._offsetY = null;
  15210. this._isScaled = false;
  15211. if (arguments.length === 2) {
  15212. const noder = arguments[0],
  15213. scaleFactor = arguments[1];
  15214. ScaledNoder.constructor_.call(this, noder, scaleFactor, 0, 0);
  15215. } else if (arguments.length === 4) {
  15216. const noder = arguments[0],
  15217. scaleFactor = arguments[1];
  15218. this._noder = noder;
  15219. this._scaleFactor = scaleFactor;
  15220. this._isScaled = !this.isIntegerPrecision();
  15221. }
  15222. }
  15223. rescale() {
  15224. if (hasInterface(arguments[0], Collection)) {
  15225. const segStrings = arguments[0];
  15226. for (let i = segStrings.iterator(); i.hasNext();) {
  15227. const ss = i.next();
  15228. this.rescale(ss.getCoordinates());
  15229. }
  15230. } else if (arguments[0] instanceof Array) {
  15231. const pts = arguments[0];
  15232. for (let i = 0; i < pts.length; i++) {
  15233. pts[i].x = pts[i].x / this._scaleFactor + this._offsetX;
  15234. pts[i].y = pts[i].y / this._scaleFactor + this._offsetY;
  15235. }
  15236. if (pts.length === 2 && pts[0].equals2D(pts[1])) System.out.println(pts);
  15237. }
  15238. }
  15239. scale() {
  15240. if (hasInterface(arguments[0], Collection)) {
  15241. const segStrings = arguments[0];
  15242. const nodedSegmentStrings = new ArrayList(segStrings.size());
  15243. for (let i = segStrings.iterator(); i.hasNext();) {
  15244. const ss = i.next();
  15245. nodedSegmentStrings.add(new NodedSegmentString(this.scale(ss.getCoordinates()), ss.getData()));
  15246. }
  15247. return nodedSegmentStrings;
  15248. } else if (arguments[0] instanceof Array) {
  15249. const pts = arguments[0];
  15250. const roundPts = new Array(pts.length).fill(null);
  15251. for (let i = 0; i < pts.length; i++) roundPts[i] = new Coordinate(Math.round((pts[i].x - this._offsetX) * this._scaleFactor), Math.round((pts[i].y - this._offsetY) * this._scaleFactor), pts[i].getZ());
  15252. const roundPtsNoDup = CoordinateArrays.removeRepeatedPoints(roundPts);
  15253. return roundPtsNoDup;
  15254. }
  15255. }
  15256. isIntegerPrecision() {
  15257. return this._scaleFactor === 1.0;
  15258. }
  15259. getNodedSubstrings() {
  15260. const splitSS = this._noder.getNodedSubstrings();
  15261. if (this._isScaled) this.rescale(splitSS);
  15262. return splitSS;
  15263. }
  15264. computeNodes(inputSegStrings) {
  15265. let intSegStrings = inputSegStrings;
  15266. if (this._isScaled) intSegStrings = this.scale(inputSegStrings);
  15267. this._noder.computeNodes(intSegStrings);
  15268. }
  15269. get interfaces_() {
  15270. return [Noder];
  15271. }
  15272. }
  15273. var noding = /*#__PURE__*/Object.freeze({
  15274. __proto__: null,
  15275. MCIndexNoder: MCIndexNoder,
  15276. ScaledNoder: ScaledNoder,
  15277. SegmentString: SegmentString
  15278. });
  15279. class BoundaryOp {
  15280. constructor() {
  15281. BoundaryOp.constructor_.apply(this, arguments);
  15282. }
  15283. static constructor_() {
  15284. this._geom = null;
  15285. this._geomFact = null;
  15286. this._bnRule = null;
  15287. this._endpointMap = null;
  15288. if (arguments.length === 1) {
  15289. const geom = arguments[0];
  15290. BoundaryOp.constructor_.call(this, geom, BoundaryNodeRule.MOD2_BOUNDARY_RULE);
  15291. } else if (arguments.length === 2) {
  15292. const geom = arguments[0],
  15293. bnRule = arguments[1];
  15294. this._geom = geom;
  15295. this._geomFact = geom.getFactory();
  15296. this._bnRule = bnRule;
  15297. }
  15298. }
  15299. static getBoundary() {
  15300. if (arguments.length === 1) {
  15301. const g = arguments[0];
  15302. const bop = new BoundaryOp(g);
  15303. return bop.getBoundary();
  15304. } else if (arguments.length === 2) {
  15305. const g = arguments[0],
  15306. bnRule = arguments[1];
  15307. const bop = new BoundaryOp(g, bnRule);
  15308. return bop.getBoundary();
  15309. }
  15310. }
  15311. boundaryMultiLineString(mLine) {
  15312. if (this._geom.isEmpty()) return this.getEmptyMultiPoint();
  15313. const bdyPts = this.computeBoundaryCoordinates(mLine);
  15314. if (bdyPts.length === 1) return this._geomFact.createPoint(bdyPts[0]);
  15315. return this._geomFact.createMultiPointFromCoords(bdyPts);
  15316. }
  15317. getBoundary() {
  15318. if (this._geom instanceof LineString) return this.boundaryLineString(this._geom);
  15319. if (this._geom instanceof MultiLineString) return this.boundaryMultiLineString(this._geom);
  15320. return this._geom.getBoundary();
  15321. }
  15322. boundaryLineString(line) {
  15323. if (this._geom.isEmpty()) return this.getEmptyMultiPoint();
  15324. if (line.isClosed()) {
  15325. const closedEndpointOnBoundary = this._bnRule.isInBoundary(2);
  15326. if (closedEndpointOnBoundary) return line.getStartPoint();else return this._geomFact.createMultiPoint();
  15327. }
  15328. return this._geomFact.createMultiPoint([line.getStartPoint(), line.getEndPoint()]);
  15329. }
  15330. getEmptyMultiPoint() {
  15331. return this._geomFact.createMultiPoint();
  15332. }
  15333. computeBoundaryCoordinates(mLine) {
  15334. const bdyPts = new ArrayList();
  15335. this._endpointMap = new TreeMap();
  15336. for (let i = 0; i < mLine.getNumGeometries(); i++) {
  15337. const line = mLine.getGeometryN(i);
  15338. if (line.getNumPoints() === 0) continue;
  15339. this.addEndpoint(line.getCoordinateN(0));
  15340. this.addEndpoint(line.getCoordinateN(line.getNumPoints() - 1));
  15341. }
  15342. for (let it = this._endpointMap.entrySet().iterator(); it.hasNext();) {
  15343. const entry = it.next();
  15344. const counter = entry.getValue();
  15345. const valence = counter.count;
  15346. if (this._bnRule.isInBoundary(valence)) bdyPts.add(entry.getKey());
  15347. }
  15348. return CoordinateArrays.toCoordinateArray(bdyPts);
  15349. }
  15350. addEndpoint(pt) {
  15351. let counter = this._endpointMap.get(pt);
  15352. if (counter === null) {
  15353. counter = new Counter$1();
  15354. this._endpointMap.put(pt, counter);
  15355. }
  15356. counter.count++;
  15357. }
  15358. }
  15359. class Counter$1 {
  15360. constructor() {
  15361. Counter$1.constructor_.apply(this, arguments);
  15362. }
  15363. static constructor_() {
  15364. this.count = null;
  15365. }
  15366. }
  15367. class IsSimpleOp {
  15368. constructor() {
  15369. IsSimpleOp.constructor_.apply(this, arguments);
  15370. }
  15371. static constructor_() {
  15372. this._inputGeom = null;
  15373. this._isClosedEndpointsInInterior = true;
  15374. this._nonSimpleLocation = null;
  15375. if (arguments.length === 1) {
  15376. const geom = arguments[0];
  15377. this._inputGeom = geom;
  15378. } else if (arguments.length === 2) {
  15379. const geom = arguments[0],
  15380. boundaryNodeRule = arguments[1];
  15381. this._inputGeom = geom;
  15382. this._isClosedEndpointsInInterior = !boundaryNodeRule.isInBoundary(2);
  15383. }
  15384. }
  15385. static isSimple() {
  15386. if (arguments.length === 1) {
  15387. const geom = arguments[0];
  15388. const op = new IsSimpleOp(geom);
  15389. return op.isSimple();
  15390. } else if (arguments.length === 2) {
  15391. const geom = arguments[0],
  15392. boundaryNodeRule = arguments[1];
  15393. const op = new IsSimpleOp(geom, boundaryNodeRule);
  15394. return op.isSimple();
  15395. }
  15396. }
  15397. isSimpleMultiPoint(mp) {
  15398. if (mp.isEmpty()) return true;
  15399. const points = new TreeSet();
  15400. for (let i = 0; i < mp.getNumGeometries(); i++) {
  15401. const pt = mp.getGeometryN(i);
  15402. const p = pt.getCoordinate();
  15403. if (points.contains(p)) {
  15404. this._nonSimpleLocation = p;
  15405. return false;
  15406. }
  15407. points.add(p);
  15408. }
  15409. return true;
  15410. }
  15411. isSimplePolygonal(geom) {
  15412. const rings = LinearComponentExtracter.getLines(geom);
  15413. for (let i = rings.iterator(); i.hasNext();) {
  15414. const ring = i.next();
  15415. if (!this.isSimpleLinearGeometry(ring)) return false;
  15416. }
  15417. return true;
  15418. }
  15419. hasClosedEndpointIntersection(graph) {
  15420. const endPoints = new TreeMap();
  15421. for (let i = graph.getEdgeIterator(); i.hasNext();) {
  15422. const e = i.next();
  15423. const isClosed = e.isClosed();
  15424. const p0 = e.getCoordinate(0);
  15425. this.addEndpoint(endPoints, p0, isClosed);
  15426. const p1 = e.getCoordinate(e.getNumPoints() - 1);
  15427. this.addEndpoint(endPoints, p1, isClosed);
  15428. }
  15429. for (let i = endPoints.values().iterator(); i.hasNext();) {
  15430. const eiInfo = i.next();
  15431. if (eiInfo.isClosed && eiInfo.degree !== 2) {
  15432. this._nonSimpleLocation = eiInfo.getCoordinate();
  15433. return true;
  15434. }
  15435. }
  15436. return false;
  15437. }
  15438. getNonSimpleLocation() {
  15439. return this._nonSimpleLocation;
  15440. }
  15441. isSimpleLinearGeometry(geom) {
  15442. if (geom.isEmpty()) return true;
  15443. const graph = new GeometryGraph(0, geom);
  15444. const li = new RobustLineIntersector();
  15445. const si = graph.computeSelfNodes(li, true);
  15446. if (!si.hasIntersection()) return true;
  15447. if (si.hasProperIntersection()) {
  15448. this._nonSimpleLocation = si.getProperIntersectionPoint();
  15449. return false;
  15450. }
  15451. if (this.hasNonEndpointIntersection(graph)) return false;
  15452. if (this._isClosedEndpointsInInterior) if (this.hasClosedEndpointIntersection(graph)) return false;
  15453. return true;
  15454. }
  15455. hasNonEndpointIntersection(graph) {
  15456. for (let i = graph.getEdgeIterator(); i.hasNext();) {
  15457. const e = i.next();
  15458. const maxSegmentIndex = e.getMaximumSegmentIndex();
  15459. for (let eiIt = e.getEdgeIntersectionList().iterator(); eiIt.hasNext();) {
  15460. const ei = eiIt.next();
  15461. if (!ei.isEndPoint(maxSegmentIndex)) {
  15462. this._nonSimpleLocation = ei.getCoordinate();
  15463. return true;
  15464. }
  15465. }
  15466. }
  15467. return false;
  15468. }
  15469. addEndpoint(endPoints, p, isClosed) {
  15470. let eiInfo = endPoints.get(p);
  15471. if (eiInfo === null) {
  15472. eiInfo = new EndpointInfo(p);
  15473. endPoints.put(p, eiInfo);
  15474. }
  15475. eiInfo.addEndpoint(isClosed);
  15476. }
  15477. computeSimple(geom) {
  15478. this._nonSimpleLocation = null;
  15479. if (geom.isEmpty()) return true;
  15480. if (geom instanceof LineString) return this.isSimpleLinearGeometry(geom);
  15481. if (geom instanceof MultiLineString) return this.isSimpleLinearGeometry(geom);
  15482. if (geom instanceof MultiPoint) return this.isSimpleMultiPoint(geom);
  15483. if (hasInterface(geom, Polygonal)) return this.isSimplePolygonal(geom);
  15484. if (geom instanceof GeometryCollection) return this.isSimpleGeometryCollection(geom);
  15485. return true;
  15486. }
  15487. isSimple() {
  15488. this._nonSimpleLocation = null;
  15489. return this.computeSimple(this._inputGeom);
  15490. }
  15491. isSimpleGeometryCollection(geom) {
  15492. for (let i = 0; i < geom.getNumGeometries(); i++) {
  15493. const comp = geom.getGeometryN(i);
  15494. if (!this.computeSimple(comp)) return false;
  15495. }
  15496. return true;
  15497. }
  15498. }
  15499. class EndpointInfo {
  15500. constructor() {
  15501. EndpointInfo.constructor_.apply(this, arguments);
  15502. }
  15503. static constructor_() {
  15504. this.pt = null;
  15505. this.isClosed = null;
  15506. this.degree = null;
  15507. const pt = arguments[0];
  15508. this.pt = pt;
  15509. this.isClosed = false;
  15510. this.degree = 0;
  15511. }
  15512. addEndpoint(isClosed) {
  15513. this.degree++;
  15514. this.isClosed |= isClosed;
  15515. }
  15516. getCoordinate() {
  15517. return this.pt;
  15518. }
  15519. }
  15520. IsSimpleOp.EndpointInfo = EndpointInfo;
  15521. class BufferParameters {
  15522. constructor() {
  15523. BufferParameters.constructor_.apply(this, arguments);
  15524. }
  15525. static constructor_() {
  15526. this._quadrantSegments = BufferParameters.DEFAULT_QUADRANT_SEGMENTS;
  15527. this._endCapStyle = BufferParameters.CAP_ROUND;
  15528. this._joinStyle = BufferParameters.JOIN_ROUND;
  15529. this._mitreLimit = BufferParameters.DEFAULT_MITRE_LIMIT;
  15530. this._isSingleSided = false;
  15531. this._simplifyFactor = BufferParameters.DEFAULT_SIMPLIFY_FACTOR;
  15532. if (arguments.length === 0) ; else if (arguments.length === 1) {
  15533. const quadrantSegments = arguments[0];
  15534. this.setQuadrantSegments(quadrantSegments);
  15535. } else if (arguments.length === 2) {
  15536. const quadrantSegments = arguments[0],
  15537. endCapStyle = arguments[1];
  15538. this.setQuadrantSegments(quadrantSegments);
  15539. this.setEndCapStyle(endCapStyle);
  15540. } else if (arguments.length === 4) {
  15541. const quadrantSegments = arguments[0],
  15542. endCapStyle = arguments[1],
  15543. joinStyle = arguments[2],
  15544. mitreLimit = arguments[3];
  15545. this.setQuadrantSegments(quadrantSegments);
  15546. this.setEndCapStyle(endCapStyle);
  15547. this.setJoinStyle(joinStyle);
  15548. this.setMitreLimit(mitreLimit);
  15549. }
  15550. }
  15551. static bufferDistanceError(quadSegs) {
  15552. const alpha = Math.PI / 2.0 / quadSegs;
  15553. return 1 - Math.cos(alpha / 2.0);
  15554. }
  15555. getEndCapStyle() {
  15556. return this._endCapStyle;
  15557. }
  15558. isSingleSided() {
  15559. return this._isSingleSided;
  15560. }
  15561. setQuadrantSegments(quadSegs) {
  15562. this._quadrantSegments = quadSegs;
  15563. if (this._quadrantSegments === 0) this._joinStyle = BufferParameters.JOIN_BEVEL;
  15564. if (this._quadrantSegments < 0) {
  15565. this._joinStyle = BufferParameters.JOIN_MITRE;
  15566. this._mitreLimit = Math.abs(this._quadrantSegments);
  15567. }
  15568. if (quadSegs <= 0) this._quadrantSegments = 1;
  15569. if (this._joinStyle !== BufferParameters.JOIN_ROUND) this._quadrantSegments = BufferParameters.DEFAULT_QUADRANT_SEGMENTS;
  15570. }
  15571. getJoinStyle() {
  15572. return this._joinStyle;
  15573. }
  15574. setJoinStyle(joinStyle) {
  15575. this._joinStyle = joinStyle;
  15576. }
  15577. setSimplifyFactor(simplifyFactor) {
  15578. this._simplifyFactor = simplifyFactor < 0 ? 0 : simplifyFactor;
  15579. }
  15580. getSimplifyFactor() {
  15581. return this._simplifyFactor;
  15582. }
  15583. getQuadrantSegments() {
  15584. return this._quadrantSegments;
  15585. }
  15586. setEndCapStyle(endCapStyle) {
  15587. this._endCapStyle = endCapStyle;
  15588. }
  15589. getMitreLimit() {
  15590. return this._mitreLimit;
  15591. }
  15592. setMitreLimit(mitreLimit) {
  15593. this._mitreLimit = mitreLimit;
  15594. }
  15595. setSingleSided(isSingleSided) {
  15596. this._isSingleSided = isSingleSided;
  15597. }
  15598. }
  15599. BufferParameters.CAP_ROUND = 1;
  15600. BufferParameters.CAP_FLAT = 2;
  15601. BufferParameters.CAP_SQUARE = 3;
  15602. BufferParameters.JOIN_ROUND = 1;
  15603. BufferParameters.JOIN_MITRE = 2;
  15604. BufferParameters.JOIN_BEVEL = 3;
  15605. BufferParameters.DEFAULT_QUADRANT_SEGMENTS = 8;
  15606. BufferParameters.DEFAULT_MITRE_LIMIT = 5.0;
  15607. BufferParameters.DEFAULT_SIMPLIFY_FACTOR = 0.01;
  15608. class RightmostEdgeFinder {
  15609. constructor() {
  15610. RightmostEdgeFinder.constructor_.apply(this, arguments);
  15611. }
  15612. static constructor_() {
  15613. this._minIndex = -1;
  15614. this._minCoord = null;
  15615. this._minDe = null;
  15616. this._orientedDe = null;
  15617. }
  15618. getCoordinate() {
  15619. return this._minCoord;
  15620. }
  15621. getRightmostSide(de, index) {
  15622. let side = this.getRightmostSideOfSegment(de, index);
  15623. if (side < 0) side = this.getRightmostSideOfSegment(de, index - 1);
  15624. if (side < 0) {
  15625. this._minCoord = null;
  15626. this.checkForRightmostCoordinate(de);
  15627. }
  15628. return side;
  15629. }
  15630. findRightmostEdgeAtVertex() {
  15631. const pts = this._minDe.getEdge().getCoordinates();
  15632. Assert.isTrue(this._minIndex > 0 && this._minIndex < pts.length, 'rightmost point expected to be interior vertex of edge');
  15633. const pPrev = pts[this._minIndex - 1];
  15634. const pNext = pts[this._minIndex + 1];
  15635. const orientation = Orientation.index(this._minCoord, pNext, pPrev);
  15636. let usePrev = false;
  15637. if (pPrev.y < this._minCoord.y && pNext.y < this._minCoord.y && orientation === Orientation.COUNTERCLOCKWISE) usePrev = true;else if (pPrev.y > this._minCoord.y && pNext.y > this._minCoord.y && orientation === Orientation.CLOCKWISE) usePrev = true;
  15638. if (usePrev) this._minIndex = this._minIndex - 1;
  15639. }
  15640. getRightmostSideOfSegment(de, i) {
  15641. const e = de.getEdge();
  15642. const coord = e.getCoordinates();
  15643. if (i < 0 || i + 1 >= coord.length) return -1;
  15644. if (coord[i].y === coord[i + 1].y) return -1;
  15645. let pos = Position.LEFT;
  15646. if (coord[i].y < coord[i + 1].y) pos = Position.RIGHT;
  15647. return pos;
  15648. }
  15649. getEdge() {
  15650. return this._orientedDe;
  15651. }
  15652. checkForRightmostCoordinate(de) {
  15653. const coord = de.getEdge().getCoordinates();
  15654. for (let i = 0; i < coord.length - 1; i++) if (this._minCoord === null || coord[i].x > this._minCoord.x) {
  15655. this._minDe = de;
  15656. this._minIndex = i;
  15657. this._minCoord = coord[i];
  15658. }
  15659. }
  15660. findRightmostEdgeAtNode() {
  15661. const node = this._minDe.getNode();
  15662. const star = node.getEdges();
  15663. this._minDe = star.getRightmostEdge();
  15664. if (!this._minDe.isForward()) {
  15665. this._minDe = this._minDe.getSym();
  15666. this._minIndex = this._minDe.getEdge().getCoordinates().length - 1;
  15667. }
  15668. }
  15669. findEdge(dirEdgeList) {
  15670. for (let i = dirEdgeList.iterator(); i.hasNext();) {
  15671. const de = i.next();
  15672. if (!de.isForward()) continue;
  15673. this.checkForRightmostCoordinate(de);
  15674. }
  15675. Assert.isTrue(this._minIndex !== 0 || this._minCoord.equals(this._minDe.getCoordinate()), 'inconsistency in rightmost processing');
  15676. if (this._minIndex === 0) this.findRightmostEdgeAtNode();else this.findRightmostEdgeAtVertex();
  15677. this._orientedDe = this._minDe;
  15678. const rightmostSide = this.getRightmostSide(this._minDe, this._minIndex);
  15679. if (rightmostSide === Position.LEFT) this._orientedDe = this._minDe.getSym();
  15680. }
  15681. }
  15682. class LinkedList {
  15683. constructor() {
  15684. this.array = [];
  15685. }
  15686. addLast(e) {
  15687. this.array.push(e);
  15688. }
  15689. removeFirst() {
  15690. return this.array.shift();
  15691. }
  15692. isEmpty() {
  15693. return this.array.length === 0;
  15694. }
  15695. }
  15696. class BufferSubgraph {
  15697. constructor() {
  15698. BufferSubgraph.constructor_.apply(this, arguments);
  15699. }
  15700. static constructor_() {
  15701. this._finder = null;
  15702. this._dirEdgeList = new ArrayList();
  15703. this._nodes = new ArrayList();
  15704. this._rightMostCoord = null;
  15705. this._env = null;
  15706. this._finder = new RightmostEdgeFinder();
  15707. }
  15708. clearVisitedEdges() {
  15709. for (let it = this._dirEdgeList.iterator(); it.hasNext();) {
  15710. const de = it.next();
  15711. de.setVisited(false);
  15712. }
  15713. }
  15714. getRightmostCoordinate() {
  15715. return this._rightMostCoord;
  15716. }
  15717. computeNodeDepth(n) {
  15718. let startEdge = null;
  15719. for (let i = n.getEdges().iterator(); i.hasNext();) {
  15720. const de = i.next();
  15721. if (de.isVisited() || de.getSym().isVisited()) {
  15722. startEdge = de;
  15723. break;
  15724. }
  15725. }
  15726. if (startEdge === null) throw new TopologyException('unable to find edge to compute depths at ' + n.getCoordinate());
  15727. n.getEdges().computeDepths(startEdge);
  15728. for (let i = n.getEdges().iterator(); i.hasNext();) {
  15729. const de = i.next();
  15730. de.setVisited(true);
  15731. this.copySymDepths(de);
  15732. }
  15733. }
  15734. computeDepth(outsideDepth) {
  15735. this.clearVisitedEdges();
  15736. const de = this._finder.getEdge();
  15737. de.getNode();
  15738. de.getLabel();
  15739. de.setEdgeDepths(Position.RIGHT, outsideDepth);
  15740. this.copySymDepths(de);
  15741. this.computeDepths(de);
  15742. }
  15743. create(node) {
  15744. this.addReachable(node);
  15745. this._finder.findEdge(this._dirEdgeList);
  15746. this._rightMostCoord = this._finder.getCoordinate();
  15747. }
  15748. findResultEdges() {
  15749. for (let it = this._dirEdgeList.iterator(); it.hasNext();) {
  15750. const de = it.next();
  15751. if (de.getDepth(Position.RIGHT) >= 1 && de.getDepth(Position.LEFT) <= 0 && !de.isInteriorAreaEdge()) de.setInResult(true);
  15752. }
  15753. }
  15754. computeDepths(startEdge) {
  15755. const nodesVisited = new HashSet();
  15756. const nodeQueue = new LinkedList();
  15757. const startNode = startEdge.getNode();
  15758. nodeQueue.addLast(startNode);
  15759. nodesVisited.add(startNode);
  15760. startEdge.setVisited(true);
  15761. while (!nodeQueue.isEmpty()) {
  15762. const n = nodeQueue.removeFirst();
  15763. nodesVisited.add(n);
  15764. this.computeNodeDepth(n);
  15765. for (let i = n.getEdges().iterator(); i.hasNext();) {
  15766. const de = i.next();
  15767. const sym = de.getSym();
  15768. if (sym.isVisited()) continue;
  15769. const adjNode = sym.getNode();
  15770. if (!nodesVisited.contains(adjNode)) {
  15771. nodeQueue.addLast(adjNode);
  15772. nodesVisited.add(adjNode);
  15773. }
  15774. }
  15775. }
  15776. }
  15777. compareTo(o) {
  15778. const graph = o;
  15779. if (this._rightMostCoord.x < graph._rightMostCoord.x) return -1;
  15780. if (this._rightMostCoord.x > graph._rightMostCoord.x) return 1;
  15781. return 0;
  15782. }
  15783. getEnvelope() {
  15784. if (this._env === null) {
  15785. const edgeEnv = new Envelope();
  15786. for (let it = this._dirEdgeList.iterator(); it.hasNext();) {
  15787. const dirEdge = it.next();
  15788. const pts = dirEdge.getEdge().getCoordinates();
  15789. for (let i = 0; i < pts.length - 1; i++) edgeEnv.expandToInclude(pts[i]);
  15790. }
  15791. this._env = edgeEnv;
  15792. }
  15793. return this._env;
  15794. }
  15795. addReachable(startNode) {
  15796. const nodeStack = new Stack();
  15797. nodeStack.add(startNode);
  15798. while (!nodeStack.empty()) {
  15799. const node = nodeStack.pop();
  15800. this.add(node, nodeStack);
  15801. }
  15802. }
  15803. copySymDepths(de) {
  15804. const sym = de.getSym();
  15805. sym.setDepth(Position.LEFT, de.getDepth(Position.RIGHT));
  15806. sym.setDepth(Position.RIGHT, de.getDepth(Position.LEFT));
  15807. }
  15808. add(node, nodeStack) {
  15809. node.setVisited(true);
  15810. this._nodes.add(node);
  15811. for (let i = node.getEdges().iterator(); i.hasNext();) {
  15812. const de = i.next();
  15813. this._dirEdgeList.add(de);
  15814. const sym = de.getSym();
  15815. const symNode = sym.getNode();
  15816. if (!symNode.isVisited()) nodeStack.push(symNode);
  15817. }
  15818. }
  15819. getNodes() {
  15820. return this._nodes;
  15821. }
  15822. getDirectedEdges() {
  15823. return this._dirEdgeList;
  15824. }
  15825. get interfaces_() {
  15826. return [Comparable];
  15827. }
  15828. }
  15829. class EdgeRing$1 {
  15830. constructor() {
  15831. EdgeRing$1.constructor_.apply(this, arguments);
  15832. }
  15833. static constructor_() {
  15834. this._startDe = null;
  15835. this._maxNodeDegree = -1;
  15836. this._edges = new ArrayList();
  15837. this._pts = new ArrayList();
  15838. this._label = new Label(Location.NONE);
  15839. this._ring = null;
  15840. this._isHole = null;
  15841. this._shell = null;
  15842. this._holes = new ArrayList();
  15843. this._geometryFactory = null;
  15844. if (arguments.length === 0) ; else if (arguments.length === 2) {
  15845. const start = arguments[0],
  15846. geometryFactory = arguments[1];
  15847. this._geometryFactory = geometryFactory;
  15848. this.computePoints(start);
  15849. this.computeRing();
  15850. }
  15851. }
  15852. computeRing() {
  15853. if (this._ring !== null) return null;
  15854. const coord = new Array(this._pts.size()).fill(null);
  15855. for (let i = 0; i < this._pts.size(); i++) coord[i] = this._pts.get(i);
  15856. this._ring = this._geometryFactory.createLinearRing(coord);
  15857. this._isHole = Orientation.isCCW(this._ring.getCoordinates());
  15858. }
  15859. isIsolated() {
  15860. return this._label.getGeometryCount() === 1;
  15861. }
  15862. computePoints(start) {
  15863. this._startDe = start;
  15864. let de = start;
  15865. let isFirstEdge = true;
  15866. do {
  15867. if (de === null) throw new TopologyException('Found null DirectedEdge');
  15868. if (de.getEdgeRing() === this) throw new TopologyException('Directed Edge visited twice during ring-building at ' + de.getCoordinate());
  15869. this._edges.add(de);
  15870. const label = de.getLabel();
  15871. Assert.isTrue(label.isArea());
  15872. this.mergeLabel(label);
  15873. this.addPoints(de.getEdge(), de.isForward(), isFirstEdge);
  15874. isFirstEdge = false;
  15875. this.setEdgeRing(de, this);
  15876. de = this.getNext(de);
  15877. } while (de !== this._startDe);
  15878. }
  15879. getLinearRing() {
  15880. return this._ring;
  15881. }
  15882. getCoordinate(i) {
  15883. return this._pts.get(i);
  15884. }
  15885. computeMaxNodeDegree() {
  15886. this._maxNodeDegree = 0;
  15887. let de = this._startDe;
  15888. do {
  15889. const node = de.getNode();
  15890. const degree = node.getEdges().getOutgoingDegree(this);
  15891. if (degree > this._maxNodeDegree) this._maxNodeDegree = degree;
  15892. de = this.getNext(de);
  15893. } while (de !== this._startDe);
  15894. this._maxNodeDegree *= 2;
  15895. }
  15896. addPoints(edge, isForward, isFirstEdge) {
  15897. const edgePts = edge.getCoordinates();
  15898. if (isForward) {
  15899. let startIndex = 1;
  15900. if (isFirstEdge) startIndex = 0;
  15901. for (let i = startIndex; i < edgePts.length; i++) this._pts.add(edgePts[i]);
  15902. } else {
  15903. let startIndex = edgePts.length - 2;
  15904. if (isFirstEdge) startIndex = edgePts.length - 1;
  15905. for (let i = startIndex; i >= 0; i--) this._pts.add(edgePts[i]);
  15906. }
  15907. }
  15908. isHole() {
  15909. return this._isHole;
  15910. }
  15911. setInResult() {
  15912. let de = this._startDe;
  15913. do {
  15914. de.getEdge().setInResult(true);
  15915. de = de.getNext();
  15916. } while (de !== this._startDe);
  15917. }
  15918. containsPoint(p) {
  15919. const shell = this.getLinearRing();
  15920. const env = shell.getEnvelopeInternal();
  15921. if (!env.contains(p)) return false;
  15922. if (!PointLocation.isInRing(p, shell.getCoordinates())) return false;
  15923. for (let i = this._holes.iterator(); i.hasNext();) {
  15924. const hole = i.next();
  15925. if (hole.containsPoint(p)) return false;
  15926. }
  15927. return true;
  15928. }
  15929. addHole(ring) {
  15930. this._holes.add(ring);
  15931. }
  15932. isShell() {
  15933. return this._shell === null;
  15934. }
  15935. getLabel() {
  15936. return this._label;
  15937. }
  15938. getEdges() {
  15939. return this._edges;
  15940. }
  15941. getMaxNodeDegree() {
  15942. if (this._maxNodeDegree < 0) this.computeMaxNodeDegree();
  15943. return this._maxNodeDegree;
  15944. }
  15945. getShell() {
  15946. return this._shell;
  15947. }
  15948. mergeLabel() {
  15949. if (arguments.length === 1) {
  15950. const deLabel = arguments[0];
  15951. this.mergeLabel(deLabel, 0);
  15952. this.mergeLabel(deLabel, 1);
  15953. } else if (arguments.length === 2) {
  15954. const deLabel = arguments[0],
  15955. geomIndex = arguments[1];
  15956. const loc = deLabel.getLocation(geomIndex, Position.RIGHT);
  15957. if (loc === Location.NONE) return null;
  15958. if (this._label.getLocation(geomIndex) === Location.NONE) {
  15959. this._label.setLocation(geomIndex, loc);
  15960. return null;
  15961. }
  15962. }
  15963. }
  15964. setShell(shell) {
  15965. this._shell = shell;
  15966. if (shell !== null) shell.addHole(this);
  15967. }
  15968. toPolygon(geometryFactory) {
  15969. const holeLR = new Array(this._holes.size()).fill(null);
  15970. for (let i = 0; i < this._holes.size(); i++) holeLR[i] = this._holes.get(i).getLinearRing();
  15971. const poly = geometryFactory.createPolygon(this.getLinearRing(), holeLR);
  15972. return poly;
  15973. }
  15974. }
  15975. class MinimalEdgeRing extends EdgeRing$1 {
  15976. constructor() {
  15977. super();
  15978. MinimalEdgeRing.constructor_.apply(this, arguments);
  15979. }
  15980. static constructor_() {
  15981. const start = arguments[0],
  15982. geometryFactory = arguments[1];
  15983. EdgeRing$1.constructor_.call(this, start, geometryFactory);
  15984. }
  15985. setEdgeRing(de, er) {
  15986. de.setMinEdgeRing(er);
  15987. }
  15988. getNext(de) {
  15989. return de.getNextMin();
  15990. }
  15991. }
  15992. class MaximalEdgeRing extends EdgeRing$1 {
  15993. constructor() {
  15994. super();
  15995. MaximalEdgeRing.constructor_.apply(this, arguments);
  15996. }
  15997. static constructor_() {
  15998. const start = arguments[0],
  15999. geometryFactory = arguments[1];
  16000. EdgeRing$1.constructor_.call(this, start, geometryFactory);
  16001. }
  16002. buildMinimalRings() {
  16003. const minEdgeRings = new ArrayList();
  16004. let de = this._startDe;
  16005. do {
  16006. if (de.getMinEdgeRing() === null) {
  16007. const minEr = new MinimalEdgeRing(de, this._geometryFactory);
  16008. minEdgeRings.add(minEr);
  16009. }
  16010. de = de.getNext();
  16011. } while (de !== this._startDe);
  16012. return minEdgeRings;
  16013. }
  16014. setEdgeRing(de, er) {
  16015. de.setEdgeRing(er);
  16016. }
  16017. linkDirectedEdgesForMinimalEdgeRings() {
  16018. let de = this._startDe;
  16019. do {
  16020. const node = de.getNode();
  16021. node.getEdges().linkMinimalDirectedEdges(this);
  16022. de = de.getNext();
  16023. } while (de !== this._startDe);
  16024. }
  16025. getNext(de) {
  16026. return de.getNext();
  16027. }
  16028. }
  16029. class PolygonBuilder {
  16030. constructor() {
  16031. PolygonBuilder.constructor_.apply(this, arguments);
  16032. }
  16033. static constructor_() {
  16034. this._geometryFactory = null;
  16035. this._shellList = new ArrayList();
  16036. const geometryFactory = arguments[0];
  16037. this._geometryFactory = geometryFactory;
  16038. }
  16039. static findEdgeRingContaining(testEr, shellList) {
  16040. const testRing = testEr.getLinearRing();
  16041. const testEnv = testRing.getEnvelopeInternal();
  16042. let testPt = testRing.getCoordinateN(0);
  16043. let minShell = null;
  16044. let minShellEnv = null;
  16045. for (let it = shellList.iterator(); it.hasNext();) {
  16046. const tryShell = it.next();
  16047. const tryShellRing = tryShell.getLinearRing();
  16048. const tryShellEnv = tryShellRing.getEnvelopeInternal();
  16049. if (tryShellEnv.equals(testEnv)) continue;
  16050. if (!tryShellEnv.contains(testEnv)) continue;
  16051. testPt = CoordinateArrays.ptNotInList(testRing.getCoordinates(), tryShellRing.getCoordinates());
  16052. let isContained = false;
  16053. if (PointLocation.isInRing(testPt, tryShellRing.getCoordinates())) isContained = true;
  16054. if (isContained) if (minShell === null || minShellEnv.contains(tryShellEnv)) {
  16055. minShell = tryShell;
  16056. minShellEnv = minShell.getLinearRing().getEnvelopeInternal();
  16057. }
  16058. }
  16059. return minShell;
  16060. }
  16061. sortShellsAndHoles(edgeRings, shellList, freeHoleList) {
  16062. for (let it = edgeRings.iterator(); it.hasNext();) {
  16063. const er = it.next();
  16064. if (er.isHole()) freeHoleList.add(er);else shellList.add(er);
  16065. }
  16066. }
  16067. computePolygons(shellList) {
  16068. const resultPolyList = new ArrayList();
  16069. for (let it = shellList.iterator(); it.hasNext();) {
  16070. const er = it.next();
  16071. const poly = er.toPolygon(this._geometryFactory);
  16072. resultPolyList.add(poly);
  16073. }
  16074. return resultPolyList;
  16075. }
  16076. placeFreeHoles(shellList, freeHoleList) {
  16077. for (let it = freeHoleList.iterator(); it.hasNext();) {
  16078. const hole = it.next();
  16079. if (hole.getShell() === null) {
  16080. const shell = PolygonBuilder.findEdgeRingContaining(hole, shellList);
  16081. if (shell === null) throw new TopologyException('unable to assign hole to a shell', hole.getCoordinate(0));
  16082. hole.setShell(shell);
  16083. }
  16084. }
  16085. }
  16086. buildMinimalEdgeRings(maxEdgeRings, shellList, freeHoleList) {
  16087. const edgeRings = new ArrayList();
  16088. for (let it = maxEdgeRings.iterator(); it.hasNext();) {
  16089. const er = it.next();
  16090. if (er.getMaxNodeDegree() > 2) {
  16091. er.linkDirectedEdgesForMinimalEdgeRings();
  16092. const minEdgeRings = er.buildMinimalRings();
  16093. const shell = this.findShell(minEdgeRings);
  16094. if (shell !== null) {
  16095. this.placePolygonHoles(shell, minEdgeRings);
  16096. shellList.add(shell);
  16097. } else {
  16098. freeHoleList.addAll(minEdgeRings);
  16099. }
  16100. } else {
  16101. edgeRings.add(er);
  16102. }
  16103. }
  16104. return edgeRings;
  16105. }
  16106. buildMaximalEdgeRings(dirEdges) {
  16107. const maxEdgeRings = new ArrayList();
  16108. for (let it = dirEdges.iterator(); it.hasNext();) {
  16109. const de = it.next();
  16110. if (de.isInResult() && de.getLabel().isArea()) if (de.getEdgeRing() === null) {
  16111. const er = new MaximalEdgeRing(de, this._geometryFactory);
  16112. maxEdgeRings.add(er);
  16113. er.setInResult();
  16114. }
  16115. }
  16116. return maxEdgeRings;
  16117. }
  16118. placePolygonHoles(shell, minEdgeRings) {
  16119. for (let it = minEdgeRings.iterator(); it.hasNext();) {
  16120. const er = it.next();
  16121. if (er.isHole()) er.setShell(shell);
  16122. }
  16123. }
  16124. getPolygons() {
  16125. const resultPolyList = this.computePolygons(this._shellList);
  16126. return resultPolyList;
  16127. }
  16128. findShell(minEdgeRings) {
  16129. let shellCount = 0;
  16130. let shell = null;
  16131. for (let it = minEdgeRings.iterator(); it.hasNext();) {
  16132. const er = it.next();
  16133. if (!er.isHole()) {
  16134. shell = er;
  16135. shellCount++;
  16136. }
  16137. }
  16138. Assert.isTrue(shellCount <= 1, 'found two shells in MinimalEdgeRing list');
  16139. return shell;
  16140. }
  16141. add() {
  16142. if (arguments.length === 1) {
  16143. const graph = arguments[0];
  16144. this.add(graph.getEdgeEnds(), graph.getNodes());
  16145. } else if (arguments.length === 2) {
  16146. const dirEdges = arguments[0],
  16147. nodes = arguments[1];
  16148. PlanarGraph$1.linkResultDirectedEdges(nodes);
  16149. const maxEdgeRings = this.buildMaximalEdgeRings(dirEdges);
  16150. const freeHoleList = new ArrayList();
  16151. const edgeRings = this.buildMinimalEdgeRings(maxEdgeRings, this._shellList, freeHoleList);
  16152. this.sortShellsAndHoles(edgeRings, this._shellList, freeHoleList);
  16153. this.placeFreeHoles(this._shellList, freeHoleList);
  16154. }
  16155. }
  16156. }
  16157. class BufferInputLineSimplifier {
  16158. constructor() {
  16159. BufferInputLineSimplifier.constructor_.apply(this, arguments);
  16160. }
  16161. static constructor_() {
  16162. this._inputLine = null;
  16163. this._distanceTol = null;
  16164. this._isDeleted = null;
  16165. this._angleOrientation = Orientation.COUNTERCLOCKWISE;
  16166. const inputLine = arguments[0];
  16167. this._inputLine = inputLine;
  16168. }
  16169. static simplify(inputLine, distanceTol) {
  16170. const simp = new BufferInputLineSimplifier(inputLine);
  16171. return simp.simplify(distanceTol);
  16172. }
  16173. isDeletable(i0, i1, i2, distanceTol) {
  16174. const p0 = this._inputLine[i0];
  16175. const p1 = this._inputLine[i1];
  16176. const p2 = this._inputLine[i2];
  16177. if (!this.isConcave(p0, p1, p2)) return false;
  16178. if (!this.isShallow(p0, p1, p2, distanceTol)) return false;
  16179. return this.isShallowSampled(p0, p1, i0, i2, distanceTol);
  16180. }
  16181. deleteShallowConcavities() {
  16182. let index = 1;
  16183. let midIndex = this.findNextNonDeletedIndex(index);
  16184. let lastIndex = this.findNextNonDeletedIndex(midIndex);
  16185. let isChanged = false;
  16186. while (lastIndex < this._inputLine.length) {
  16187. let isMiddleVertexDeleted = false;
  16188. if (this.isDeletable(index, midIndex, lastIndex, this._distanceTol)) {
  16189. this._isDeleted[midIndex] = BufferInputLineSimplifier.DELETE;
  16190. isMiddleVertexDeleted = true;
  16191. isChanged = true;
  16192. }
  16193. if (isMiddleVertexDeleted) index = lastIndex;else index = midIndex;
  16194. midIndex = this.findNextNonDeletedIndex(index);
  16195. lastIndex = this.findNextNonDeletedIndex(midIndex);
  16196. }
  16197. return isChanged;
  16198. }
  16199. isShallowConcavity(p0, p1, p2, distanceTol) {
  16200. const orientation = Orientation.index(p0, p1, p2);
  16201. const isAngleToSimplify = orientation === this._angleOrientation;
  16202. if (!isAngleToSimplify) return false;
  16203. const dist = Distance.pointToSegment(p1, p0, p2);
  16204. return dist < distanceTol;
  16205. }
  16206. isShallowSampled(p0, p2, i0, i2, distanceTol) {
  16207. let inc = Math.trunc((i2 - i0) / BufferInputLineSimplifier.NUM_PTS_TO_CHECK);
  16208. if (inc <= 0) inc = 1;
  16209. for (let i = i0; i < i2; i += inc) if (!this.isShallow(p0, p2, this._inputLine[i], distanceTol)) return false;
  16210. return true;
  16211. }
  16212. isConcave(p0, p1, p2) {
  16213. const orientation = Orientation.index(p0, p1, p2);
  16214. const isConcave = orientation === this._angleOrientation;
  16215. return isConcave;
  16216. }
  16217. simplify(distanceTol) {
  16218. this._distanceTol = Math.abs(distanceTol);
  16219. if (distanceTol < 0) this._angleOrientation = Orientation.CLOCKWISE;
  16220. this._isDeleted = new Array(this._inputLine.length).fill(null);
  16221. let isChanged = false;
  16222. do isChanged = this.deleteShallowConcavities(); while (isChanged);
  16223. return this.collapseLine();
  16224. }
  16225. findNextNonDeletedIndex(index) {
  16226. let next = index + 1;
  16227. while (next < this._inputLine.length && this._isDeleted[next] === BufferInputLineSimplifier.DELETE) next++;
  16228. return next;
  16229. }
  16230. isShallow(p0, p1, p2, distanceTol) {
  16231. const dist = Distance.pointToSegment(p1, p0, p2);
  16232. return dist < distanceTol;
  16233. }
  16234. collapseLine() {
  16235. const coordList = new CoordinateList();
  16236. for (let i = 0; i < this._inputLine.length; i++) if (this._isDeleted[i] !== BufferInputLineSimplifier.DELETE) coordList.add(this._inputLine[i]);
  16237. return coordList.toCoordinateArray();
  16238. }
  16239. }
  16240. BufferInputLineSimplifier.INIT = 0;
  16241. BufferInputLineSimplifier.DELETE = 1;
  16242. BufferInputLineSimplifier.KEEP = 1;
  16243. BufferInputLineSimplifier.NUM_PTS_TO_CHECK = 10;
  16244. class OffsetSegmentString {
  16245. constructor() {
  16246. OffsetSegmentString.constructor_.apply(this, arguments);
  16247. }
  16248. static constructor_() {
  16249. this._ptList = null;
  16250. this._precisionModel = null;
  16251. this._minimimVertexDistance = 0.0;
  16252. this._ptList = new ArrayList();
  16253. }
  16254. getCoordinates() {
  16255. const coord = this._ptList.toArray(OffsetSegmentString.COORDINATE_ARRAY_TYPE);
  16256. return coord;
  16257. }
  16258. setPrecisionModel(precisionModel) {
  16259. this._precisionModel = precisionModel;
  16260. }
  16261. addPt(pt) {
  16262. const bufPt = new Coordinate(pt);
  16263. this._precisionModel.makePrecise(bufPt);
  16264. if (this.isRedundant(bufPt)) return null;
  16265. this._ptList.add(bufPt);
  16266. }
  16267. reverse() {}
  16268. addPts(pt, isForward) {
  16269. if (isForward) for (let i = 0; i < pt.length; i++) this.addPt(pt[i]);else for (let i = pt.length - 1; i >= 0; i--) this.addPt(pt[i]);
  16270. }
  16271. isRedundant(pt) {
  16272. if (this._ptList.size() < 1) return false;
  16273. const lastPt = this._ptList.get(this._ptList.size() - 1);
  16274. const ptDist = pt.distance(lastPt);
  16275. if (ptDist < this._minimimVertexDistance) return true;
  16276. return false;
  16277. }
  16278. toString() {
  16279. const fact = new GeometryFactory();
  16280. const line = fact.createLineString(this.getCoordinates());
  16281. return line.toString();
  16282. }
  16283. closeRing() {
  16284. if (this._ptList.size() < 1) return null;
  16285. const startPt = new Coordinate(this._ptList.get(0));
  16286. const lastPt = this._ptList.get(this._ptList.size() - 1);
  16287. if (startPt.equals(lastPt)) return null;
  16288. this._ptList.add(startPt);
  16289. }
  16290. setMinimumVertexDistance(minimimVertexDistance) {
  16291. this._minimimVertexDistance = minimimVertexDistance;
  16292. }
  16293. }
  16294. OffsetSegmentString.COORDINATE_ARRAY_TYPE = new Array(0).fill(null);
  16295. class OffsetSegmentGenerator {
  16296. constructor() {
  16297. OffsetSegmentGenerator.constructor_.apply(this, arguments);
  16298. }
  16299. static constructor_() {
  16300. this._maxCurveSegmentError = 0.0;
  16301. this._filletAngleQuantum = null;
  16302. this._closingSegLengthFactor = 1;
  16303. this._segList = null;
  16304. this._distance = 0.0;
  16305. this._precisionModel = null;
  16306. this._bufParams = null;
  16307. this._li = null;
  16308. this._s0 = null;
  16309. this._s1 = null;
  16310. this._s2 = null;
  16311. this._seg0 = new LineSegment();
  16312. this._seg1 = new LineSegment();
  16313. this._offset0 = new LineSegment();
  16314. this._offset1 = new LineSegment();
  16315. this._side = 0;
  16316. this._hasNarrowConcaveAngle = false;
  16317. const precisionModel = arguments[0],
  16318. bufParams = arguments[1],
  16319. distance = arguments[2];
  16320. this._precisionModel = precisionModel;
  16321. this._bufParams = bufParams;
  16322. this._li = new RobustLineIntersector();
  16323. this._filletAngleQuantum = Math.PI / 2.0 / bufParams.getQuadrantSegments();
  16324. if (bufParams.getQuadrantSegments() >= 8 && bufParams.getJoinStyle() === BufferParameters.JOIN_ROUND) this._closingSegLengthFactor = OffsetSegmentGenerator.MAX_CLOSING_SEG_LEN_FACTOR;
  16325. this.init(distance);
  16326. }
  16327. addNextSegment(p, addStartPoint) {
  16328. this._s0 = this._s1;
  16329. this._s1 = this._s2;
  16330. this._s2 = p;
  16331. this._seg0.setCoordinates(this._s0, this._s1);
  16332. this.computeOffsetSegment(this._seg0, this._side, this._distance, this._offset0);
  16333. this._seg1.setCoordinates(this._s1, this._s2);
  16334. this.computeOffsetSegment(this._seg1, this._side, this._distance, this._offset1);
  16335. if (this._s1.equals(this._s2)) return null;
  16336. const orientation = Orientation.index(this._s0, this._s1, this._s2);
  16337. const outsideTurn = orientation === Orientation.CLOCKWISE && this._side === Position.LEFT || orientation === Orientation.COUNTERCLOCKWISE && this._side === Position.RIGHT;
  16338. if (orientation === 0) this.addCollinear(addStartPoint);else if (outsideTurn) this.addOutsideTurn(orientation, addStartPoint);else this.addInsideTurn(orientation, addStartPoint);
  16339. }
  16340. addLineEndCap(p0, p1) {
  16341. const seg = new LineSegment(p0, p1);
  16342. const offsetL = new LineSegment();
  16343. this.computeOffsetSegment(seg, Position.LEFT, this._distance, offsetL);
  16344. const offsetR = new LineSegment();
  16345. this.computeOffsetSegment(seg, Position.RIGHT, this._distance, offsetR);
  16346. const dx = p1.x - p0.x;
  16347. const dy = p1.y - p0.y;
  16348. const angle = Math.atan2(dy, dx);
  16349. switch (this._bufParams.getEndCapStyle()) {
  16350. case BufferParameters.CAP_ROUND:
  16351. this._segList.addPt(offsetL.p1);
  16352. this.addDirectedFillet(p1, angle + Math.PI / 2, angle - Math.PI / 2, Orientation.CLOCKWISE, this._distance);
  16353. this._segList.addPt(offsetR.p1);
  16354. break;
  16355. case BufferParameters.CAP_FLAT:
  16356. this._segList.addPt(offsetL.p1);
  16357. this._segList.addPt(offsetR.p1);
  16358. break;
  16359. case BufferParameters.CAP_SQUARE:
  16360. const squareCapSideOffset = new Coordinate();
  16361. squareCapSideOffset.x = Math.abs(this._distance) * Math.cos(angle);
  16362. squareCapSideOffset.y = Math.abs(this._distance) * Math.sin(angle);
  16363. const squareCapLOffset = new Coordinate(offsetL.p1.x + squareCapSideOffset.x, offsetL.p1.y + squareCapSideOffset.y);
  16364. const squareCapROffset = new Coordinate(offsetR.p1.x + squareCapSideOffset.x, offsetR.p1.y + squareCapSideOffset.y);
  16365. this._segList.addPt(squareCapLOffset);
  16366. this._segList.addPt(squareCapROffset);
  16367. break;
  16368. }
  16369. }
  16370. getCoordinates() {
  16371. const pts = this._segList.getCoordinates();
  16372. return pts;
  16373. }
  16374. addMitreJoin(p, offset0, offset1, distance) {
  16375. const intPt = Intersection.intersection(offset0.p0, offset0.p1, offset1.p0, offset1.p1);
  16376. if (intPt !== null) {
  16377. const mitreRatio = distance <= 0.0 ? 1.0 : intPt.distance(p) / Math.abs(distance);
  16378. if (mitreRatio <= this._bufParams.getMitreLimit()) {
  16379. this._segList.addPt(intPt);
  16380. return null;
  16381. }
  16382. }
  16383. this.addLimitedMitreJoin(offset0, offset1, distance, this._bufParams.getMitreLimit());
  16384. }
  16385. addOutsideTurn(orientation, addStartPoint) {
  16386. if (this._offset0.p1.distance(this._offset1.p0) < this._distance * OffsetSegmentGenerator.OFFSET_SEGMENT_SEPARATION_FACTOR) {
  16387. this._segList.addPt(this._offset0.p1);
  16388. return null;
  16389. }
  16390. if (this._bufParams.getJoinStyle() === BufferParameters.JOIN_MITRE) {
  16391. this.addMitreJoin(this._s1, this._offset0, this._offset1, this._distance);
  16392. } else if (this._bufParams.getJoinStyle() === BufferParameters.JOIN_BEVEL) {
  16393. this.addBevelJoin(this._offset0, this._offset1);
  16394. } else {
  16395. if (addStartPoint) this._segList.addPt(this._offset0.p1);
  16396. this.addCornerFillet(this._s1, this._offset0.p1, this._offset1.p0, orientation, this._distance);
  16397. this._segList.addPt(this._offset1.p0);
  16398. }
  16399. }
  16400. createSquare(p) {
  16401. this._segList.addPt(new Coordinate(p.x + this._distance, p.y + this._distance));
  16402. this._segList.addPt(new Coordinate(p.x + this._distance, p.y - this._distance));
  16403. this._segList.addPt(new Coordinate(p.x - this._distance, p.y - this._distance));
  16404. this._segList.addPt(new Coordinate(p.x - this._distance, p.y + this._distance));
  16405. this._segList.closeRing();
  16406. }
  16407. addSegments(pt, isForward) {
  16408. this._segList.addPts(pt, isForward);
  16409. }
  16410. addFirstSegment() {
  16411. this._segList.addPt(this._offset1.p0);
  16412. }
  16413. addCornerFillet(p, p0, p1, direction, radius) {
  16414. const dx0 = p0.x - p.x;
  16415. const dy0 = p0.y - p.y;
  16416. let startAngle = Math.atan2(dy0, dx0);
  16417. const dx1 = p1.x - p.x;
  16418. const dy1 = p1.y - p.y;
  16419. const endAngle = Math.atan2(dy1, dx1);
  16420. if (direction === Orientation.CLOCKWISE) {
  16421. if (startAngle <= endAngle) startAngle += 2.0 * Math.PI;
  16422. } else {
  16423. if (startAngle >= endAngle) startAngle -= 2.0 * Math.PI;
  16424. }
  16425. this._segList.addPt(p0);
  16426. this.addDirectedFillet(p, startAngle, endAngle, direction, radius);
  16427. this._segList.addPt(p1);
  16428. }
  16429. addLastSegment() {
  16430. this._segList.addPt(this._offset1.p1);
  16431. }
  16432. initSideSegments(s1, s2, side) {
  16433. this._s1 = s1;
  16434. this._s2 = s2;
  16435. this._side = side;
  16436. this._seg1.setCoordinates(s1, s2);
  16437. this.computeOffsetSegment(this._seg1, side, this._distance, this._offset1);
  16438. }
  16439. addLimitedMitreJoin(offset0, offset1, distance, mitreLimit) {
  16440. const basePt = this._seg0.p1;
  16441. const ang0 = Angle.angle(basePt, this._seg0.p0);
  16442. const angDiff = Angle.angleBetweenOriented(this._seg0.p0, basePt, this._seg1.p1);
  16443. const angDiffHalf = angDiff / 2;
  16444. const midAng = Angle.normalize(ang0 + angDiffHalf);
  16445. const mitreMidAng = Angle.normalize(midAng + Math.PI);
  16446. const mitreDist = mitreLimit * distance;
  16447. const bevelDelta = mitreDist * Math.abs(Math.sin(angDiffHalf));
  16448. const bevelHalfLen = distance - bevelDelta;
  16449. const bevelMidX = basePt.x + mitreDist * Math.cos(mitreMidAng);
  16450. const bevelMidY = basePt.y + mitreDist * Math.sin(mitreMidAng);
  16451. const bevelMidPt = new Coordinate(bevelMidX, bevelMidY);
  16452. const mitreMidLine = new LineSegment(basePt, bevelMidPt);
  16453. const bevelEndLeft = mitreMidLine.pointAlongOffset(1.0, bevelHalfLen);
  16454. const bevelEndRight = mitreMidLine.pointAlongOffset(1.0, -bevelHalfLen);
  16455. if (this._side === Position.LEFT) {
  16456. this._segList.addPt(bevelEndLeft);
  16457. this._segList.addPt(bevelEndRight);
  16458. } else {
  16459. this._segList.addPt(bevelEndRight);
  16460. this._segList.addPt(bevelEndLeft);
  16461. }
  16462. }
  16463. addDirectedFillet(p, startAngle, endAngle, direction, radius) {
  16464. const directionFactor = direction === Orientation.CLOCKWISE ? -1 : 1;
  16465. const totalAngle = Math.abs(startAngle - endAngle);
  16466. const nSegs = Math.trunc(totalAngle / this._filletAngleQuantum + 0.5);
  16467. if (nSegs < 1) return null;
  16468. const angleInc = totalAngle / nSegs;
  16469. const pt = new Coordinate();
  16470. for (let i = 0; i < nSegs; i++) {
  16471. const angle = startAngle + directionFactor * i * angleInc;
  16472. pt.x = p.x + radius * Math.cos(angle);
  16473. pt.y = p.y + radius * Math.sin(angle);
  16474. this._segList.addPt(pt);
  16475. }
  16476. }
  16477. computeOffsetSegment(seg, side, distance, offset) {
  16478. const sideSign = side === Position.LEFT ? 1 : -1;
  16479. const dx = seg.p1.x - seg.p0.x;
  16480. const dy = seg.p1.y - seg.p0.y;
  16481. const len = Math.sqrt(dx * dx + dy * dy);
  16482. const ux = sideSign * distance * dx / len;
  16483. const uy = sideSign * distance * dy / len;
  16484. offset.p0.x = seg.p0.x - uy;
  16485. offset.p0.y = seg.p0.y + ux;
  16486. offset.p1.x = seg.p1.x - uy;
  16487. offset.p1.y = seg.p1.y + ux;
  16488. }
  16489. addInsideTurn(orientation, addStartPoint) {
  16490. this._li.computeIntersection(this._offset0.p0, this._offset0.p1, this._offset1.p0, this._offset1.p1);
  16491. if (this._li.hasIntersection()) {
  16492. this._segList.addPt(this._li.getIntersection(0));
  16493. } else {
  16494. this._hasNarrowConcaveAngle = true;
  16495. if (this._offset0.p1.distance(this._offset1.p0) < this._distance * OffsetSegmentGenerator.INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR) {
  16496. this._segList.addPt(this._offset0.p1);
  16497. } else {
  16498. this._segList.addPt(this._offset0.p1);
  16499. if (this._closingSegLengthFactor > 0) {
  16500. const 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));
  16501. this._segList.addPt(mid0);
  16502. const 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));
  16503. this._segList.addPt(mid1);
  16504. } else {
  16505. this._segList.addPt(this._s1);
  16506. }
  16507. this._segList.addPt(this._offset1.p0);
  16508. }
  16509. }
  16510. }
  16511. createCircle(p) {
  16512. const pt = new Coordinate(p.x + this._distance, p.y);
  16513. this._segList.addPt(pt);
  16514. this.addDirectedFillet(p, 0.0, 2.0 * Math.PI, -1, this._distance);
  16515. this._segList.closeRing();
  16516. }
  16517. addBevelJoin(offset0, offset1) {
  16518. this._segList.addPt(offset0.p1);
  16519. this._segList.addPt(offset1.p0);
  16520. }
  16521. init(distance) {
  16522. this._distance = distance;
  16523. this._maxCurveSegmentError = distance * (1 - Math.cos(this._filletAngleQuantum / 2.0));
  16524. this._segList = new OffsetSegmentString();
  16525. this._segList.setPrecisionModel(this._precisionModel);
  16526. this._segList.setMinimumVertexDistance(distance * OffsetSegmentGenerator.CURVE_VERTEX_SNAP_DISTANCE_FACTOR);
  16527. }
  16528. addCollinear(addStartPoint) {
  16529. this._li.computeIntersection(this._s0, this._s1, this._s1, this._s2);
  16530. const numInt = this._li.getIntersectionNum();
  16531. if (numInt >= 2) if (this._bufParams.getJoinStyle() === BufferParameters.JOIN_BEVEL || this._bufParams.getJoinStyle() === BufferParameters.JOIN_MITRE) {
  16532. if (addStartPoint) this._segList.addPt(this._offset0.p1);
  16533. this._segList.addPt(this._offset1.p0);
  16534. } else {
  16535. this.addCornerFillet(this._s1, this._offset0.p1, this._offset1.p0, Orientation.CLOCKWISE, this._distance);
  16536. }
  16537. }
  16538. closeRing() {
  16539. this._segList.closeRing();
  16540. }
  16541. hasNarrowConcaveAngle() {
  16542. return this._hasNarrowConcaveAngle;
  16543. }
  16544. }
  16545. OffsetSegmentGenerator.OFFSET_SEGMENT_SEPARATION_FACTOR = 1.0E-3;
  16546. OffsetSegmentGenerator.INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR = 1.0E-3;
  16547. OffsetSegmentGenerator.CURVE_VERTEX_SNAP_DISTANCE_FACTOR = 1.0E-6;
  16548. OffsetSegmentGenerator.MAX_CLOSING_SEG_LEN_FACTOR = 80;
  16549. class OffsetCurveBuilder {
  16550. constructor() {
  16551. OffsetCurveBuilder.constructor_.apply(this, arguments);
  16552. }
  16553. static constructor_() {
  16554. this._distance = 0.0;
  16555. this._precisionModel = null;
  16556. this._bufParams = null;
  16557. const precisionModel = arguments[0],
  16558. bufParams = arguments[1];
  16559. this._precisionModel = precisionModel;
  16560. this._bufParams = bufParams;
  16561. }
  16562. static copyCoordinates(pts) {
  16563. const copy = new Array(pts.length).fill(null);
  16564. for (let i = 0; i < copy.length; i++) copy[i] = new Coordinate(pts[i]);
  16565. return copy;
  16566. }
  16567. getOffsetCurve(inputPts, distance) {
  16568. this._distance = distance;
  16569. if (distance === 0.0) return null;
  16570. const isRightSide = distance < 0.0;
  16571. const posDistance = Math.abs(distance);
  16572. const segGen = this.getSegGen(posDistance);
  16573. if (inputPts.length <= 1) this.computePointCurve(inputPts[0], segGen);else this.computeOffsetCurve(inputPts, isRightSide, segGen);
  16574. const curvePts = segGen.getCoordinates();
  16575. if (isRightSide) CoordinateArrays.reverse(curvePts);
  16576. return curvePts;
  16577. }
  16578. computeSingleSidedBufferCurve(inputPts, isRightSide, segGen) {
  16579. const distTol = this.simplifyTolerance(this._distance);
  16580. if (isRightSide) {
  16581. segGen.addSegments(inputPts, true);
  16582. const simp2 = BufferInputLineSimplifier.simplify(inputPts, -distTol);
  16583. const n2 = simp2.length - 1;
  16584. segGen.initSideSegments(simp2[n2], simp2[n2 - 1], Position.LEFT);
  16585. segGen.addFirstSegment();
  16586. for (let i = n2 - 2; i >= 0; i--) segGen.addNextSegment(simp2[i], true);
  16587. } else {
  16588. segGen.addSegments(inputPts, false);
  16589. const simp1 = BufferInputLineSimplifier.simplify(inputPts, distTol);
  16590. const n1 = simp1.length - 1;
  16591. segGen.initSideSegments(simp1[0], simp1[1], Position.LEFT);
  16592. segGen.addFirstSegment();
  16593. for (let i = 2; i <= n1; i++) segGen.addNextSegment(simp1[i], true);
  16594. }
  16595. segGen.addLastSegment();
  16596. segGen.closeRing();
  16597. }
  16598. computeRingBufferCurve(inputPts, side, segGen) {
  16599. let distTol = this.simplifyTolerance(this._distance);
  16600. if (side === Position.RIGHT) distTol = -distTol;
  16601. const simp = BufferInputLineSimplifier.simplify(inputPts, distTol);
  16602. const n = simp.length - 1;
  16603. segGen.initSideSegments(simp[n - 1], simp[0], side);
  16604. for (let i = 1; i <= n; i++) {
  16605. const addStartPoint = i !== 1;
  16606. segGen.addNextSegment(simp[i], addStartPoint);
  16607. }
  16608. segGen.closeRing();
  16609. }
  16610. computeLineBufferCurve(inputPts, segGen) {
  16611. const distTol = this.simplifyTolerance(this._distance);
  16612. const simp1 = BufferInputLineSimplifier.simplify(inputPts, distTol);
  16613. const n1 = simp1.length - 1;
  16614. segGen.initSideSegments(simp1[0], simp1[1], Position.LEFT);
  16615. for (let i = 2; i <= n1; i++) segGen.addNextSegment(simp1[i], true);
  16616. segGen.addLastSegment();
  16617. segGen.addLineEndCap(simp1[n1 - 1], simp1[n1]);
  16618. const simp2 = BufferInputLineSimplifier.simplify(inputPts, -distTol);
  16619. const n2 = simp2.length - 1;
  16620. segGen.initSideSegments(simp2[n2], simp2[n2 - 1], Position.LEFT);
  16621. for (let i = n2 - 2; i >= 0; i--) segGen.addNextSegment(simp2[i], true);
  16622. segGen.addLastSegment();
  16623. segGen.addLineEndCap(simp2[1], simp2[0]);
  16624. segGen.closeRing();
  16625. }
  16626. computePointCurve(pt, segGen) {
  16627. switch (this._bufParams.getEndCapStyle()) {
  16628. case BufferParameters.CAP_ROUND:
  16629. segGen.createCircle(pt);
  16630. break;
  16631. case BufferParameters.CAP_SQUARE:
  16632. segGen.createSquare(pt);
  16633. break;
  16634. }
  16635. }
  16636. getLineCurve(inputPts, distance) {
  16637. this._distance = distance;
  16638. if (this.isLineOffsetEmpty(distance)) return null;
  16639. const posDistance = Math.abs(distance);
  16640. const segGen = this.getSegGen(posDistance);
  16641. if (inputPts.length <= 1) {
  16642. this.computePointCurve(inputPts[0], segGen);
  16643. } else if (this._bufParams.isSingleSided()) {
  16644. const isRightSide = distance < 0.0;
  16645. this.computeSingleSidedBufferCurve(inputPts, isRightSide, segGen);
  16646. } else {
  16647. this.computeLineBufferCurve(inputPts, segGen);
  16648. }
  16649. const lineCoord = segGen.getCoordinates();
  16650. return lineCoord;
  16651. }
  16652. getBufferParameters() {
  16653. return this._bufParams;
  16654. }
  16655. simplifyTolerance(bufDistance) {
  16656. return bufDistance * this._bufParams.getSimplifyFactor();
  16657. }
  16658. getRingCurve(inputPts, side, distance) {
  16659. this._distance = distance;
  16660. if (inputPts.length <= 2) return this.getLineCurve(inputPts, distance);
  16661. if (distance === 0.0) return OffsetCurveBuilder.copyCoordinates(inputPts);
  16662. const segGen = this.getSegGen(distance);
  16663. this.computeRingBufferCurve(inputPts, side, segGen);
  16664. return segGen.getCoordinates();
  16665. }
  16666. computeOffsetCurve(inputPts, isRightSide, segGen) {
  16667. const distTol = this.simplifyTolerance(this._distance);
  16668. if (isRightSide) {
  16669. const simp2 = BufferInputLineSimplifier.simplify(inputPts, -distTol);
  16670. const n2 = simp2.length - 1;
  16671. segGen.initSideSegments(simp2[n2], simp2[n2 - 1], Position.LEFT);
  16672. segGen.addFirstSegment();
  16673. for (let i = n2 - 2; i >= 0; i--) segGen.addNextSegment(simp2[i], true);
  16674. } else {
  16675. const simp1 = BufferInputLineSimplifier.simplify(inputPts, distTol);
  16676. const n1 = simp1.length - 1;
  16677. segGen.initSideSegments(simp1[0], simp1[1], Position.LEFT);
  16678. segGen.addFirstSegment();
  16679. for (let i = 2; i <= n1; i++) segGen.addNextSegment(simp1[i], true);
  16680. }
  16681. segGen.addLastSegment();
  16682. }
  16683. isLineOffsetEmpty(distance) {
  16684. if (distance === 0.0) return true;
  16685. if (distance < 0.0 && !this._bufParams.isSingleSided()) return true;
  16686. return false;
  16687. }
  16688. getSegGen(distance) {
  16689. return new OffsetSegmentGenerator(this._precisionModel, this._bufParams, distance);
  16690. }
  16691. }
  16692. class SubgraphDepthLocater {
  16693. constructor() {
  16694. SubgraphDepthLocater.constructor_.apply(this, arguments);
  16695. }
  16696. static constructor_() {
  16697. this._subgraphs = null;
  16698. this._seg = new LineSegment();
  16699. const subgraphs = arguments[0];
  16700. this._subgraphs = subgraphs;
  16701. }
  16702. findStabbedSegments() {
  16703. if (arguments.length === 1) {
  16704. const stabbingRayLeftPt = arguments[0];
  16705. const stabbedSegments = new ArrayList();
  16706. for (let i = this._subgraphs.iterator(); i.hasNext();) {
  16707. const bsg = i.next();
  16708. const env = bsg.getEnvelope();
  16709. if (stabbingRayLeftPt.y < env.getMinY() || stabbingRayLeftPt.y > env.getMaxY()) continue;
  16710. this.findStabbedSegments(stabbingRayLeftPt, bsg.getDirectedEdges(), stabbedSegments);
  16711. }
  16712. return stabbedSegments;
  16713. } else if (arguments.length === 3) {
  16714. if (hasInterface(arguments[2], List) && arguments[0] instanceof Coordinate && arguments[1] instanceof DirectedEdge$1) {
  16715. const stabbingRayLeftPt = arguments[0],
  16716. dirEdge = arguments[1],
  16717. stabbedSegments = arguments[2];
  16718. const pts = dirEdge.getEdge().getCoordinates();
  16719. for (let i = 0; i < pts.length - 1; i++) {
  16720. this._seg.p0 = pts[i];
  16721. this._seg.p1 = pts[i + 1];
  16722. if (this._seg.p0.y > this._seg.p1.y) this._seg.reverse();
  16723. const maxx = Math.max(this._seg.p0.x, this._seg.p1.x);
  16724. if (maxx < stabbingRayLeftPt.x) continue;
  16725. if (this._seg.isHorizontal()) continue;
  16726. if (stabbingRayLeftPt.y < this._seg.p0.y || stabbingRayLeftPt.y > this._seg.p1.y) continue;
  16727. if (Orientation.index(this._seg.p0, this._seg.p1, stabbingRayLeftPt) === Orientation.RIGHT) continue;
  16728. let depth = dirEdge.getDepth(Position.LEFT);
  16729. if (!this._seg.p0.equals(pts[i])) depth = dirEdge.getDepth(Position.RIGHT);
  16730. const ds = new DepthSegment(this._seg, depth);
  16731. stabbedSegments.add(ds);
  16732. }
  16733. } else if (hasInterface(arguments[2], List) && arguments[0] instanceof Coordinate && hasInterface(arguments[1], List)) {
  16734. const stabbingRayLeftPt = arguments[0],
  16735. dirEdges = arguments[1],
  16736. stabbedSegments = arguments[2];
  16737. for (let i = dirEdges.iterator(); i.hasNext();) {
  16738. const de = i.next();
  16739. if (!de.isForward()) continue;
  16740. this.findStabbedSegments(stabbingRayLeftPt, de, stabbedSegments);
  16741. }
  16742. }
  16743. }
  16744. }
  16745. getDepth(p) {
  16746. const stabbedSegments = this.findStabbedSegments(p);
  16747. if (stabbedSegments.size() === 0) return 0;
  16748. const ds = Collections.min(stabbedSegments);
  16749. return ds._leftDepth;
  16750. }
  16751. }
  16752. class DepthSegment {
  16753. constructor() {
  16754. DepthSegment.constructor_.apply(this, arguments);
  16755. }
  16756. static constructor_() {
  16757. this._upwardSeg = null;
  16758. this._leftDepth = null;
  16759. const seg = arguments[0],
  16760. depth = arguments[1];
  16761. this._upwardSeg = new LineSegment(seg);
  16762. this._leftDepth = depth;
  16763. }
  16764. compareTo(obj) {
  16765. const other = obj;
  16766. if (this._upwardSeg.minX() >= other._upwardSeg.maxX()) return 1;
  16767. if (this._upwardSeg.maxX() <= other._upwardSeg.minX()) return -1;
  16768. let orientIndex = this._upwardSeg.orientationIndex(other._upwardSeg);
  16769. if (orientIndex !== 0) return orientIndex;
  16770. orientIndex = -1 * other._upwardSeg.orientationIndex(this._upwardSeg);
  16771. if (orientIndex !== 0) return orientIndex;
  16772. return this._upwardSeg.compareTo(other._upwardSeg);
  16773. }
  16774. compareX(seg0, seg1) {
  16775. const compare0 = seg0.p0.compareTo(seg1.p0);
  16776. if (compare0 !== 0) return compare0;
  16777. return seg0.p1.compareTo(seg1.p1);
  16778. }
  16779. toString() {
  16780. return this._upwardSeg.toString();
  16781. }
  16782. get interfaces_() {
  16783. return [Comparable];
  16784. }
  16785. }
  16786. SubgraphDepthLocater.DepthSegment = DepthSegment;
  16787. class OffsetCurveSetBuilder {
  16788. constructor() {
  16789. OffsetCurveSetBuilder.constructor_.apply(this, arguments);
  16790. }
  16791. static constructor_() {
  16792. this._inputGeom = null;
  16793. this._distance = null;
  16794. this._curveBuilder = null;
  16795. this._curveList = new ArrayList();
  16796. const inputGeom = arguments[0],
  16797. distance = arguments[1],
  16798. curveBuilder = arguments[2];
  16799. this._inputGeom = inputGeom;
  16800. this._distance = distance;
  16801. this._curveBuilder = curveBuilder;
  16802. }
  16803. addRingSide(coord, offsetDistance, side, cwLeftLoc, cwRightLoc) {
  16804. if (offsetDistance === 0.0 && coord.length < LinearRing.MINIMUM_VALID_SIZE) return null;
  16805. let leftLoc = cwLeftLoc;
  16806. let rightLoc = cwRightLoc;
  16807. if (coord.length >= LinearRing.MINIMUM_VALID_SIZE && Orientation.isCCW(coord)) {
  16808. leftLoc = cwRightLoc;
  16809. rightLoc = cwLeftLoc;
  16810. side = Position.opposite(side);
  16811. }
  16812. const curve = this._curveBuilder.getRingCurve(coord, side, offsetDistance);
  16813. this.addCurve(curve, leftLoc, rightLoc);
  16814. }
  16815. addRingBothSides(coord, distance) {
  16816. this.addRingSide(coord, distance, Position.LEFT, Location.EXTERIOR, Location.INTERIOR);
  16817. this.addRingSide(coord, distance, Position.RIGHT, Location.INTERIOR, Location.EXTERIOR);
  16818. }
  16819. addPoint(p) {
  16820. if (this._distance <= 0.0) return null;
  16821. const coord = p.getCoordinates();
  16822. const curve = this._curveBuilder.getLineCurve(coord, this._distance);
  16823. this.addCurve(curve, Location.EXTERIOR, Location.INTERIOR);
  16824. }
  16825. addPolygon(p) {
  16826. let offsetDistance = this._distance;
  16827. let offsetSide = Position.LEFT;
  16828. if (this._distance < 0.0) {
  16829. offsetDistance = -this._distance;
  16830. offsetSide = Position.RIGHT;
  16831. }
  16832. const shell = p.getExteriorRing();
  16833. const shellCoord = CoordinateArrays.removeRepeatedPoints(shell.getCoordinates());
  16834. if (this._distance < 0.0 && this.isErodedCompletely(shell, this._distance)) return null;
  16835. if (this._distance <= 0.0 && shellCoord.length < 3) return null;
  16836. this.addRingSide(shellCoord, offsetDistance, offsetSide, Location.EXTERIOR, Location.INTERIOR);
  16837. for (let i = 0; i < p.getNumInteriorRing(); i++) {
  16838. const hole = p.getInteriorRingN(i);
  16839. const holeCoord = CoordinateArrays.removeRepeatedPoints(hole.getCoordinates());
  16840. if (this._distance > 0.0 && this.isErodedCompletely(hole, -this._distance)) continue;
  16841. this.addRingSide(holeCoord, offsetDistance, Position.opposite(offsetSide), Location.INTERIOR, Location.EXTERIOR);
  16842. }
  16843. }
  16844. isTriangleErodedCompletely(triangleCoord, bufferDistance) {
  16845. const tri = new Triangle(triangleCoord[0], triangleCoord[1], triangleCoord[2]);
  16846. const inCentre = tri.inCentre();
  16847. const distToCentre = Distance.pointToSegment(inCentre, tri.p0, tri.p1);
  16848. return distToCentre < Math.abs(bufferDistance);
  16849. }
  16850. addLineString(line) {
  16851. if (this._curveBuilder.isLineOffsetEmpty(this._distance)) return null;
  16852. const coord = CoordinateArrays.removeRepeatedPoints(line.getCoordinates());
  16853. if (CoordinateArrays.isRing(coord) && !this._curveBuilder.getBufferParameters().isSingleSided()) {
  16854. this.addRingBothSides(coord, this._distance);
  16855. } else {
  16856. const curve = this._curveBuilder.getLineCurve(coord, this._distance);
  16857. this.addCurve(curve, Location.EXTERIOR, Location.INTERIOR);
  16858. }
  16859. }
  16860. addCurve(coord, leftLoc, rightLoc) {
  16861. if (coord === null || coord.length < 2) return null;
  16862. const e = new NodedSegmentString(coord, new Label(0, Location.BOUNDARY, leftLoc, rightLoc));
  16863. this._curveList.add(e);
  16864. }
  16865. getCurves() {
  16866. this.add(this._inputGeom);
  16867. return this._curveList;
  16868. }
  16869. add(g) {
  16870. if (g.isEmpty()) return null;
  16871. if (g instanceof Polygon) this.addPolygon(g);else if (g instanceof LineString) this.addLineString(g);else if (g instanceof Point) this.addPoint(g);else if (g instanceof MultiPoint) this.addCollection(g);else if (g instanceof MultiLineString) this.addCollection(g);else if (g instanceof MultiPolygon) this.addCollection(g);else if (g instanceof GeometryCollection) this.addCollection(g);else throw new UnsupportedOperationException(g.getGeometryType());
  16872. }
  16873. isErodedCompletely(ring, bufferDistance) {
  16874. const ringCoord = ring.getCoordinates();
  16875. if (ringCoord.length < 4) return bufferDistance < 0;
  16876. if (ringCoord.length === 4) return this.isTriangleErodedCompletely(ringCoord, bufferDistance);
  16877. const env = ring.getEnvelopeInternal();
  16878. const envMinDimension = Math.min(env.getHeight(), env.getWidth());
  16879. if (bufferDistance < 0.0 && 2 * Math.abs(bufferDistance) > envMinDimension) return true;
  16880. return false;
  16881. }
  16882. addCollection(gc) {
  16883. for (let i = 0; i < gc.getNumGeometries(); i++) {
  16884. const g = gc.getGeometryN(i);
  16885. this.add(g);
  16886. }
  16887. }
  16888. }
  16889. class EdgeEndStar {
  16890. constructor() {
  16891. EdgeEndStar.constructor_.apply(this, arguments);
  16892. }
  16893. static constructor_() {
  16894. this._edgeMap = new TreeMap();
  16895. this._edgeList = null;
  16896. this._ptInAreaLocation = [Location.NONE, Location.NONE];
  16897. }
  16898. getNextCW(ee) {
  16899. this.getEdges();
  16900. const i = this._edgeList.indexOf(ee);
  16901. let iNextCW = i - 1;
  16902. if (i === 0) iNextCW = this._edgeList.size() - 1;
  16903. return this._edgeList.get(iNextCW);
  16904. }
  16905. propagateSideLabels(geomIndex) {
  16906. let startLoc = Location.NONE;
  16907. for (let it = this.iterator(); it.hasNext();) {
  16908. const e = it.next();
  16909. const label = e.getLabel();
  16910. if (label.isArea(geomIndex) && label.getLocation(geomIndex, Position.LEFT) !== Location.NONE) startLoc = label.getLocation(geomIndex, Position.LEFT);
  16911. }
  16912. if (startLoc === Location.NONE) return null;
  16913. let currLoc = startLoc;
  16914. for (let it = this.iterator(); it.hasNext();) {
  16915. const e = it.next();
  16916. const label = e.getLabel();
  16917. if (label.getLocation(geomIndex, Position.ON) === Location.NONE) label.setLocation(geomIndex, Position.ON, currLoc);
  16918. if (label.isArea(geomIndex)) {
  16919. const leftLoc = label.getLocation(geomIndex, Position.LEFT);
  16920. const rightLoc = label.getLocation(geomIndex, Position.RIGHT);
  16921. if (rightLoc !== Location.NONE) {
  16922. if (rightLoc !== currLoc) throw new TopologyException('side location conflict', e.getCoordinate());
  16923. if (leftLoc === Location.NONE) Assert.shouldNeverReachHere('found single null side (at ' + e.getCoordinate() + ')');
  16924. currLoc = leftLoc;
  16925. } else {
  16926. Assert.isTrue(label.getLocation(geomIndex, Position.LEFT) === Location.NONE, 'found single null side');
  16927. label.setLocation(geomIndex, Position.RIGHT, currLoc);
  16928. label.setLocation(geomIndex, Position.LEFT, currLoc);
  16929. }
  16930. }
  16931. }
  16932. }
  16933. getCoordinate() {
  16934. const it = this.iterator();
  16935. if (!it.hasNext()) return null;
  16936. const e = it.next();
  16937. return e.getCoordinate();
  16938. }
  16939. print(out) {
  16940. System.out.println('EdgeEndStar: ' + this.getCoordinate());
  16941. for (let it = this.iterator(); it.hasNext();) {
  16942. const e = it.next();
  16943. e.print(out);
  16944. }
  16945. }
  16946. isAreaLabelsConsistent(geomGraph) {
  16947. this.computeEdgeEndLabels(geomGraph.getBoundaryNodeRule());
  16948. return this.checkAreaLabelsConsistent(0);
  16949. }
  16950. checkAreaLabelsConsistent(geomIndex) {
  16951. const edges = this.getEdges();
  16952. if (edges.size() <= 0) return true;
  16953. const lastEdgeIndex = edges.size() - 1;
  16954. const startLabel = edges.get(lastEdgeIndex).getLabel();
  16955. const startLoc = startLabel.getLocation(geomIndex, Position.LEFT);
  16956. Assert.isTrue(startLoc !== Location.NONE, 'Found unlabelled area edge');
  16957. let currLoc = startLoc;
  16958. for (let it = this.iterator(); it.hasNext();) {
  16959. const e = it.next();
  16960. const label = e.getLabel();
  16961. Assert.isTrue(label.isArea(geomIndex), 'Found non-area edge');
  16962. const leftLoc = label.getLocation(geomIndex, Position.LEFT);
  16963. const rightLoc = label.getLocation(geomIndex, Position.RIGHT);
  16964. if (leftLoc === rightLoc) return false;
  16965. if (rightLoc !== currLoc) return false;
  16966. currLoc = leftLoc;
  16967. }
  16968. return true;
  16969. }
  16970. findIndex(eSearch) {
  16971. this.iterator();
  16972. for (let i = 0; i < this._edgeList.size(); i++) {
  16973. const e = this._edgeList.get(i);
  16974. if (e === eSearch) return i;
  16975. }
  16976. return -1;
  16977. }
  16978. iterator() {
  16979. return this.getEdges().iterator();
  16980. }
  16981. getEdges() {
  16982. if (this._edgeList === null) this._edgeList = new ArrayList(this._edgeMap.values());
  16983. return this._edgeList;
  16984. }
  16985. getLocation(geomIndex, p, geom) {
  16986. if (this._ptInAreaLocation[geomIndex] === Location.NONE) this._ptInAreaLocation[geomIndex] = SimplePointInAreaLocator.locate(p, geom[geomIndex].getGeometry());
  16987. return this._ptInAreaLocation[geomIndex];
  16988. }
  16989. toString() {
  16990. const buf = new StringBuffer();
  16991. buf.append('EdgeEndStar: ' + this.getCoordinate());
  16992. buf.append('\n');
  16993. for (let it = this.iterator(); it.hasNext();) {
  16994. const e = it.next();
  16995. buf.append(e);
  16996. buf.append('\n');
  16997. }
  16998. return buf.toString();
  16999. }
  17000. computeEdgeEndLabels(boundaryNodeRule) {
  17001. for (let it = this.iterator(); it.hasNext();) {
  17002. const ee = it.next();
  17003. ee.computeLabel(boundaryNodeRule);
  17004. }
  17005. }
  17006. computeLabelling(geomGraph) {
  17007. this.computeEdgeEndLabels(geomGraph[0].getBoundaryNodeRule());
  17008. this.propagateSideLabels(0);
  17009. this.propagateSideLabels(1);
  17010. const hasDimensionalCollapseEdge = [false, false];
  17011. for (let it = this.iterator(); it.hasNext();) {
  17012. const e = it.next();
  17013. const label = e.getLabel();
  17014. for (let geomi = 0; geomi < 2; geomi++) if (label.isLine(geomi) && label.getLocation(geomi) === Location.BOUNDARY) hasDimensionalCollapseEdge[geomi] = true;
  17015. }
  17016. for (let it = this.iterator(); it.hasNext();) {
  17017. const e = it.next();
  17018. const label = e.getLabel();
  17019. for (let geomi = 0; geomi < 2; geomi++) if (label.isAnyNull(geomi)) {
  17020. let loc = Location.NONE;
  17021. if (hasDimensionalCollapseEdge[geomi]) {
  17022. loc = Location.EXTERIOR;
  17023. } else {
  17024. const p = e.getCoordinate();
  17025. loc = this.getLocation(geomi, p, geomGraph);
  17026. }
  17027. label.setAllLocationsIfNull(geomi, loc);
  17028. }
  17029. }
  17030. }
  17031. getDegree() {
  17032. return this._edgeMap.size();
  17033. }
  17034. insertEdgeEnd(e, obj) {
  17035. this._edgeMap.put(e, obj);
  17036. this._edgeList = null;
  17037. }
  17038. }
  17039. class DirectedEdgeStar$1 extends EdgeEndStar {
  17040. constructor() {
  17041. super();
  17042. DirectedEdgeStar$1.constructor_.apply(this, arguments);
  17043. }
  17044. static constructor_() {
  17045. this._resultAreaEdgeList = null;
  17046. this._label = null;
  17047. this._SCANNING_FOR_INCOMING = 1;
  17048. this._LINKING_TO_OUTGOING = 2;
  17049. }
  17050. linkResultDirectedEdges() {
  17051. this.getResultAreaEdges();
  17052. let firstOut = null;
  17053. let incoming = null;
  17054. let state = this._SCANNING_FOR_INCOMING;
  17055. for (let i = 0; i < this._resultAreaEdgeList.size(); i++) {
  17056. const nextOut = this._resultAreaEdgeList.get(i);
  17057. const nextIn = nextOut.getSym();
  17058. if (!nextOut.getLabel().isArea()) continue;
  17059. if (firstOut === null && nextOut.isInResult()) firstOut = nextOut;
  17060. switch (state) {
  17061. case this._SCANNING_FOR_INCOMING:
  17062. if (!nextIn.isInResult()) continue;
  17063. incoming = nextIn;
  17064. state = this._LINKING_TO_OUTGOING;
  17065. break;
  17066. case this._LINKING_TO_OUTGOING:
  17067. if (!nextOut.isInResult()) continue;
  17068. incoming.setNext(nextOut);
  17069. state = this._SCANNING_FOR_INCOMING;
  17070. break;
  17071. }
  17072. }
  17073. if (state === this._LINKING_TO_OUTGOING) {
  17074. if (firstOut === null) throw new TopologyException('no outgoing dirEdge found', this.getCoordinate());
  17075. Assert.isTrue(firstOut.isInResult(), 'unable to link last incoming dirEdge');
  17076. incoming.setNext(firstOut);
  17077. }
  17078. }
  17079. insert(ee) {
  17080. const de = ee;
  17081. this.insertEdgeEnd(de, de);
  17082. }
  17083. getRightmostEdge() {
  17084. const edges = this.getEdges();
  17085. const size = edges.size();
  17086. if (size < 1) return null;
  17087. const de0 = edges.get(0);
  17088. if (size === 1) return de0;
  17089. const deLast = edges.get(size - 1);
  17090. const quad0 = de0.getQuadrant();
  17091. const quad1 = deLast.getQuadrant();
  17092. if (Quadrant.isNorthern(quad0) && Quadrant.isNorthern(quad1)) {
  17093. return de0;
  17094. } else if (!Quadrant.isNorthern(quad0) && !Quadrant.isNorthern(quad1)) {
  17095. return deLast;
  17096. } else {
  17097. if (de0.getDy() !== 0) return de0;else if (deLast.getDy() !== 0) return deLast;
  17098. }
  17099. Assert.shouldNeverReachHere('found two horizontal edges incident on node');
  17100. return null;
  17101. }
  17102. print(out) {
  17103. System.out.println('DirectedEdgeStar: ' + this.getCoordinate());
  17104. for (let it = this.iterator(); it.hasNext();) {
  17105. const de = it.next();
  17106. out.print('out ');
  17107. de.print(out);
  17108. out.println();
  17109. out.print('in ');
  17110. de.getSym().print(out);
  17111. out.println();
  17112. }
  17113. }
  17114. getResultAreaEdges() {
  17115. if (this._resultAreaEdgeList !== null) return this._resultAreaEdgeList;
  17116. this._resultAreaEdgeList = new ArrayList();
  17117. for (let it = this.iterator(); it.hasNext();) {
  17118. const de = it.next();
  17119. if (de.isInResult() || de.getSym().isInResult()) this._resultAreaEdgeList.add(de);
  17120. }
  17121. return this._resultAreaEdgeList;
  17122. }
  17123. updateLabelling(nodeLabel) {
  17124. for (let it = this.iterator(); it.hasNext();) {
  17125. const de = it.next();
  17126. const label = de.getLabel();
  17127. label.setAllLocationsIfNull(0, nodeLabel.getLocation(0));
  17128. label.setAllLocationsIfNull(1, nodeLabel.getLocation(1));
  17129. }
  17130. }
  17131. linkAllDirectedEdges() {
  17132. this.getEdges();
  17133. let prevOut = null;
  17134. let firstIn = null;
  17135. for (let i = this._edgeList.size() - 1; i >= 0; i--) {
  17136. const nextOut = this._edgeList.get(i);
  17137. const nextIn = nextOut.getSym();
  17138. if (firstIn === null) firstIn = nextIn;
  17139. if (prevOut !== null) nextIn.setNext(prevOut);
  17140. prevOut = nextOut;
  17141. }
  17142. firstIn.setNext(prevOut);
  17143. }
  17144. computeDepths() {
  17145. if (arguments.length === 1) {
  17146. const de = arguments[0];
  17147. const edgeIndex = this.findIndex(de);
  17148. const startDepth = de.getDepth(Position.LEFT);
  17149. const targetLastDepth = de.getDepth(Position.RIGHT);
  17150. const nextDepth = this.computeDepths(edgeIndex + 1, this._edgeList.size(), startDepth);
  17151. const lastDepth = this.computeDepths(0, edgeIndex, nextDepth);
  17152. if (lastDepth !== targetLastDepth) throw new TopologyException('depth mismatch at ' + de.getCoordinate());
  17153. } else if (arguments.length === 3) {
  17154. const startIndex = arguments[0],
  17155. endIndex = arguments[1],
  17156. startDepth = arguments[2];
  17157. let currDepth = startDepth;
  17158. for (let i = startIndex; i < endIndex; i++) {
  17159. const nextDe = this._edgeList.get(i);
  17160. nextDe.setEdgeDepths(Position.RIGHT, currDepth);
  17161. currDepth = nextDe.getDepth(Position.LEFT);
  17162. }
  17163. return currDepth;
  17164. }
  17165. }
  17166. mergeSymLabels() {
  17167. for (let it = this.iterator(); it.hasNext();) {
  17168. const de = it.next();
  17169. const label = de.getLabel();
  17170. label.merge(de.getSym().getLabel());
  17171. }
  17172. }
  17173. linkMinimalDirectedEdges(er) {
  17174. let firstOut = null;
  17175. let incoming = null;
  17176. let state = this._SCANNING_FOR_INCOMING;
  17177. for (let i = this._resultAreaEdgeList.size() - 1; i >= 0; i--) {
  17178. const nextOut = this._resultAreaEdgeList.get(i);
  17179. const nextIn = nextOut.getSym();
  17180. if (firstOut === null && nextOut.getEdgeRing() === er) firstOut = nextOut;
  17181. switch (state) {
  17182. case this._SCANNING_FOR_INCOMING:
  17183. if (nextIn.getEdgeRing() !== er) continue;
  17184. incoming = nextIn;
  17185. state = this._LINKING_TO_OUTGOING;
  17186. break;
  17187. case this._LINKING_TO_OUTGOING:
  17188. if (nextOut.getEdgeRing() !== er) continue;
  17189. incoming.setNextMin(nextOut);
  17190. state = this._SCANNING_FOR_INCOMING;
  17191. break;
  17192. }
  17193. }
  17194. if (state === this._LINKING_TO_OUTGOING) {
  17195. Assert.isTrue(firstOut !== null, 'found null for first outgoing dirEdge');
  17196. Assert.isTrue(firstOut.getEdgeRing() === er, 'unable to link last incoming dirEdge');
  17197. incoming.setNextMin(firstOut);
  17198. }
  17199. }
  17200. getOutgoingDegree() {
  17201. if (arguments.length === 0) {
  17202. let degree = 0;
  17203. for (let it = this.iterator(); it.hasNext();) {
  17204. const de = it.next();
  17205. if (de.isInResult()) degree++;
  17206. }
  17207. return degree;
  17208. } else if (arguments.length === 1) {
  17209. const er = arguments[0];
  17210. let degree = 0;
  17211. for (let it = this.iterator(); it.hasNext();) {
  17212. const de = it.next();
  17213. if (de.getEdgeRing() === er) degree++;
  17214. }
  17215. return degree;
  17216. }
  17217. }
  17218. getLabel() {
  17219. return this._label;
  17220. }
  17221. findCoveredLineEdges() {
  17222. let startLoc = Location.NONE;
  17223. for (let it = this.iterator(); it.hasNext();) {
  17224. const nextOut = it.next();
  17225. const nextIn = nextOut.getSym();
  17226. if (!nextOut.isLineEdge()) {
  17227. if (nextOut.isInResult()) {
  17228. startLoc = Location.INTERIOR;
  17229. break;
  17230. }
  17231. if (nextIn.isInResult()) {
  17232. startLoc = Location.EXTERIOR;
  17233. break;
  17234. }
  17235. }
  17236. }
  17237. if (startLoc === Location.NONE) return null;
  17238. let currLoc = startLoc;
  17239. for (let it = this.iterator(); it.hasNext();) {
  17240. const nextOut = it.next();
  17241. const nextIn = nextOut.getSym();
  17242. if (nextOut.isLineEdge()) {
  17243. nextOut.getEdge().setCovered(currLoc === Location.INTERIOR);
  17244. } else {
  17245. if (nextOut.isInResult()) currLoc = Location.EXTERIOR;
  17246. if (nextIn.isInResult()) currLoc = Location.INTERIOR;
  17247. }
  17248. }
  17249. }
  17250. computeLabelling(geom) {
  17251. super.computeLabelling.call(this, geom);
  17252. this._label = new Label(Location.NONE);
  17253. for (let it = this.iterator(); it.hasNext();) {
  17254. const ee = it.next();
  17255. const e = ee.getEdge();
  17256. const eLabel = e.getLabel();
  17257. for (let i = 0; i < 2; i++) {
  17258. const eLoc = eLabel.getLocation(i);
  17259. if (eLoc === Location.INTERIOR || eLoc === Location.BOUNDARY) this._label.setLocation(i, Location.INTERIOR);
  17260. }
  17261. }
  17262. }
  17263. }
  17264. class OverlayNodeFactory extends NodeFactory {
  17265. constructor() {
  17266. super();
  17267. }
  17268. createNode(coord) {
  17269. return new Node$2(coord, new DirectedEdgeStar$1());
  17270. }
  17271. }
  17272. class OrientedCoordinateArray {
  17273. constructor() {
  17274. OrientedCoordinateArray.constructor_.apply(this, arguments);
  17275. }
  17276. static constructor_() {
  17277. this._pts = null;
  17278. this._orientation = null;
  17279. const pts = arguments[0];
  17280. this._pts = pts;
  17281. this._orientation = OrientedCoordinateArray.orientation(pts);
  17282. }
  17283. static orientation(pts) {
  17284. return CoordinateArrays.increasingDirection(pts) === 1;
  17285. }
  17286. static compareOriented(pts1, orientation1, pts2, orientation2) {
  17287. const dir1 = orientation1 ? 1 : -1;
  17288. const dir2 = orientation2 ? 1 : -1;
  17289. const limit1 = orientation1 ? pts1.length : -1;
  17290. const limit2 = orientation2 ? pts2.length : -1;
  17291. let i1 = orientation1 ? 0 : pts1.length - 1;
  17292. let i2 = orientation2 ? 0 : pts2.length - 1;
  17293. while (true) {
  17294. const compPt = pts1[i1].compareTo(pts2[i2]);
  17295. if (compPt !== 0) return compPt;
  17296. i1 += dir1;
  17297. i2 += dir2;
  17298. const done1 = i1 === limit1;
  17299. const done2 = i2 === limit2;
  17300. if (done1 && !done2) return -1;
  17301. if (!done1 && done2) return 1;
  17302. if (done1 && done2) return 0;
  17303. }
  17304. }
  17305. compareTo(o1) {
  17306. const oca = o1;
  17307. const comp = OrientedCoordinateArray.compareOriented(this._pts, this._orientation, oca._pts, oca._orientation);
  17308. return comp;
  17309. }
  17310. get interfaces_() {
  17311. return [Comparable];
  17312. }
  17313. }
  17314. class EdgeList {
  17315. constructor() {
  17316. EdgeList.constructor_.apply(this, arguments);
  17317. }
  17318. static constructor_() {
  17319. this._edges = new ArrayList();
  17320. this._ocaMap = new TreeMap();
  17321. }
  17322. print(out) {
  17323. out.print('MULTILINESTRING ( ');
  17324. for (let j = 0; j < this._edges.size(); j++) {
  17325. const e = this._edges.get(j);
  17326. if (j > 0) out.print(',');
  17327. out.print('(');
  17328. const pts = e.getCoordinates();
  17329. for (let i = 0; i < pts.length; i++) {
  17330. if (i > 0) out.print(',');
  17331. out.print(pts[i].x + ' ' + pts[i].y);
  17332. }
  17333. out.println(')');
  17334. }
  17335. out.print(') ');
  17336. }
  17337. addAll(edgeColl) {
  17338. for (let i = edgeColl.iterator(); i.hasNext();) this.add(i.next());
  17339. }
  17340. findEdgeIndex(e) {
  17341. for (let i = 0; i < this._edges.size(); i++) if (this._edges.get(i).equals(e)) return i;
  17342. return -1;
  17343. }
  17344. iterator() {
  17345. return this._edges.iterator();
  17346. }
  17347. getEdges() {
  17348. return this._edges;
  17349. }
  17350. get(i) {
  17351. return this._edges.get(i);
  17352. }
  17353. findEqualEdge(e) {
  17354. const oca = new OrientedCoordinateArray(e.getCoordinates());
  17355. const matchEdge = this._ocaMap.get(oca);
  17356. return matchEdge;
  17357. }
  17358. add(e) {
  17359. this._edges.add(e);
  17360. const oca = new OrientedCoordinateArray(e.getCoordinates());
  17361. this._ocaMap.put(oca, e);
  17362. }
  17363. }
  17364. class SegmentIntersector {
  17365. processIntersections(e0, segIndex0, e1, segIndex1) {}
  17366. isDone() {}
  17367. }
  17368. class IntersectionAdder {
  17369. constructor() {
  17370. IntersectionAdder.constructor_.apply(this, arguments);
  17371. }
  17372. static constructor_() {
  17373. this._hasIntersection = false;
  17374. this._hasProper = false;
  17375. this._hasProperInterior = false;
  17376. this._hasInterior = false;
  17377. this._properIntersectionPoint = null;
  17378. this._li = null;
  17379. this._isSelfIntersection = null;
  17380. this.numIntersections = 0;
  17381. this.numInteriorIntersections = 0;
  17382. this.numProperIntersections = 0;
  17383. this.numTests = 0;
  17384. const li = arguments[0];
  17385. this._li = li;
  17386. }
  17387. static isAdjacentSegments(i1, i2) {
  17388. return Math.abs(i1 - i2) === 1;
  17389. }
  17390. isTrivialIntersection(e0, segIndex0, e1, segIndex1) {
  17391. if (e0 === e1) if (this._li.getIntersectionNum() === 1) {
  17392. if (IntersectionAdder.isAdjacentSegments(segIndex0, segIndex1)) return true;
  17393. if (e0.isClosed()) {
  17394. const maxSegIndex = e0.size() - 1;
  17395. if (segIndex0 === 0 && segIndex1 === maxSegIndex || segIndex1 === 0 && segIndex0 === maxSegIndex) return true;
  17396. }
  17397. }
  17398. return false;
  17399. }
  17400. getProperIntersectionPoint() {
  17401. return this._properIntersectionPoint;
  17402. }
  17403. hasProperInteriorIntersection() {
  17404. return this._hasProperInterior;
  17405. }
  17406. getLineIntersector() {
  17407. return this._li;
  17408. }
  17409. hasProperIntersection() {
  17410. return this._hasProper;
  17411. }
  17412. processIntersections(e0, segIndex0, e1, segIndex1) {
  17413. if (e0 === e1 && segIndex0 === segIndex1) return null;
  17414. this.numTests++;
  17415. const p00 = e0.getCoordinates()[segIndex0];
  17416. const p01 = e0.getCoordinates()[segIndex0 + 1];
  17417. const p10 = e1.getCoordinates()[segIndex1];
  17418. const p11 = e1.getCoordinates()[segIndex1 + 1];
  17419. this._li.computeIntersection(p00, p01, p10, p11);
  17420. if (this._li.hasIntersection()) {
  17421. this.numIntersections++;
  17422. if (this._li.isInteriorIntersection()) {
  17423. this.numInteriorIntersections++;
  17424. this._hasInterior = true;
  17425. }
  17426. if (!this.isTrivialIntersection(e0, segIndex0, e1, segIndex1)) {
  17427. this._hasIntersection = true;
  17428. e0.addIntersections(this._li, segIndex0, 0);
  17429. e1.addIntersections(this._li, segIndex1, 1);
  17430. if (this._li.isProper()) {
  17431. this.numProperIntersections++;
  17432. this._hasProper = true;
  17433. this._hasProperInterior = true;
  17434. }
  17435. }
  17436. }
  17437. }
  17438. hasIntersection() {
  17439. return this._hasIntersection;
  17440. }
  17441. isDone() {
  17442. return false;
  17443. }
  17444. hasInteriorIntersection() {
  17445. return this._hasInterior;
  17446. }
  17447. get interfaces_() {
  17448. return [SegmentIntersector];
  17449. }
  17450. }
  17451. class BufferBuilder {
  17452. constructor() {
  17453. BufferBuilder.constructor_.apply(this, arguments);
  17454. }
  17455. static constructor_() {
  17456. this._bufParams = null;
  17457. this._workingPrecisionModel = null;
  17458. this._workingNoder = null;
  17459. this._geomFact = null;
  17460. this._graph = null;
  17461. this._edgeList = new EdgeList();
  17462. const bufParams = arguments[0];
  17463. this._bufParams = bufParams;
  17464. }
  17465. static depthDelta(label) {
  17466. const lLoc = label.getLocation(0, Position.LEFT);
  17467. const rLoc = label.getLocation(0, Position.RIGHT);
  17468. if (lLoc === Location.INTERIOR && rLoc === Location.EXTERIOR) return 1;else if (lLoc === Location.EXTERIOR && rLoc === Location.INTERIOR) return -1;
  17469. return 0;
  17470. }
  17471. static convertSegStrings(it) {
  17472. const fact = new GeometryFactory();
  17473. const lines = new ArrayList();
  17474. while (it.hasNext()) {
  17475. const ss = it.next();
  17476. const line = fact.createLineString(ss.getCoordinates());
  17477. lines.add(line);
  17478. }
  17479. return fact.buildGeometry(lines);
  17480. }
  17481. setWorkingPrecisionModel(pm) {
  17482. this._workingPrecisionModel = pm;
  17483. }
  17484. insertUniqueEdge(e) {
  17485. const existingEdge = this._edgeList.findEqualEdge(e);
  17486. if (existingEdge !== null) {
  17487. const existingLabel = existingEdge.getLabel();
  17488. let labelToMerge = e.getLabel();
  17489. if (!existingEdge.isPointwiseEqual(e)) {
  17490. labelToMerge = new Label(e.getLabel());
  17491. labelToMerge.flip();
  17492. }
  17493. existingLabel.merge(labelToMerge);
  17494. const mergeDelta = BufferBuilder.depthDelta(labelToMerge);
  17495. const existingDelta = existingEdge.getDepthDelta();
  17496. const newDelta = existingDelta + mergeDelta;
  17497. existingEdge.setDepthDelta(newDelta);
  17498. } else {
  17499. this._edgeList.add(e);
  17500. e.setDepthDelta(BufferBuilder.depthDelta(e.getLabel()));
  17501. }
  17502. }
  17503. buildSubgraphs(subgraphList, polyBuilder) {
  17504. const processedGraphs = new ArrayList();
  17505. for (let i = subgraphList.iterator(); i.hasNext();) {
  17506. const subgraph = i.next();
  17507. const p = subgraph.getRightmostCoordinate();
  17508. const locater = new SubgraphDepthLocater(processedGraphs);
  17509. const outsideDepth = locater.getDepth(p);
  17510. subgraph.computeDepth(outsideDepth);
  17511. subgraph.findResultEdges();
  17512. processedGraphs.add(subgraph);
  17513. polyBuilder.add(subgraph.getDirectedEdges(), subgraph.getNodes());
  17514. }
  17515. }
  17516. createSubgraphs(graph) {
  17517. const subgraphList = new ArrayList();
  17518. for (let i = graph.getNodes().iterator(); i.hasNext();) {
  17519. const node = i.next();
  17520. if (!node.isVisited()) {
  17521. const subgraph = new BufferSubgraph();
  17522. subgraph.create(node);
  17523. subgraphList.add(subgraph);
  17524. }
  17525. }
  17526. Collections.sort(subgraphList, Collections.reverseOrder());
  17527. return subgraphList;
  17528. }
  17529. createEmptyResultGeometry() {
  17530. const emptyGeom = this._geomFact.createPolygon();
  17531. return emptyGeom;
  17532. }
  17533. getNoder(precisionModel) {
  17534. if (this._workingNoder !== null) return this._workingNoder;
  17535. const noder = new MCIndexNoder();
  17536. const li = new RobustLineIntersector();
  17537. li.setPrecisionModel(precisionModel);
  17538. noder.setSegmentIntersector(new IntersectionAdder(li));
  17539. return noder;
  17540. }
  17541. buffer(g, distance) {
  17542. let precisionModel = this._workingPrecisionModel;
  17543. if (precisionModel === null) precisionModel = g.getPrecisionModel();
  17544. this._geomFact = g.getFactory();
  17545. const curveBuilder = new OffsetCurveBuilder(precisionModel, this._bufParams);
  17546. const curveSetBuilder = new OffsetCurveSetBuilder(g, distance, curveBuilder);
  17547. const bufferSegStrList = curveSetBuilder.getCurves();
  17548. if (bufferSegStrList.size() <= 0) return this.createEmptyResultGeometry();
  17549. this.computeNodedEdges(bufferSegStrList, precisionModel);
  17550. this._graph = new PlanarGraph$1(new OverlayNodeFactory());
  17551. this._graph.addEdges(this._edgeList.getEdges());
  17552. const subgraphList = this.createSubgraphs(this._graph);
  17553. const polyBuilder = new PolygonBuilder(this._geomFact);
  17554. this.buildSubgraphs(subgraphList, polyBuilder);
  17555. const resultPolyList = polyBuilder.getPolygons();
  17556. if (resultPolyList.size() <= 0) return this.createEmptyResultGeometry();
  17557. const resultGeom = this._geomFact.buildGeometry(resultPolyList);
  17558. return resultGeom;
  17559. }
  17560. computeNodedEdges(bufferSegStrList, precisionModel) {
  17561. const noder = this.getNoder(precisionModel);
  17562. noder.computeNodes(bufferSegStrList);
  17563. const nodedSegStrings = noder.getNodedSubstrings();
  17564. for (let i = nodedSegStrings.iterator(); i.hasNext();) {
  17565. const segStr = i.next();
  17566. const pts = segStr.getCoordinates();
  17567. if (pts.length === 2 && pts[0].equals2D(pts[1])) continue;
  17568. const oldLabel = segStr.getData();
  17569. const edge = new Edge$1(segStr.getCoordinates(), new Label(oldLabel));
  17570. this.insertUniqueEdge(edge);
  17571. }
  17572. }
  17573. setNoder(noder) {
  17574. this._workingNoder = noder;
  17575. }
  17576. }
  17577. class NodingValidator {
  17578. constructor() {
  17579. NodingValidator.constructor_.apply(this, arguments);
  17580. }
  17581. static constructor_() {
  17582. this._li = new RobustLineIntersector();
  17583. this._segStrings = null;
  17584. const segStrings = arguments[0];
  17585. this._segStrings = segStrings;
  17586. }
  17587. checkEndPtVertexIntersections() {
  17588. if (arguments.length === 0) {
  17589. for (let i = this._segStrings.iterator(); i.hasNext();) {
  17590. const ss = i.next();
  17591. const pts = ss.getCoordinates();
  17592. this.checkEndPtVertexIntersections(pts[0], this._segStrings);
  17593. this.checkEndPtVertexIntersections(pts[pts.length - 1], this._segStrings);
  17594. }
  17595. } else if (arguments.length === 2) {
  17596. const testPt = arguments[0],
  17597. segStrings = arguments[1];
  17598. for (let i = segStrings.iterator(); i.hasNext();) {
  17599. const ss = i.next();
  17600. const pts = ss.getCoordinates();
  17601. for (let j = 1; j < pts.length - 1; j++) if (pts[j].equals(testPt)) throw new RuntimeException('found endpt/interior pt intersection at index ' + j + ' :pt ' + testPt);
  17602. }
  17603. }
  17604. }
  17605. checkInteriorIntersections() {
  17606. if (arguments.length === 0) {
  17607. for (let i = this._segStrings.iterator(); i.hasNext();) {
  17608. const ss0 = i.next();
  17609. for (let j = this._segStrings.iterator(); j.hasNext();) {
  17610. const ss1 = j.next();
  17611. this.checkInteriorIntersections(ss0, ss1);
  17612. }
  17613. }
  17614. } else if (arguments.length === 2) {
  17615. const ss0 = arguments[0],
  17616. ss1 = arguments[1];
  17617. const pts0 = ss0.getCoordinates();
  17618. const pts1 = ss1.getCoordinates();
  17619. for (let i0 = 0; i0 < pts0.length - 1; i0++) for (let i1 = 0; i1 < pts1.length - 1; i1++) this.checkInteriorIntersections(ss0, i0, ss1, i1);
  17620. } else if (arguments.length === 4) {
  17621. const e0 = arguments[0],
  17622. segIndex0 = arguments[1],
  17623. e1 = arguments[2],
  17624. segIndex1 = arguments[3];
  17625. if (e0 === e1 && segIndex0 === segIndex1) return null;
  17626. const p00 = e0.getCoordinates()[segIndex0];
  17627. const p01 = e0.getCoordinates()[segIndex0 + 1];
  17628. const p10 = e1.getCoordinates()[segIndex1];
  17629. const p11 = e1.getCoordinates()[segIndex1 + 1];
  17630. this._li.computeIntersection(p00, p01, p10, p11);
  17631. if (this._li.hasIntersection()) if (this._li.isProper() || this.hasInteriorIntersection(this._li, p00, p01) || this.hasInteriorIntersection(this._li, p10, p11)) throw new RuntimeException('found non-noded intersection at ' + p00 + '-' + p01 + ' and ' + p10 + '-' + p11);
  17632. }
  17633. }
  17634. checkValid() {
  17635. this.checkEndPtVertexIntersections();
  17636. this.checkInteriorIntersections();
  17637. this.checkCollapses();
  17638. }
  17639. checkCollapses() {
  17640. if (arguments.length === 0) {
  17641. for (let i = this._segStrings.iterator(); i.hasNext();) {
  17642. const ss = i.next();
  17643. this.checkCollapses(ss);
  17644. }
  17645. } else if (arguments.length === 1) {
  17646. const ss = arguments[0];
  17647. const pts = ss.getCoordinates();
  17648. for (let i = 0; i < pts.length - 2; i++) this.checkCollapse(pts[i], pts[i + 1], pts[i + 2]);
  17649. }
  17650. }
  17651. hasInteriorIntersection(li, p0, p1) {
  17652. for (let i = 0; i < li.getIntersectionNum(); i++) {
  17653. const intPt = li.getIntersection(i);
  17654. if (!(intPt.equals(p0) || intPt.equals(p1))) return true;
  17655. }
  17656. return false;
  17657. }
  17658. checkCollapse(p0, p1, p2) {
  17659. if (p0.equals(p2)) throw new RuntimeException('found non-noded collapse at ' + NodingValidator.fact.createLineString([p0, p1, p2]));
  17660. }
  17661. }
  17662. NodingValidator.fact = new GeometryFactory();
  17663. class HotPixel {
  17664. constructor() {
  17665. HotPixel.constructor_.apply(this, arguments);
  17666. }
  17667. static constructor_() {
  17668. this._li = null;
  17669. this._pt = null;
  17670. this._originalPt = null;
  17671. this._ptScaled = null;
  17672. this._p0Scaled = null;
  17673. this._p1Scaled = null;
  17674. this._scaleFactor = null;
  17675. this._minx = null;
  17676. this._maxx = null;
  17677. this._miny = null;
  17678. this._maxy = null;
  17679. this._corner = new Array(4).fill(null);
  17680. this._safeEnv = null;
  17681. const pt = arguments[0],
  17682. scaleFactor = arguments[1],
  17683. li = arguments[2];
  17684. this._originalPt = pt;
  17685. this._pt = pt;
  17686. this._scaleFactor = scaleFactor;
  17687. this._li = li;
  17688. if (scaleFactor <= 0) throw new IllegalArgumentException('Scale factor must be non-zero');
  17689. if (scaleFactor !== 1.0) {
  17690. this._pt = new Coordinate(this.scale(pt.x), this.scale(pt.y));
  17691. this._p0Scaled = new Coordinate();
  17692. this._p1Scaled = new Coordinate();
  17693. }
  17694. this.initCorners(this._pt);
  17695. }
  17696. intersectsScaled(p0, p1) {
  17697. const segMinx = Math.min(p0.x, p1.x);
  17698. const segMaxx = Math.max(p0.x, p1.x);
  17699. const segMiny = Math.min(p0.y, p1.y);
  17700. const segMaxy = Math.max(p0.y, p1.y);
  17701. const isOutsidePixelEnv = this._maxx < segMinx || this._minx > segMaxx || this._maxy < segMiny || this._miny > segMaxy;
  17702. if (isOutsidePixelEnv) return false;
  17703. const intersects = this.intersectsToleranceSquare(p0, p1);
  17704. Assert.isTrue(!(isOutsidePixelEnv && intersects), 'Found bad envelope test');
  17705. return intersects;
  17706. }
  17707. initCorners(pt) {
  17708. const tolerance = 0.5;
  17709. this._minx = pt.x - tolerance;
  17710. this._maxx = pt.x + tolerance;
  17711. this._miny = pt.y - tolerance;
  17712. this._maxy = pt.y + tolerance;
  17713. this._corner[0] = new Coordinate(this._maxx, this._maxy);
  17714. this._corner[1] = new Coordinate(this._minx, this._maxy);
  17715. this._corner[2] = new Coordinate(this._minx, this._miny);
  17716. this._corner[3] = new Coordinate(this._maxx, this._miny);
  17717. }
  17718. intersects(p0, p1) {
  17719. if (this._scaleFactor === 1.0) return this.intersectsScaled(p0, p1);
  17720. this.copyScaled(p0, this._p0Scaled);
  17721. this.copyScaled(p1, this._p1Scaled);
  17722. return this.intersectsScaled(this._p0Scaled, this._p1Scaled);
  17723. }
  17724. scale(val) {
  17725. return Math.round(val * this._scaleFactor);
  17726. }
  17727. getCoordinate() {
  17728. return this._originalPt;
  17729. }
  17730. copyScaled(p, pScaled) {
  17731. pScaled.x = this.scale(p.x);
  17732. pScaled.y = this.scale(p.y);
  17733. }
  17734. getSafeEnvelope() {
  17735. if (this._safeEnv === null) {
  17736. const safeTolerance = HotPixel.SAFE_ENV_EXPANSION_FACTOR / this._scaleFactor;
  17737. this._safeEnv = new Envelope(this._originalPt.x - safeTolerance, this._originalPt.x + safeTolerance, this._originalPt.y - safeTolerance, this._originalPt.y + safeTolerance);
  17738. }
  17739. return this._safeEnv;
  17740. }
  17741. intersectsPixelClosure(p0, p1) {
  17742. this._li.computeIntersection(p0, p1, this._corner[0], this._corner[1]);
  17743. if (this._li.hasIntersection()) return true;
  17744. this._li.computeIntersection(p0, p1, this._corner[1], this._corner[2]);
  17745. if (this._li.hasIntersection()) return true;
  17746. this._li.computeIntersection(p0, p1, this._corner[2], this._corner[3]);
  17747. if (this._li.hasIntersection()) return true;
  17748. this._li.computeIntersection(p0, p1, this._corner[3], this._corner[0]);
  17749. if (this._li.hasIntersection()) return true;
  17750. return false;
  17751. }
  17752. intersectsToleranceSquare(p0, p1) {
  17753. let intersectsLeft = false;
  17754. let intersectsBottom = false;
  17755. this._li.computeIntersection(p0, p1, this._corner[0], this._corner[1]);
  17756. if (this._li.isProper()) return true;
  17757. this._li.computeIntersection(p0, p1, this._corner[1], this._corner[2]);
  17758. if (this._li.isProper()) return true;
  17759. if (this._li.hasIntersection()) intersectsLeft = true;
  17760. this._li.computeIntersection(p0, p1, this._corner[2], this._corner[3]);
  17761. if (this._li.isProper()) return true;
  17762. if (this._li.hasIntersection()) intersectsBottom = true;
  17763. this._li.computeIntersection(p0, p1, this._corner[3], this._corner[0]);
  17764. if (this._li.isProper()) return true;
  17765. if (intersectsLeft && intersectsBottom) return true;
  17766. if (p0.equals(this._pt)) return true;
  17767. if (p1.equals(this._pt)) return true;
  17768. return false;
  17769. }
  17770. addSnappedNode(segStr, segIndex) {
  17771. const p0 = segStr.getCoordinate(segIndex);
  17772. const p1 = segStr.getCoordinate(segIndex + 1);
  17773. if (this.intersects(p0, p1)) {
  17774. segStr.addIntersection(this.getCoordinate(), segIndex);
  17775. return true;
  17776. }
  17777. return false;
  17778. }
  17779. }
  17780. HotPixel.SAFE_ENV_EXPANSION_FACTOR = 0.75;
  17781. class MonotoneChainSelectAction {
  17782. constructor() {
  17783. MonotoneChainSelectAction.constructor_.apply(this, arguments);
  17784. }
  17785. static constructor_() {
  17786. this.selectedSegment = new LineSegment();
  17787. }
  17788. select() {
  17789. if (arguments.length === 1) ; else if (arguments.length === 2) {
  17790. const mc = arguments[0],
  17791. startIndex = arguments[1];
  17792. mc.getLineSegment(startIndex, this.selectedSegment);
  17793. this.select(this.selectedSegment);
  17794. }
  17795. }
  17796. }
  17797. class MCIndexPointSnapper {
  17798. constructor() {
  17799. MCIndexPointSnapper.constructor_.apply(this, arguments);
  17800. }
  17801. static constructor_() {
  17802. this._index = null;
  17803. const index = arguments[0];
  17804. this._index = index;
  17805. }
  17806. snap() {
  17807. if (arguments.length === 1) {
  17808. const hotPixel = arguments[0];
  17809. return this.snap(hotPixel, null, -1);
  17810. } else if (arguments.length === 3) {
  17811. const hotPixel = arguments[0],
  17812. parentEdge = arguments[1],
  17813. hotPixelVertexIndex = arguments[2];
  17814. const pixelEnv = hotPixel.getSafeEnvelope();
  17815. const hotPixelSnapAction = new HotPixelSnapAction(hotPixel, parentEdge, hotPixelVertexIndex);
  17816. this._index.query(pixelEnv, new class {
  17817. get interfaces_() {
  17818. return [ItemVisitor];
  17819. }
  17820. visitItem(item) {
  17821. const testChain = item;
  17822. testChain.select(pixelEnv, hotPixelSnapAction);
  17823. }
  17824. }());
  17825. return hotPixelSnapAction.isNodeAdded();
  17826. }
  17827. }
  17828. }
  17829. class HotPixelSnapAction extends MonotoneChainSelectAction {
  17830. constructor() {
  17831. super();
  17832. HotPixelSnapAction.constructor_.apply(this, arguments);
  17833. }
  17834. static constructor_() {
  17835. this._hotPixel = null;
  17836. this._parentEdge = null;
  17837. this._hotPixelVertexIndex = null;
  17838. this._isNodeAdded = false;
  17839. const hotPixel = arguments[0],
  17840. parentEdge = arguments[1],
  17841. hotPixelVertexIndex = arguments[2];
  17842. this._hotPixel = hotPixel;
  17843. this._parentEdge = parentEdge;
  17844. this._hotPixelVertexIndex = hotPixelVertexIndex;
  17845. }
  17846. isNodeAdded() {
  17847. return this._isNodeAdded;
  17848. }
  17849. select() {
  17850. if (arguments.length === 2 && Number.isInteger(arguments[1]) && arguments[0] instanceof MonotoneChain) {
  17851. const mc = arguments[0],
  17852. startIndex = arguments[1];
  17853. const ss = mc.getContext();
  17854. if (this._parentEdge === ss) if (startIndex === this._hotPixelVertexIndex || startIndex + 1 === this._hotPixelVertexIndex) return null;
  17855. this._isNodeAdded |= this._hotPixel.addSnappedNode(ss, startIndex);
  17856. } else {
  17857. return super.select.apply(this, arguments);
  17858. }
  17859. }
  17860. }
  17861. MCIndexPointSnapper.HotPixelSnapAction = HotPixelSnapAction;
  17862. class InteriorIntersectionFinderAdder {
  17863. constructor() {
  17864. InteriorIntersectionFinderAdder.constructor_.apply(this, arguments);
  17865. }
  17866. static constructor_() {
  17867. this._li = null;
  17868. this._interiorIntersections = null;
  17869. const li = arguments[0];
  17870. this._li = li;
  17871. this._interiorIntersections = new ArrayList();
  17872. }
  17873. processIntersections(e0, segIndex0, e1, segIndex1) {
  17874. if (e0 === e1 && segIndex0 === segIndex1) return null;
  17875. const p00 = e0.getCoordinates()[segIndex0];
  17876. const p01 = e0.getCoordinates()[segIndex0 + 1];
  17877. const p10 = e1.getCoordinates()[segIndex1];
  17878. const p11 = e1.getCoordinates()[segIndex1 + 1];
  17879. this._li.computeIntersection(p00, p01, p10, p11);
  17880. if (this._li.hasIntersection()) if (this._li.isInteriorIntersection()) {
  17881. for (let intIndex = 0; intIndex < this._li.getIntersectionNum(); intIndex++) this._interiorIntersections.add(this._li.getIntersection(intIndex));
  17882. e0.addIntersections(this._li, segIndex0, 0);
  17883. e1.addIntersections(this._li, segIndex1, 1);
  17884. }
  17885. }
  17886. isDone() {
  17887. return false;
  17888. }
  17889. getInteriorIntersections() {
  17890. return this._interiorIntersections;
  17891. }
  17892. get interfaces_() {
  17893. return [SegmentIntersector];
  17894. }
  17895. }
  17896. class MCIndexSnapRounder {
  17897. constructor() {
  17898. MCIndexSnapRounder.constructor_.apply(this, arguments);
  17899. }
  17900. static constructor_() {
  17901. this._pm = null;
  17902. this._li = null;
  17903. this._scaleFactor = null;
  17904. this._noder = null;
  17905. this._pointSnapper = null;
  17906. this._nodedSegStrings = null;
  17907. const pm = arguments[0];
  17908. this._pm = pm;
  17909. this._li = new RobustLineIntersector();
  17910. this._li.setPrecisionModel(pm);
  17911. this._scaleFactor = pm.getScale();
  17912. }
  17913. checkCorrectness(inputSegmentStrings) {
  17914. const resultSegStrings = NodedSegmentString.getNodedSubstrings(inputSegmentStrings);
  17915. const nv = new NodingValidator(resultSegStrings);
  17916. try {
  17917. nv.checkValid();
  17918. } catch (ex) {
  17919. if (ex instanceof Exception) ex.printStackTrace();else throw ex;
  17920. } finally {}
  17921. }
  17922. getNodedSubstrings() {
  17923. return NodedSegmentString.getNodedSubstrings(this._nodedSegStrings);
  17924. }
  17925. snapRound(segStrings, li) {
  17926. const intersections = this.findInteriorIntersections(segStrings, li);
  17927. this.computeIntersectionSnaps(intersections);
  17928. this.computeVertexSnaps(segStrings);
  17929. }
  17930. findInteriorIntersections(segStrings, li) {
  17931. const intFinderAdder = new InteriorIntersectionFinderAdder(li);
  17932. this._noder.setSegmentIntersector(intFinderAdder);
  17933. this._noder.computeNodes(segStrings);
  17934. return intFinderAdder.getInteriorIntersections();
  17935. }
  17936. computeVertexSnaps() {
  17937. if (hasInterface(arguments[0], Collection)) {
  17938. const edges = arguments[0];
  17939. for (let i0 = edges.iterator(); i0.hasNext();) {
  17940. const edge0 = i0.next();
  17941. this.computeVertexSnaps(edge0);
  17942. }
  17943. } else if (arguments[0] instanceof NodedSegmentString) {
  17944. const e = arguments[0];
  17945. const pts0 = e.getCoordinates();
  17946. for (let i = 0; i < pts0.length; i++) {
  17947. const hotPixel = new HotPixel(pts0[i], this._scaleFactor, this._li);
  17948. const isNodeAdded = this._pointSnapper.snap(hotPixel, e, i);
  17949. if (isNodeAdded) e.addIntersection(pts0[i], i);
  17950. }
  17951. }
  17952. }
  17953. computeNodes(inputSegmentStrings) {
  17954. this._nodedSegStrings = inputSegmentStrings;
  17955. this._noder = new MCIndexNoder();
  17956. this._pointSnapper = new MCIndexPointSnapper(this._noder.getIndex());
  17957. this.snapRound(inputSegmentStrings, this._li);
  17958. }
  17959. computeIntersectionSnaps(snapPts) {
  17960. for (let it = snapPts.iterator(); it.hasNext();) {
  17961. const snapPt = it.next();
  17962. const hotPixel = new HotPixel(snapPt, this._scaleFactor, this._li);
  17963. this._pointSnapper.snap(hotPixel);
  17964. }
  17965. }
  17966. get interfaces_() {
  17967. return [Noder];
  17968. }
  17969. }
  17970. class BufferOp {
  17971. constructor() {
  17972. BufferOp.constructor_.apply(this, arguments);
  17973. }
  17974. static constructor_() {
  17975. this._argGeom = null;
  17976. this._distance = null;
  17977. this._bufParams = new BufferParameters();
  17978. this._resultGeometry = null;
  17979. this._saveException = null;
  17980. if (arguments.length === 1) {
  17981. const g = arguments[0];
  17982. this._argGeom = g;
  17983. } else if (arguments.length === 2) {
  17984. const g = arguments[0],
  17985. bufParams = arguments[1];
  17986. this._argGeom = g;
  17987. this._bufParams = bufParams;
  17988. }
  17989. }
  17990. static bufferOp() {
  17991. if (arguments.length === 2) {
  17992. const g = arguments[0],
  17993. distance = arguments[1];
  17994. const gBuf = new BufferOp(g);
  17995. const geomBuf = gBuf.getResultGeometry(distance);
  17996. return geomBuf;
  17997. } else if (arguments.length === 3) {
  17998. if (Number.isInteger(arguments[2]) && arguments[0] instanceof Geometry && typeof arguments[1] === 'number') {
  17999. const g = arguments[0],
  18000. distance = arguments[1],
  18001. quadrantSegments = arguments[2];
  18002. const bufOp = new BufferOp(g);
  18003. bufOp.setQuadrantSegments(quadrantSegments);
  18004. const geomBuf = bufOp.getResultGeometry(distance);
  18005. return geomBuf;
  18006. } else if (arguments[2] instanceof BufferParameters && arguments[0] instanceof Geometry && typeof arguments[1] === 'number') {
  18007. const g = arguments[0],
  18008. distance = arguments[1],
  18009. params = arguments[2];
  18010. const bufOp = new BufferOp(g, params);
  18011. const geomBuf = bufOp.getResultGeometry(distance);
  18012. return geomBuf;
  18013. }
  18014. } else if (arguments.length === 4) {
  18015. const g = arguments[0],
  18016. distance = arguments[1],
  18017. quadrantSegments = arguments[2],
  18018. endCapStyle = arguments[3];
  18019. const bufOp = new BufferOp(g);
  18020. bufOp.setQuadrantSegments(quadrantSegments);
  18021. bufOp.setEndCapStyle(endCapStyle);
  18022. const geomBuf = bufOp.getResultGeometry(distance);
  18023. return geomBuf;
  18024. }
  18025. }
  18026. static precisionScaleFactor(g, distance, maxPrecisionDigits) {
  18027. const env = g.getEnvelopeInternal();
  18028. const envMax = MathUtil.max(Math.abs(env.getMaxX()), Math.abs(env.getMaxY()), Math.abs(env.getMinX()), Math.abs(env.getMinY()));
  18029. const expandByDistance = distance > 0.0 ? distance : 0.0;
  18030. const bufEnvMax = envMax + 2 * expandByDistance;
  18031. const bufEnvPrecisionDigits = Math.trunc(Math.log(bufEnvMax) / Math.log(10) + 1.0);
  18032. const minUnitLog10 = maxPrecisionDigits - bufEnvPrecisionDigits;
  18033. const scaleFactor = Math.pow(10.0, minUnitLog10);
  18034. return scaleFactor;
  18035. }
  18036. bufferFixedPrecision(fixedPM) {
  18037. const noder = new ScaledNoder(new MCIndexSnapRounder(new PrecisionModel(1.0)), fixedPM.getScale());
  18038. const bufBuilder = new BufferBuilder(this._bufParams);
  18039. bufBuilder.setWorkingPrecisionModel(fixedPM);
  18040. bufBuilder.setNoder(noder);
  18041. this._resultGeometry = bufBuilder.buffer(this._argGeom, this._distance);
  18042. }
  18043. bufferReducedPrecision() {
  18044. if (arguments.length === 0) {
  18045. for (let precDigits = BufferOp.MAX_PRECISION_DIGITS; precDigits >= 0; precDigits--) {
  18046. try {
  18047. this.bufferReducedPrecision(precDigits);
  18048. } catch (ex) {
  18049. if (ex instanceof TopologyException) this._saveException = ex;else throw ex;
  18050. } finally {}
  18051. if (this._resultGeometry !== null) return null;
  18052. }
  18053. throw this._saveException;
  18054. } else if (arguments.length === 1) {
  18055. const precisionDigits = arguments[0];
  18056. const sizeBasedScaleFactor = BufferOp.precisionScaleFactor(this._argGeom, this._distance, precisionDigits);
  18057. const fixedPM = new PrecisionModel(sizeBasedScaleFactor);
  18058. this.bufferFixedPrecision(fixedPM);
  18059. }
  18060. }
  18061. computeGeometry() {
  18062. this.bufferOriginalPrecision();
  18063. if (this._resultGeometry !== null) return null;
  18064. const argPM = this._argGeom.getFactory().getPrecisionModel();
  18065. if (argPM.getType() === PrecisionModel.FIXED) this.bufferFixedPrecision(argPM);else this.bufferReducedPrecision();
  18066. }
  18067. setQuadrantSegments(quadrantSegments) {
  18068. this._bufParams.setQuadrantSegments(quadrantSegments);
  18069. }
  18070. bufferOriginalPrecision() {
  18071. try {
  18072. const bufBuilder = new BufferBuilder(this._bufParams);
  18073. this._resultGeometry = bufBuilder.buffer(this._argGeom, this._distance);
  18074. } catch (ex) {
  18075. if (ex instanceof RuntimeException) this._saveException = ex;else throw ex;
  18076. } finally {}
  18077. }
  18078. getResultGeometry(distance) {
  18079. this._distance = distance;
  18080. this.computeGeometry();
  18081. return this._resultGeometry;
  18082. }
  18083. setEndCapStyle(endCapStyle) {
  18084. this._bufParams.setEndCapStyle(endCapStyle);
  18085. }
  18086. }
  18087. BufferOp.CAP_ROUND = BufferParameters.CAP_ROUND;
  18088. BufferOp.CAP_BUTT = BufferParameters.CAP_FLAT;
  18089. BufferOp.CAP_FLAT = BufferParameters.CAP_FLAT;
  18090. BufferOp.CAP_SQUARE = BufferParameters.CAP_SQUARE;
  18091. BufferOp.MAX_PRECISION_DIGITS = 12;
  18092. var buffer = /*#__PURE__*/Object.freeze({
  18093. __proto__: null,
  18094. BufferOp: BufferOp,
  18095. BufferParameters: BufferParameters
  18096. });
  18097. class GeometryLocation {
  18098. constructor() {
  18099. GeometryLocation.constructor_.apply(this, arguments);
  18100. }
  18101. static constructor_() {
  18102. this._component = null;
  18103. this._segIndex = null;
  18104. this._pt = null;
  18105. if (arguments.length === 2) {
  18106. const component = arguments[0],
  18107. pt = arguments[1];
  18108. GeometryLocation.constructor_.call(this, component, GeometryLocation.INSIDE_AREA, pt);
  18109. } else if (arguments.length === 3) {
  18110. const component = arguments[0],
  18111. segIndex = arguments[1],
  18112. pt = arguments[2];
  18113. this._component = component;
  18114. this._segIndex = segIndex;
  18115. this._pt = pt;
  18116. }
  18117. }
  18118. getSegmentIndex() {
  18119. return this._segIndex;
  18120. }
  18121. getCoordinate() {
  18122. return this._pt;
  18123. }
  18124. isInsideArea() {
  18125. return this._segIndex === GeometryLocation.INSIDE_AREA;
  18126. }
  18127. toString() {
  18128. return this._component.getGeometryType() + '[' + this._segIndex + ']' + '-' + WKTWriter.toPoint(this._pt);
  18129. }
  18130. getGeometryComponent() {
  18131. return this._component;
  18132. }
  18133. }
  18134. GeometryLocation.INSIDE_AREA = -1;
  18135. class ConnectedElementLocationFilter {
  18136. constructor() {
  18137. ConnectedElementLocationFilter.constructor_.apply(this, arguments);
  18138. }
  18139. static constructor_() {
  18140. this._locations = null;
  18141. const locations = arguments[0];
  18142. this._locations = locations;
  18143. }
  18144. static getLocations(geom) {
  18145. const locations = new ArrayList();
  18146. geom.apply(new ConnectedElementLocationFilter(locations));
  18147. return locations;
  18148. }
  18149. filter(geom) {
  18150. if (geom.isEmpty()) return null;
  18151. if (geom instanceof Point || geom instanceof LineString || geom instanceof Polygon) this._locations.add(new GeometryLocation(geom, 0, geom.getCoordinate()));
  18152. }
  18153. get interfaces_() {
  18154. return [GeometryFilter];
  18155. }
  18156. }
  18157. class DistanceOp {
  18158. constructor() {
  18159. DistanceOp.constructor_.apply(this, arguments);
  18160. }
  18161. static constructor_() {
  18162. this._geom = null;
  18163. this._terminateDistance = 0.0;
  18164. this._ptLocator = new PointLocator();
  18165. this._minDistanceLocation = null;
  18166. this._minDistance = Double.MAX_VALUE;
  18167. if (arguments.length === 2) {
  18168. const g0 = arguments[0],
  18169. g1 = arguments[1];
  18170. DistanceOp.constructor_.call(this, g0, g1, 0.0);
  18171. } else if (arguments.length === 3) {
  18172. const g0 = arguments[0],
  18173. g1 = arguments[1],
  18174. terminateDistance = arguments[2];
  18175. this._geom = new Array(2).fill(null);
  18176. this._geom[0] = g0;
  18177. this._geom[1] = g1;
  18178. this._terminateDistance = terminateDistance;
  18179. }
  18180. }
  18181. static distance(g0, g1) {
  18182. const distOp = new DistanceOp(g0, g1);
  18183. return distOp.distance();
  18184. }
  18185. static isWithinDistance(g0, g1, distance) {
  18186. const envDist = g0.getEnvelopeInternal().distance(g1.getEnvelopeInternal());
  18187. if (envDist > distance) return false;
  18188. const distOp = new DistanceOp(g0, g1, distance);
  18189. return distOp.distance() <= distance;
  18190. }
  18191. static nearestPoints(g0, g1) {
  18192. const distOp = new DistanceOp(g0, g1);
  18193. return distOp.nearestPoints();
  18194. }
  18195. computeContainmentDistance() {
  18196. if (arguments.length === 0) {
  18197. const locPtPoly = new Array(2).fill(null);
  18198. this.computeContainmentDistance(0, locPtPoly);
  18199. if (this._minDistance <= this._terminateDistance) return null;
  18200. this.computeContainmentDistance(1, locPtPoly);
  18201. } else if (arguments.length === 2) {
  18202. const polyGeomIndex = arguments[0],
  18203. locPtPoly = arguments[1];
  18204. const polyGeom = this._geom[polyGeomIndex];
  18205. if (polyGeom.getDimension() < 2) return null;
  18206. const locationsIndex = 1 - polyGeomIndex;
  18207. const polys = PolygonExtracter.getPolygons(polyGeom);
  18208. if (polys.size() > 0) {
  18209. const insideLocs = ConnectedElementLocationFilter.getLocations(this._geom[locationsIndex]);
  18210. this.computeContainmentDistance(insideLocs, polys, locPtPoly);
  18211. if (this._minDistance <= this._terminateDistance) {
  18212. this._minDistanceLocation[locationsIndex] = locPtPoly[0];
  18213. this._minDistanceLocation[polyGeomIndex] = locPtPoly[1];
  18214. return null;
  18215. }
  18216. }
  18217. } else if (arguments.length === 3) {
  18218. if (arguments[2] instanceof Array && hasInterface(arguments[0], List) && hasInterface(arguments[1], List)) {
  18219. const locs = arguments[0],
  18220. polys = arguments[1],
  18221. locPtPoly = arguments[2];
  18222. for (let i = 0; i < locs.size(); i++) {
  18223. const loc = locs.get(i);
  18224. for (let j = 0; j < polys.size(); j++) {
  18225. this.computeContainmentDistance(loc, polys.get(j), locPtPoly);
  18226. if (this._minDistance <= this._terminateDistance) return null;
  18227. }
  18228. }
  18229. } else if (arguments[2] instanceof Array && arguments[0] instanceof GeometryLocation && arguments[1] instanceof Polygon) {
  18230. const ptLoc = arguments[0],
  18231. poly = arguments[1],
  18232. locPtPoly = arguments[2];
  18233. const pt = ptLoc.getCoordinate();
  18234. if (Location.EXTERIOR !== this._ptLocator.locate(pt, poly)) {
  18235. this._minDistance = 0.0;
  18236. locPtPoly[0] = ptLoc;
  18237. locPtPoly[1] = new GeometryLocation(poly, pt);
  18238. return null;
  18239. }
  18240. }
  18241. }
  18242. }
  18243. computeMinDistanceLinesPoints(lines, points, locGeom) {
  18244. for (let i = 0; i < lines.size(); i++) {
  18245. const line = lines.get(i);
  18246. for (let j = 0; j < points.size(); j++) {
  18247. const pt = points.get(j);
  18248. this.computeMinDistance(line, pt, locGeom);
  18249. if (this._minDistance <= this._terminateDistance) return null;
  18250. }
  18251. }
  18252. }
  18253. computeFacetDistance() {
  18254. const locGeom = new Array(2).fill(null);
  18255. const lines0 = LinearComponentExtracter.getLines(this._geom[0]);
  18256. const lines1 = LinearComponentExtracter.getLines(this._geom[1]);
  18257. const pts0 = PointExtracter.getPoints(this._geom[0]);
  18258. const pts1 = PointExtracter.getPoints(this._geom[1]);
  18259. this.computeMinDistanceLines(lines0, lines1, locGeom);
  18260. this.updateMinDistance(locGeom, false);
  18261. if (this._minDistance <= this._terminateDistance) return null;
  18262. locGeom[0] = null;
  18263. locGeom[1] = null;
  18264. this.computeMinDistanceLinesPoints(lines0, pts1, locGeom);
  18265. this.updateMinDistance(locGeom, false);
  18266. if (this._minDistance <= this._terminateDistance) return null;
  18267. locGeom[0] = null;
  18268. locGeom[1] = null;
  18269. this.computeMinDistanceLinesPoints(lines1, pts0, locGeom);
  18270. this.updateMinDistance(locGeom, true);
  18271. if (this._minDistance <= this._terminateDistance) return null;
  18272. locGeom[0] = null;
  18273. locGeom[1] = null;
  18274. this.computeMinDistancePoints(pts0, pts1, locGeom);
  18275. this.updateMinDistance(locGeom, false);
  18276. }
  18277. nearestLocations() {
  18278. this.computeMinDistance();
  18279. return this._minDistanceLocation;
  18280. }
  18281. updateMinDistance(locGeom, flip) {
  18282. if (locGeom[0] === null) return null;
  18283. if (flip) {
  18284. this._minDistanceLocation[0] = locGeom[1];
  18285. this._minDistanceLocation[1] = locGeom[0];
  18286. } else {
  18287. this._minDistanceLocation[0] = locGeom[0];
  18288. this._minDistanceLocation[1] = locGeom[1];
  18289. }
  18290. }
  18291. nearestPoints() {
  18292. this.computeMinDistance();
  18293. const nearestPts = [this._minDistanceLocation[0].getCoordinate(), this._minDistanceLocation[1].getCoordinate()];
  18294. return nearestPts;
  18295. }
  18296. computeMinDistance() {
  18297. if (arguments.length === 0) {
  18298. if (this._minDistanceLocation !== null) return null;
  18299. this._minDistanceLocation = new Array(2).fill(null);
  18300. this.computeContainmentDistance();
  18301. if (this._minDistance <= this._terminateDistance) return null;
  18302. this.computeFacetDistance();
  18303. } else if (arguments.length === 3) {
  18304. if (arguments[2] instanceof Array && arguments[0] instanceof LineString && arguments[1] instanceof Point) {
  18305. const line = arguments[0],
  18306. pt = arguments[1],
  18307. locGeom = arguments[2];
  18308. if (line.getEnvelopeInternal().distance(pt.getEnvelopeInternal()) > this._minDistance) return null;
  18309. const coord0 = line.getCoordinates();
  18310. const coord = pt.getCoordinate();
  18311. for (let i = 0; i < coord0.length - 1; i++) {
  18312. const dist = Distance.pointToSegment(coord, coord0[i], coord0[i + 1]);
  18313. if (dist < this._minDistance) {
  18314. this._minDistance = dist;
  18315. const seg = new LineSegment(coord0[i], coord0[i + 1]);
  18316. const segClosestPoint = seg.closestPoint(coord);
  18317. locGeom[0] = new GeometryLocation(line, i, segClosestPoint);
  18318. locGeom[1] = new GeometryLocation(pt, 0, coord);
  18319. }
  18320. if (this._minDistance <= this._terminateDistance) return null;
  18321. }
  18322. } else if (arguments[2] instanceof Array && arguments[0] instanceof LineString && arguments[1] instanceof LineString) {
  18323. const line0 = arguments[0],
  18324. line1 = arguments[1],
  18325. locGeom = arguments[2];
  18326. if (line0.getEnvelopeInternal().distance(line1.getEnvelopeInternal()) > this._minDistance) return null;
  18327. const coord0 = line0.getCoordinates();
  18328. const coord1 = line1.getCoordinates();
  18329. for (let i = 0; i < coord0.length - 1; i++) {
  18330. const segEnv0 = new Envelope(coord0[i], coord0[i + 1]);
  18331. if (segEnv0.distance(line1.getEnvelopeInternal()) > this._minDistance) continue;
  18332. for (let j = 0; j < coord1.length - 1; j++) {
  18333. const segEnv1 = new Envelope(coord1[j], coord1[j + 1]);
  18334. if (segEnv0.distance(segEnv1) > this._minDistance) continue;
  18335. const dist = Distance.segmentToSegment(coord0[i], coord0[i + 1], coord1[j], coord1[j + 1]);
  18336. if (dist < this._minDistance) {
  18337. this._minDistance = dist;
  18338. const seg0 = new LineSegment(coord0[i], coord0[i + 1]);
  18339. const seg1 = new LineSegment(coord1[j], coord1[j + 1]);
  18340. const closestPt = seg0.closestPoints(seg1);
  18341. locGeom[0] = new GeometryLocation(line0, i, closestPt[0]);
  18342. locGeom[1] = new GeometryLocation(line1, j, closestPt[1]);
  18343. }
  18344. if (this._minDistance <= this._terminateDistance) return null;
  18345. }
  18346. }
  18347. }
  18348. }
  18349. }
  18350. computeMinDistancePoints(points0, points1, locGeom) {
  18351. for (let i = 0; i < points0.size(); i++) {
  18352. const pt0 = points0.get(i);
  18353. for (let j = 0; j < points1.size(); j++) {
  18354. const pt1 = points1.get(j);
  18355. const dist = pt0.getCoordinate().distance(pt1.getCoordinate());
  18356. if (dist < this._minDistance) {
  18357. this._minDistance = dist;
  18358. locGeom[0] = new GeometryLocation(pt0, 0, pt0.getCoordinate());
  18359. locGeom[1] = new GeometryLocation(pt1, 0, pt1.getCoordinate());
  18360. }
  18361. if (this._minDistance <= this._terminateDistance) return null;
  18362. }
  18363. }
  18364. }
  18365. distance() {
  18366. if (this._geom[0] === null || this._geom[1] === null) throw new IllegalArgumentException('null geometries are not supported');
  18367. if (this._geom[0].isEmpty() || this._geom[1].isEmpty()) return 0.0;
  18368. this.computeMinDistance();
  18369. return this._minDistance;
  18370. }
  18371. computeMinDistanceLines(lines0, lines1, locGeom) {
  18372. for (let i = 0; i < lines0.size(); i++) {
  18373. const line0 = lines0.get(i);
  18374. for (let j = 0; j < lines1.size(); j++) {
  18375. const line1 = lines1.get(j);
  18376. this.computeMinDistance(line0, line1, locGeom);
  18377. if (this._minDistance <= this._terminateDistance) return null;
  18378. }
  18379. }
  18380. }
  18381. }
  18382. var distance = /*#__PURE__*/Object.freeze({
  18383. __proto__: null,
  18384. DistanceOp: DistanceOp
  18385. });
  18386. class EdgeString {
  18387. constructor() {
  18388. EdgeString.constructor_.apply(this, arguments);
  18389. }
  18390. static constructor_() {
  18391. this._factory = null;
  18392. this._directedEdges = new ArrayList();
  18393. this._coordinates = null;
  18394. const factory = arguments[0];
  18395. this._factory = factory;
  18396. }
  18397. getCoordinates() {
  18398. if (this._coordinates === null) {
  18399. let forwardDirectedEdges = 0;
  18400. let reverseDirectedEdges = 0;
  18401. const coordinateList = new CoordinateList();
  18402. for (let i = this._directedEdges.iterator(); i.hasNext();) {
  18403. const directedEdge = i.next();
  18404. if (directedEdge.getEdgeDirection()) forwardDirectedEdges++;else reverseDirectedEdges++;
  18405. coordinateList.add(directedEdge.getEdge().getLine().getCoordinates(), false, directedEdge.getEdgeDirection());
  18406. }
  18407. this._coordinates = coordinateList.toCoordinateArray();
  18408. if (reverseDirectedEdges > forwardDirectedEdges) CoordinateArrays.reverse(this._coordinates);
  18409. }
  18410. return this._coordinates;
  18411. }
  18412. toLineString() {
  18413. return this._factory.createLineString(this.getCoordinates());
  18414. }
  18415. add(directedEdge) {
  18416. this._directedEdges.add(directedEdge);
  18417. }
  18418. }
  18419. class GraphComponent {
  18420. constructor() {
  18421. GraphComponent.constructor_.apply(this, arguments);
  18422. }
  18423. static constructor_() {
  18424. this._isMarked = false;
  18425. this._isVisited = false;
  18426. this._data = null;
  18427. }
  18428. static getComponentWithVisitedState(i, visitedState) {
  18429. while (i.hasNext()) {
  18430. const comp = i.next();
  18431. if (comp.isVisited() === visitedState) return comp;
  18432. }
  18433. return null;
  18434. }
  18435. static setVisited(i, visited) {
  18436. while (i.hasNext()) {
  18437. const comp = i.next();
  18438. comp.setVisited(visited);
  18439. }
  18440. }
  18441. static setMarked(i, marked) {
  18442. while (i.hasNext()) {
  18443. const comp = i.next();
  18444. comp.setMarked(marked);
  18445. }
  18446. }
  18447. setVisited(isVisited) {
  18448. this._isVisited = isVisited;
  18449. }
  18450. isMarked() {
  18451. return this._isMarked;
  18452. }
  18453. setData(data) {
  18454. this._data = data;
  18455. }
  18456. getData() {
  18457. return this._data;
  18458. }
  18459. setMarked(isMarked) {
  18460. this._isMarked = isMarked;
  18461. }
  18462. getContext() {
  18463. return this._data;
  18464. }
  18465. isVisited() {
  18466. return this._isVisited;
  18467. }
  18468. setContext(data) {
  18469. this._data = data;
  18470. }
  18471. }
  18472. class DirectedEdge extends GraphComponent {
  18473. constructor() {
  18474. super();
  18475. DirectedEdge.constructor_.apply(this, arguments);
  18476. }
  18477. static constructor_() {
  18478. this._parentEdge = null;
  18479. this._from = null;
  18480. this._to = null;
  18481. this._p0 = null;
  18482. this._p1 = null;
  18483. this._sym = null;
  18484. this._edgeDirection = null;
  18485. this._quadrant = null;
  18486. this._angle = null;
  18487. if (arguments.length === 0) ; else if (arguments.length === 4) {
  18488. const from = arguments[0],
  18489. to = arguments[1],
  18490. directionPt = arguments[2],
  18491. edgeDirection = arguments[3];
  18492. this._from = from;
  18493. this._to = to;
  18494. this._edgeDirection = edgeDirection;
  18495. this._p0 = from.getCoordinate();
  18496. this._p1 = directionPt;
  18497. const dx = this._p1.x - this._p0.x;
  18498. const dy = this._p1.y - this._p0.y;
  18499. this._quadrant = Quadrant.quadrant(dx, dy);
  18500. this._angle = Math.atan2(dy, dx);
  18501. }
  18502. }
  18503. static toEdges(dirEdges) {
  18504. const edges = new ArrayList();
  18505. for (let i = dirEdges.iterator(); i.hasNext();) edges.add(i.next()._parentEdge);
  18506. return edges;
  18507. }
  18508. isRemoved() {
  18509. return this._parentEdge === null;
  18510. }
  18511. compareDirection(e) {
  18512. if (this._quadrant > e._quadrant) return 1;
  18513. if (this._quadrant < e._quadrant) return -1;
  18514. return Orientation.index(e._p0, e._p1, this._p1);
  18515. }
  18516. getCoordinate() {
  18517. return this._from.getCoordinate();
  18518. }
  18519. print(out) {
  18520. const className = this.getClass().getName();
  18521. const lastDotPos = className.lastIndexOf('.');
  18522. const name = className.substring(lastDotPos + 1);
  18523. out.print(' ' + name + ': ' + this._p0 + ' - ' + this._p1 + ' ' + this._quadrant + ':' + this._angle);
  18524. }
  18525. getDirectionPt() {
  18526. return this._p1;
  18527. }
  18528. getAngle() {
  18529. return this._angle;
  18530. }
  18531. compareTo(obj) {
  18532. const de = obj;
  18533. return this.compareDirection(de);
  18534. }
  18535. getFromNode() {
  18536. return this._from;
  18537. }
  18538. getSym() {
  18539. return this._sym;
  18540. }
  18541. setEdge(parentEdge) {
  18542. this._parentEdge = parentEdge;
  18543. }
  18544. remove() {
  18545. this._sym = null;
  18546. this._parentEdge = null;
  18547. }
  18548. getEdge() {
  18549. return this._parentEdge;
  18550. }
  18551. getQuadrant() {
  18552. return this._quadrant;
  18553. }
  18554. setSym(sym) {
  18555. this._sym = sym;
  18556. }
  18557. getToNode() {
  18558. return this._to;
  18559. }
  18560. getEdgeDirection() {
  18561. return this._edgeDirection;
  18562. }
  18563. get interfaces_() {
  18564. return [Comparable];
  18565. }
  18566. }
  18567. class LineMergeDirectedEdge extends DirectedEdge {
  18568. constructor() {
  18569. super();
  18570. LineMergeDirectedEdge.constructor_.apply(this, arguments);
  18571. }
  18572. static constructor_() {
  18573. const from = arguments[0],
  18574. to = arguments[1],
  18575. directionPt = arguments[2],
  18576. edgeDirection = arguments[3];
  18577. DirectedEdge.constructor_.call(this, from, to, directionPt, edgeDirection);
  18578. }
  18579. getNext() {
  18580. if (this.getToNode().getDegree() !== 2) return null;
  18581. if (this.getToNode().getOutEdges().getEdges().get(0) === this.getSym()) return this.getToNode().getOutEdges().getEdges().get(1);
  18582. Assert.isTrue(this.getToNode().getOutEdges().getEdges().get(1) === this.getSym());
  18583. return this.getToNode().getOutEdges().getEdges().get(0);
  18584. }
  18585. }
  18586. class Edge extends GraphComponent {
  18587. constructor() {
  18588. super();
  18589. Edge.constructor_.apply(this, arguments);
  18590. }
  18591. static constructor_() {
  18592. this._dirEdge = null;
  18593. if (arguments.length === 0) ; else if (arguments.length === 2) {
  18594. const de0 = arguments[0],
  18595. de1 = arguments[1];
  18596. this.setDirectedEdges(de0, de1);
  18597. }
  18598. }
  18599. isRemoved() {
  18600. return this._dirEdge === null;
  18601. }
  18602. setDirectedEdges(de0, de1) {
  18603. this._dirEdge = [de0, de1];
  18604. de0.setEdge(this);
  18605. de1.setEdge(this);
  18606. de0.setSym(de1);
  18607. de1.setSym(de0);
  18608. de0.getFromNode().addOutEdge(de0);
  18609. de1.getFromNode().addOutEdge(de1);
  18610. }
  18611. getDirEdge() {
  18612. if (Number.isInteger(arguments[0])) {
  18613. const i = arguments[0];
  18614. return this._dirEdge[i];
  18615. } else if (arguments[0] instanceof Node) {
  18616. const fromNode = arguments[0];
  18617. if (this._dirEdge[0].getFromNode() === fromNode) return this._dirEdge[0];
  18618. if (this._dirEdge[1].getFromNode() === fromNode) return this._dirEdge[1];
  18619. return null;
  18620. }
  18621. }
  18622. remove() {
  18623. this._dirEdge = null;
  18624. }
  18625. getOppositeNode(node) {
  18626. if (this._dirEdge[0].getFromNode() === node) return this._dirEdge[0].getToNode();
  18627. if (this._dirEdge[1].getFromNode() === node) return this._dirEdge[1].getToNode();
  18628. return null;
  18629. }
  18630. }
  18631. class DirectedEdgeStar {
  18632. constructor() {
  18633. DirectedEdgeStar.constructor_.apply(this, arguments);
  18634. }
  18635. static constructor_() {
  18636. this._outEdges = new ArrayList();
  18637. this._sorted = false;
  18638. }
  18639. getNextEdge(dirEdge) {
  18640. const i = this.getIndex(dirEdge);
  18641. return this._outEdges.get(this.getIndex(i + 1));
  18642. }
  18643. getCoordinate() {
  18644. const it = this.iterator();
  18645. if (!it.hasNext()) return null;
  18646. const e = it.next();
  18647. return e.getCoordinate();
  18648. }
  18649. iterator() {
  18650. this.sortEdges();
  18651. return this._outEdges.iterator();
  18652. }
  18653. sortEdges() {
  18654. if (!this._sorted) {
  18655. Collections.sort(this._outEdges);
  18656. this._sorted = true;
  18657. }
  18658. }
  18659. remove(de) {
  18660. this._outEdges.remove(de);
  18661. }
  18662. getEdges() {
  18663. this.sortEdges();
  18664. return this._outEdges;
  18665. }
  18666. getNextCWEdge(dirEdge) {
  18667. const i = this.getIndex(dirEdge);
  18668. return this._outEdges.get(this.getIndex(i - 1));
  18669. }
  18670. getIndex() {
  18671. if (arguments[0] instanceof Edge) {
  18672. const edge = arguments[0];
  18673. this.sortEdges();
  18674. for (let i = 0; i < this._outEdges.size(); i++) {
  18675. const de = this._outEdges.get(i);
  18676. if (de.getEdge() === edge) return i;
  18677. }
  18678. return -1;
  18679. } else if (arguments[0] instanceof DirectedEdge) {
  18680. const dirEdge = arguments[0];
  18681. this.sortEdges();
  18682. for (let i = 0; i < this._outEdges.size(); i++) {
  18683. const de = this._outEdges.get(i);
  18684. if (de === dirEdge) return i;
  18685. }
  18686. return -1;
  18687. } else if (Number.isInteger(arguments[0])) {
  18688. const i = arguments[0];
  18689. let modi = i % this._outEdges.size();
  18690. if (modi < 0) modi += this._outEdges.size();
  18691. return modi;
  18692. }
  18693. }
  18694. add(de) {
  18695. this._outEdges.add(de);
  18696. this._sorted = false;
  18697. }
  18698. getDegree() {
  18699. return this._outEdges.size();
  18700. }
  18701. }
  18702. class Node extends GraphComponent {
  18703. constructor() {
  18704. super();
  18705. Node.constructor_.apply(this, arguments);
  18706. }
  18707. static constructor_() {
  18708. this._pt = null;
  18709. this._deStar = null;
  18710. if (arguments.length === 1) {
  18711. const pt = arguments[0];
  18712. Node.constructor_.call(this, pt, new DirectedEdgeStar());
  18713. } else if (arguments.length === 2) {
  18714. const pt = arguments[0],
  18715. deStar = arguments[1];
  18716. this._pt = pt;
  18717. this._deStar = deStar;
  18718. }
  18719. }
  18720. static getEdgesBetween(node0, node1) {
  18721. const edges0 = DirectedEdge.toEdges(node0.getOutEdges().getEdges());
  18722. const commonEdges = new HashSet(edges0);
  18723. const edges1 = DirectedEdge.toEdges(node1.getOutEdges().getEdges());
  18724. commonEdges.retainAll(edges1);
  18725. return commonEdges;
  18726. }
  18727. isRemoved() {
  18728. return this._pt === null;
  18729. }
  18730. addOutEdge(de) {
  18731. this._deStar.add(de);
  18732. }
  18733. getCoordinate() {
  18734. return this._pt;
  18735. }
  18736. getOutEdges() {
  18737. return this._deStar;
  18738. }
  18739. remove() {
  18740. if (arguments.length === 0) {
  18741. this._pt = null;
  18742. } else if (arguments.length === 1) {
  18743. const de = arguments[0];
  18744. this._deStar.remove(de);
  18745. }
  18746. }
  18747. getIndex(edge) {
  18748. return this._deStar.getIndex(edge);
  18749. }
  18750. getDegree() {
  18751. return this._deStar.getDegree();
  18752. }
  18753. }
  18754. class LineMergeEdge extends Edge {
  18755. constructor() {
  18756. super();
  18757. LineMergeEdge.constructor_.apply(this, arguments);
  18758. }
  18759. static constructor_() {
  18760. this._line = null;
  18761. const line = arguments[0];
  18762. this._line = line;
  18763. }
  18764. getLine() {
  18765. return this._line;
  18766. }
  18767. }
  18768. class NodeMap {
  18769. constructor() {
  18770. NodeMap.constructor_.apply(this, arguments);
  18771. }
  18772. static constructor_() {
  18773. this._nodeMap = new TreeMap();
  18774. }
  18775. find(coord) {
  18776. return this._nodeMap.get(coord);
  18777. }
  18778. iterator() {
  18779. return this._nodeMap.values().iterator();
  18780. }
  18781. remove(pt) {
  18782. return this._nodeMap.remove(pt);
  18783. }
  18784. values() {
  18785. return this._nodeMap.values();
  18786. }
  18787. add(n) {
  18788. this._nodeMap.put(n.getCoordinate(), n);
  18789. return n;
  18790. }
  18791. }
  18792. class PlanarGraph {
  18793. constructor() {
  18794. PlanarGraph.constructor_.apply(this, arguments);
  18795. }
  18796. static constructor_() {
  18797. this._edges = new HashSet();
  18798. this._dirEdges = new HashSet();
  18799. this._nodeMap = new NodeMap();
  18800. }
  18801. findNodesOfDegree(degree) {
  18802. const nodesFound = new ArrayList();
  18803. for (let i = this.nodeIterator(); i.hasNext();) {
  18804. const node = i.next();
  18805. if (node.getDegree() === degree) nodesFound.add(node);
  18806. }
  18807. return nodesFound;
  18808. }
  18809. dirEdgeIterator() {
  18810. return this._dirEdges.iterator();
  18811. }
  18812. edgeIterator() {
  18813. return this._edges.iterator();
  18814. }
  18815. remove() {
  18816. if (arguments[0] instanceof Edge) {
  18817. const edge = arguments[0];
  18818. this.remove(edge.getDirEdge(0));
  18819. this.remove(edge.getDirEdge(1));
  18820. this._edges.remove(edge);
  18821. edge.remove();
  18822. } else if (arguments[0] instanceof DirectedEdge) {
  18823. const de = arguments[0];
  18824. const sym = de.getSym();
  18825. if (sym !== null) sym.setSym(null);
  18826. de.getFromNode().remove(de);
  18827. de.remove();
  18828. this._dirEdges.remove(de);
  18829. } else if (arguments[0] instanceof Node) {
  18830. const node = arguments[0];
  18831. const outEdges = node.getOutEdges().getEdges();
  18832. for (let i = outEdges.iterator(); i.hasNext();) {
  18833. const de = i.next();
  18834. const sym = de.getSym();
  18835. if (sym !== null) this.remove(sym);
  18836. this._dirEdges.remove(de);
  18837. const edge = de.getEdge();
  18838. if (edge !== null) this._edges.remove(edge);
  18839. }
  18840. this._nodeMap.remove(node.getCoordinate());
  18841. node.remove();
  18842. }
  18843. }
  18844. findNode(pt) {
  18845. return this._nodeMap.find(pt);
  18846. }
  18847. getEdges() {
  18848. return this._edges;
  18849. }
  18850. nodeIterator() {
  18851. return this._nodeMap.iterator();
  18852. }
  18853. contains() {
  18854. if (arguments[0] instanceof Edge) {
  18855. const e = arguments[0];
  18856. return this._edges.contains(e);
  18857. } else if (arguments[0] instanceof DirectedEdge) {
  18858. const de = arguments[0];
  18859. return this._dirEdges.contains(de);
  18860. }
  18861. }
  18862. add() {
  18863. if (arguments[0] instanceof Node) {
  18864. const node = arguments[0];
  18865. this._nodeMap.add(node);
  18866. } else if (arguments[0] instanceof Edge) {
  18867. const edge = arguments[0];
  18868. this._edges.add(edge);
  18869. this.add(edge.getDirEdge(0));
  18870. this.add(edge.getDirEdge(1));
  18871. } else if (arguments[0] instanceof DirectedEdge) {
  18872. const dirEdge = arguments[0];
  18873. this._dirEdges.add(dirEdge);
  18874. }
  18875. }
  18876. getNodes() {
  18877. return this._nodeMap.values();
  18878. }
  18879. }
  18880. class LineMergeGraph extends PlanarGraph {
  18881. constructor() {
  18882. super();
  18883. }
  18884. addEdge(lineString) {
  18885. if (lineString.isEmpty()) return null;
  18886. const coordinates = CoordinateArrays.removeRepeatedPoints(lineString.getCoordinates());
  18887. if (coordinates.length <= 1) return null;
  18888. const startCoordinate = coordinates[0];
  18889. const endCoordinate = coordinates[coordinates.length - 1];
  18890. const startNode = this.getNode(startCoordinate);
  18891. const endNode = this.getNode(endCoordinate);
  18892. const directedEdge0 = new LineMergeDirectedEdge(startNode, endNode, coordinates[1], true);
  18893. const directedEdge1 = new LineMergeDirectedEdge(endNode, startNode, coordinates[coordinates.length - 2], false);
  18894. const edge = new LineMergeEdge(lineString);
  18895. edge.setDirectedEdges(directedEdge0, directedEdge1);
  18896. this.add(edge);
  18897. }
  18898. getNode(coordinate) {
  18899. let node = this.findNode(coordinate);
  18900. if (node === null) {
  18901. node = new Node(coordinate);
  18902. this.add(node);
  18903. }
  18904. return node;
  18905. }
  18906. }
  18907. class LineMerger {
  18908. constructor() {
  18909. LineMerger.constructor_.apply(this, arguments);
  18910. }
  18911. static constructor_() {
  18912. this._graph = new LineMergeGraph();
  18913. this._mergedLineStrings = null;
  18914. this._factory = null;
  18915. this._edgeStrings = null;
  18916. }
  18917. buildEdgeStringsForUnprocessedNodes() {
  18918. for (let i = this._graph.getNodes().iterator(); i.hasNext();) {
  18919. const node = i.next();
  18920. if (!node.isMarked()) {
  18921. Assert.isTrue(node.getDegree() === 2);
  18922. this.buildEdgeStringsStartingAt(node);
  18923. node.setMarked(true);
  18924. }
  18925. }
  18926. }
  18927. buildEdgeStringsForNonDegree2Nodes() {
  18928. for (let i = this._graph.getNodes().iterator(); i.hasNext();) {
  18929. const node = i.next();
  18930. if (node.getDegree() !== 2) {
  18931. this.buildEdgeStringsStartingAt(node);
  18932. node.setMarked(true);
  18933. }
  18934. }
  18935. }
  18936. buildEdgeStringsForObviousStartNodes() {
  18937. this.buildEdgeStringsForNonDegree2Nodes();
  18938. }
  18939. getMergedLineStrings() {
  18940. this.merge();
  18941. return this._mergedLineStrings;
  18942. }
  18943. buildEdgeStringsStartingAt(node) {
  18944. for (let i = node.getOutEdges().iterator(); i.hasNext();) {
  18945. const directedEdge = i.next();
  18946. if (directedEdge.getEdge().isMarked()) continue;
  18947. this._edgeStrings.add(this.buildEdgeStringStartingWith(directedEdge));
  18948. }
  18949. }
  18950. merge() {
  18951. if (this._mergedLineStrings !== null) return null;
  18952. GraphComponent.setMarked(this._graph.nodeIterator(), false);
  18953. GraphComponent.setMarked(this._graph.edgeIterator(), false);
  18954. this._edgeStrings = new ArrayList();
  18955. this.buildEdgeStringsForObviousStartNodes();
  18956. this.buildEdgeStringsForIsolatedLoops();
  18957. this._mergedLineStrings = new ArrayList();
  18958. for (let i = this._edgeStrings.iterator(); i.hasNext();) {
  18959. const edgeString = i.next();
  18960. this._mergedLineStrings.add(edgeString.toLineString());
  18961. }
  18962. }
  18963. addLineString(lineString) {
  18964. if (this._factory === null) this._factory = lineString.getFactory();
  18965. this._graph.addEdge(lineString);
  18966. }
  18967. buildEdgeStringStartingWith(start) {
  18968. const edgeString = new EdgeString(this._factory);
  18969. let current = start;
  18970. do {
  18971. edgeString.add(current);
  18972. current.getEdge().setMarked(true);
  18973. current = current.getNext();
  18974. } while (current !== null && current !== start);
  18975. return edgeString;
  18976. }
  18977. add() {
  18978. if (arguments[0] instanceof Geometry) {
  18979. const geometry = arguments[0];
  18980. for (let i = 0; i < geometry.getNumGeometries(); i++) {
  18981. const component = geometry.getGeometryN(i);
  18982. if (component instanceof LineString) this.addLineString(component);
  18983. }
  18984. } else if (hasInterface(arguments[0], Collection)) {
  18985. const geometries = arguments[0];
  18986. this._mergedLineStrings = null;
  18987. for (let i = geometries.iterator(); i.hasNext();) {
  18988. const geometry = i.next();
  18989. this.add(geometry);
  18990. }
  18991. }
  18992. }
  18993. buildEdgeStringsForIsolatedLoops() {
  18994. this.buildEdgeStringsForUnprocessedNodes();
  18995. }
  18996. }
  18997. class Subgraph {
  18998. constructor() {
  18999. Subgraph.constructor_.apply(this, arguments);
  19000. }
  19001. static constructor_() {
  19002. this._parentGraph = null;
  19003. this._edges = new HashSet();
  19004. this._dirEdges = new ArrayList();
  19005. this._nodeMap = new NodeMap();
  19006. const parentGraph = arguments[0];
  19007. this._parentGraph = parentGraph;
  19008. }
  19009. dirEdgeIterator() {
  19010. return this._dirEdges.iterator();
  19011. }
  19012. edgeIterator() {
  19013. return this._edges.iterator();
  19014. }
  19015. getParent() {
  19016. return this._parentGraph;
  19017. }
  19018. nodeIterator() {
  19019. return this._nodeMap.iterator();
  19020. }
  19021. contains(e) {
  19022. return this._edges.contains(e);
  19023. }
  19024. add(e) {
  19025. if (this._edges.contains(e)) return null;
  19026. this._edges.add(e);
  19027. this._dirEdges.add(e.getDirEdge(0));
  19028. this._dirEdges.add(e.getDirEdge(1));
  19029. this._nodeMap.add(e.getDirEdge(0).getFromNode());
  19030. this._nodeMap.add(e.getDirEdge(1).getFromNode());
  19031. }
  19032. }
  19033. class ConnectedSubgraphFinder {
  19034. constructor() {
  19035. ConnectedSubgraphFinder.constructor_.apply(this, arguments);
  19036. }
  19037. static constructor_() {
  19038. this._graph = null;
  19039. const graph = arguments[0];
  19040. this._graph = graph;
  19041. }
  19042. addReachable(startNode, subgraph) {
  19043. const nodeStack = new Stack();
  19044. nodeStack.add(startNode);
  19045. while (!nodeStack.empty()) {
  19046. const node = nodeStack.pop();
  19047. this.addEdges(node, nodeStack, subgraph);
  19048. }
  19049. }
  19050. findSubgraph(node) {
  19051. const subgraph = new Subgraph(this._graph);
  19052. this.addReachable(node, subgraph);
  19053. return subgraph;
  19054. }
  19055. getConnectedSubgraphs() {
  19056. const subgraphs = new ArrayList();
  19057. GraphComponent.setVisited(this._graph.nodeIterator(), false);
  19058. for (let i = this._graph.edgeIterator(); i.hasNext();) {
  19059. const e = i.next();
  19060. const node = e.getDirEdge(0).getFromNode();
  19061. if (!node.isVisited()) subgraphs.add(this.findSubgraph(node));
  19062. }
  19063. return subgraphs;
  19064. }
  19065. addEdges(node, nodeStack, subgraph) {
  19066. node.setVisited(true);
  19067. for (let i = node.getOutEdges().iterator(); i.hasNext();) {
  19068. const de = i.next();
  19069. subgraph.add(de.getEdge());
  19070. const toNode = de.getToNode();
  19071. if (!toNode.isVisited()) nodeStack.push(toNode);
  19072. }
  19073. }
  19074. }
  19075. class LineSequencer {
  19076. constructor() {
  19077. LineSequencer.constructor_.apply(this, arguments);
  19078. }
  19079. static constructor_() {
  19080. this._graph = new LineMergeGraph();
  19081. this._factory = new GeometryFactory();
  19082. this._lineCount = 0;
  19083. this._isRun = false;
  19084. this._sequencedGeometry = null;
  19085. this._isSequenceable = false;
  19086. }
  19087. static findUnvisitedBestOrientedDE(node) {
  19088. let wellOrientedDE = null;
  19089. let unvisitedDE = null;
  19090. for (let i = node.getOutEdges().iterator(); i.hasNext();) {
  19091. const de = i.next();
  19092. if (!de.getEdge().isVisited()) {
  19093. unvisitedDE = de;
  19094. if (de.getEdgeDirection()) wellOrientedDE = de;
  19095. }
  19096. }
  19097. if (wellOrientedDE !== null) return wellOrientedDE;
  19098. return unvisitedDE;
  19099. }
  19100. static findLowestDegreeNode(graph) {
  19101. let minDegree = Integer.MAX_VALUE;
  19102. let minDegreeNode = null;
  19103. for (let i = graph.nodeIterator(); i.hasNext();) {
  19104. const node = i.next();
  19105. if (minDegreeNode === null || node.getDegree() < minDegree) {
  19106. minDegree = node.getDegree();
  19107. minDegreeNode = node;
  19108. }
  19109. }
  19110. return minDegreeNode;
  19111. }
  19112. static isSequenced(geom) {
  19113. if (!(geom instanceof MultiLineString)) return true;
  19114. const mls = geom;
  19115. const prevSubgraphNodes = new TreeSet();
  19116. let lastNode = null;
  19117. const currNodes = new ArrayList();
  19118. for (let i = 0; i < mls.getNumGeometries(); i++) {
  19119. const line = mls.getGeometryN(i);
  19120. const startNode = line.getCoordinateN(0);
  19121. const endNode = line.getCoordinateN(line.getNumPoints() - 1);
  19122. if (prevSubgraphNodes.contains(startNode)) return false;
  19123. if (prevSubgraphNodes.contains(endNode)) return false;
  19124. if (lastNode !== null) if (!startNode.equals(lastNode)) {
  19125. prevSubgraphNodes.addAll(currNodes);
  19126. currNodes.clear();
  19127. }
  19128. currNodes.add(startNode);
  19129. currNodes.add(endNode);
  19130. lastNode = endNode;
  19131. }
  19132. return true;
  19133. }
  19134. static reverse(line) {
  19135. const pts = line.getCoordinates();
  19136. const revPts = new Array(pts.length).fill(null);
  19137. const len = pts.length;
  19138. for (let i = 0; i < len; i++) revPts[len - 1 - i] = new Coordinate(pts[i]);
  19139. return line.getFactory().createLineString(revPts);
  19140. }
  19141. static sequence(geom) {
  19142. const sequencer = new LineSequencer();
  19143. sequencer.add(geom);
  19144. return sequencer.getSequencedLineStrings();
  19145. }
  19146. addLine(lineString) {
  19147. if (this._factory === null) this._factory = lineString.getFactory();
  19148. this._graph.addEdge(lineString);
  19149. this._lineCount++;
  19150. }
  19151. hasSequence(graph) {
  19152. let oddDegreeCount = 0;
  19153. for (let i = graph.nodeIterator(); i.hasNext();) {
  19154. const node = i.next();
  19155. if (node.getDegree() % 2 === 1) oddDegreeCount++;
  19156. }
  19157. return oddDegreeCount <= 2;
  19158. }
  19159. computeSequence() {
  19160. if (this._isRun) return null;
  19161. this._isRun = true;
  19162. const sequences = this.findSequences();
  19163. if (sequences === null) return null;
  19164. this._sequencedGeometry = this.buildSequencedGeometry(sequences);
  19165. this._isSequenceable = true;
  19166. const finalLineCount = this._sequencedGeometry.getNumGeometries();
  19167. Assert.isTrue(this._lineCount === finalLineCount, 'Lines were missing from result');
  19168. Assert.isTrue(this._sequencedGeometry instanceof LineString || this._sequencedGeometry instanceof MultiLineString, 'Result is not lineal');
  19169. }
  19170. findSequences() {
  19171. const sequences = new ArrayList();
  19172. const csFinder = new ConnectedSubgraphFinder(this._graph);
  19173. const subgraphs = csFinder.getConnectedSubgraphs();
  19174. for (let i = subgraphs.iterator(); i.hasNext();) {
  19175. const subgraph = i.next();
  19176. if (this.hasSequence(subgraph)) {
  19177. const seq = this.findSequence(subgraph);
  19178. sequences.add(seq);
  19179. } else {
  19180. return null;
  19181. }
  19182. }
  19183. return sequences;
  19184. }
  19185. addReverseSubpath(de, lit, expectedClosed) {
  19186. const endNode = de.getToNode();
  19187. let fromNode = null;
  19188. while (true) {
  19189. lit.add(de.getSym());
  19190. de.getEdge().setVisited(true);
  19191. fromNode = de.getFromNode();
  19192. const unvisitedOutDE = LineSequencer.findUnvisitedBestOrientedDE(fromNode);
  19193. if (unvisitedOutDE === null) break;
  19194. de = unvisitedOutDE.getSym();
  19195. }
  19196. if (expectedClosed) Assert.isTrue(fromNode === endNode, 'path not contiguous');
  19197. }
  19198. findSequence(graph) {
  19199. GraphComponent.setVisited(graph.edgeIterator(), false);
  19200. const startNode = LineSequencer.findLowestDegreeNode(graph);
  19201. const startDE = startNode.getOutEdges().iterator().next();
  19202. const startDESym = startDE.getSym();
  19203. const seq = new LinkedList();
  19204. const lit = seq.listIterator();
  19205. this.addReverseSubpath(startDESym, lit, false);
  19206. while (lit.hasPrevious()) {
  19207. const prev = lit.previous();
  19208. const unvisitedOutDE = LineSequencer.findUnvisitedBestOrientedDE(prev.getFromNode());
  19209. if (unvisitedOutDE !== null) this.addReverseSubpath(unvisitedOutDE.getSym(), lit, true);
  19210. }
  19211. const orientedSeq = this.orient(seq);
  19212. return orientedSeq;
  19213. }
  19214. reverse(seq) {
  19215. const newSeq = new LinkedList();
  19216. for (let i = seq.iterator(); i.hasNext();) {
  19217. const de = i.next();
  19218. newSeq.addFirst(de.getSym());
  19219. }
  19220. return newSeq;
  19221. }
  19222. orient(seq) {
  19223. const startEdge = seq.get(0);
  19224. const endEdge = seq.get(seq.size() - 1);
  19225. const startNode = startEdge.getFromNode();
  19226. const endNode = endEdge.getToNode();
  19227. let flipSeq = false;
  19228. const hasDegree1Node = startNode.getDegree() === 1 || endNode.getDegree() === 1;
  19229. if (hasDegree1Node) {
  19230. let hasObviousStartNode = false;
  19231. if (endEdge.getToNode().getDegree() === 1 && endEdge.getEdgeDirection() === false) {
  19232. hasObviousStartNode = true;
  19233. flipSeq = true;
  19234. }
  19235. if (startEdge.getFromNode().getDegree() === 1 && startEdge.getEdgeDirection() === true) {
  19236. hasObviousStartNode = true;
  19237. flipSeq = false;
  19238. }
  19239. if (!hasObviousStartNode) if (startEdge.getFromNode().getDegree() === 1) flipSeq = true;
  19240. }
  19241. if (flipSeq) return this.reverse(seq);
  19242. return seq;
  19243. }
  19244. buildSequencedGeometry(sequences) {
  19245. const lines = new ArrayList();
  19246. for (let i1 = sequences.iterator(); i1.hasNext();) {
  19247. const seq = i1.next();
  19248. for (let i2 = seq.iterator(); i2.hasNext();) {
  19249. const de = i2.next();
  19250. const e = de.getEdge();
  19251. const line = e.getLine();
  19252. let lineToAdd = line;
  19253. if (!de.getEdgeDirection() && !line.isClosed()) lineToAdd = LineSequencer.reverse(line);
  19254. lines.add(lineToAdd);
  19255. }
  19256. }
  19257. if (lines.size() === 0) return this._factory.createMultiLineString(new Array(0).fill(null));
  19258. return this._factory.buildGeometry(lines);
  19259. }
  19260. getSequencedLineStrings() {
  19261. this.computeSequence();
  19262. return this._sequencedGeometry;
  19263. }
  19264. isSequenceable() {
  19265. this.computeSequence();
  19266. return this._isSequenceable;
  19267. }
  19268. add() {
  19269. if (hasInterface(arguments[0], Collection)) {
  19270. const geometries = arguments[0];
  19271. for (let i = geometries.iterator(); i.hasNext();) {
  19272. const geometry = i.next();
  19273. this.add(geometry);
  19274. }
  19275. } else if (arguments[0] instanceof Geometry) {
  19276. const geometry = arguments[0];
  19277. geometry.apply(new class {
  19278. get interfaces_() {
  19279. return [GeometryComponentFilter];
  19280. }
  19281. filter(component) {
  19282. if (component instanceof LineString) this.addLine(component);
  19283. }
  19284. }());
  19285. }
  19286. }
  19287. }
  19288. var linemerge = /*#__PURE__*/Object.freeze({
  19289. __proto__: null,
  19290. LineMerger: LineMerger,
  19291. LineSequencer: LineSequencer
  19292. });
  19293. class LineStringSnapper {
  19294. constructor() {
  19295. LineStringSnapper.constructor_.apply(this, arguments);
  19296. }
  19297. static constructor_() {
  19298. this._snapTolerance = 0.0;
  19299. this._srcPts = null;
  19300. this._seg = new LineSegment();
  19301. this._allowSnappingToSourceVertices = false;
  19302. this._isClosed = false;
  19303. if (arguments[0] instanceof LineString && typeof arguments[1] === 'number') {
  19304. const srcLine = arguments[0],
  19305. snapTolerance = arguments[1];
  19306. LineStringSnapper.constructor_.call(this, srcLine.getCoordinates(), snapTolerance);
  19307. } else if (arguments[0] instanceof Array && typeof arguments[1] === 'number') {
  19308. const srcPts = arguments[0],
  19309. snapTolerance = arguments[1];
  19310. this._srcPts = srcPts;
  19311. this._isClosed = LineStringSnapper.isClosed(srcPts);
  19312. this._snapTolerance = snapTolerance;
  19313. }
  19314. }
  19315. static isClosed(pts) {
  19316. if (pts.length <= 1) return false;
  19317. return pts[0].equals2D(pts[pts.length - 1]);
  19318. }
  19319. snapVertices(srcCoords, snapPts) {
  19320. const end = this._isClosed ? srcCoords.size() - 1 : srcCoords.size();
  19321. for (let i = 0; i < end; i++) {
  19322. const srcPt = srcCoords.get(i);
  19323. const snapVert = this.findSnapForVertex(srcPt, snapPts);
  19324. if (snapVert !== null) {
  19325. srcCoords.set(i, new Coordinate(snapVert));
  19326. if (i === 0 && this._isClosed) srcCoords.set(srcCoords.size() - 1, new Coordinate(snapVert));
  19327. }
  19328. }
  19329. }
  19330. findSnapForVertex(pt, snapPts) {
  19331. for (let i = 0; i < snapPts.length; i++) {
  19332. if (pt.equals2D(snapPts[i])) return null;
  19333. if (pt.distance(snapPts[i]) < this._snapTolerance) return snapPts[i];
  19334. }
  19335. return null;
  19336. }
  19337. snapTo(snapPts) {
  19338. const coordList = new CoordinateList(this._srcPts);
  19339. this.snapVertices(coordList, snapPts);
  19340. this.snapSegments(coordList, snapPts);
  19341. const newPts = coordList.toCoordinateArray();
  19342. return newPts;
  19343. }
  19344. snapSegments(srcCoords, snapPts) {
  19345. if (snapPts.length === 0) return null;
  19346. let distinctPtCount = snapPts.length;
  19347. if (snapPts[0].equals2D(snapPts[snapPts.length - 1])) distinctPtCount = snapPts.length - 1;
  19348. for (let i = 0; i < distinctPtCount; i++) {
  19349. const snapPt = snapPts[i];
  19350. const index = this.findSegmentIndexToSnap(snapPt, srcCoords);
  19351. if (index >= 0) srcCoords.add(index + 1, new Coordinate(snapPt), false);
  19352. }
  19353. }
  19354. findSegmentIndexToSnap(snapPt, srcCoords) {
  19355. let minDist = Double.MAX_VALUE;
  19356. let snapIndex = -1;
  19357. for (let i = 0; i < srcCoords.size() - 1; i++) {
  19358. this._seg.p0 = srcCoords.get(i);
  19359. this._seg.p1 = srcCoords.get(i + 1);
  19360. if (this._seg.p0.equals2D(snapPt) || this._seg.p1.equals2D(snapPt)) if (this._allowSnappingToSourceVertices) continue;else return -1;
  19361. const dist = this._seg.distance(snapPt);
  19362. if (dist < this._snapTolerance && dist < minDist) {
  19363. minDist = dist;
  19364. snapIndex = i;
  19365. }
  19366. }
  19367. return snapIndex;
  19368. }
  19369. setAllowSnappingToSourceVertices(allowSnappingToSourceVertices) {
  19370. this._allowSnappingToSourceVertices = allowSnappingToSourceVertices;
  19371. }
  19372. }
  19373. class GeometrySnapper {
  19374. constructor() {
  19375. GeometrySnapper.constructor_.apply(this, arguments);
  19376. }
  19377. static constructor_() {
  19378. this._srcGeom = null;
  19379. const srcGeom = arguments[0];
  19380. this._srcGeom = srcGeom;
  19381. }
  19382. static snap(g0, g1, snapTolerance) {
  19383. const snapGeom = new Array(2).fill(null);
  19384. const snapper0 = new GeometrySnapper(g0);
  19385. snapGeom[0] = snapper0.snapTo(g1, snapTolerance);
  19386. const snapper1 = new GeometrySnapper(g1);
  19387. snapGeom[1] = snapper1.snapTo(snapGeom[0], snapTolerance);
  19388. return snapGeom;
  19389. }
  19390. static computeOverlaySnapTolerance() {
  19391. if (arguments.length === 1) {
  19392. const g = arguments[0];
  19393. let snapTolerance = GeometrySnapper.computeSizeBasedSnapTolerance(g);
  19394. const pm = g.getPrecisionModel();
  19395. if (pm.getType() === PrecisionModel.FIXED) {
  19396. const fixedSnapTol = 1 / pm.getScale() * 2 / 1.415;
  19397. if (fixedSnapTol > snapTolerance) snapTolerance = fixedSnapTol;
  19398. }
  19399. return snapTolerance;
  19400. } else if (arguments.length === 2) {
  19401. const g0 = arguments[0],
  19402. g1 = arguments[1];
  19403. return Math.min(GeometrySnapper.computeOverlaySnapTolerance(g0), GeometrySnapper.computeOverlaySnapTolerance(g1));
  19404. }
  19405. }
  19406. static computeSizeBasedSnapTolerance(g) {
  19407. const env = g.getEnvelopeInternal();
  19408. const minDimension = Math.min(env.getHeight(), env.getWidth());
  19409. const snapTol = minDimension * GeometrySnapper.SNAP_PRECISION_FACTOR;
  19410. return snapTol;
  19411. }
  19412. static snapToSelf(geom, snapTolerance, cleanResult) {
  19413. const snapper0 = new GeometrySnapper(geom);
  19414. return snapper0.snapToSelf(snapTolerance, cleanResult);
  19415. }
  19416. snapTo(snapGeom, snapTolerance) {
  19417. const snapPts = this.extractTargetCoordinates(snapGeom);
  19418. const snapTrans = new SnapTransformer(snapTolerance, snapPts);
  19419. return snapTrans.transform(this._srcGeom);
  19420. }
  19421. snapToSelf(snapTolerance, cleanResult) {
  19422. const snapPts = this.extractTargetCoordinates(this._srcGeom);
  19423. const snapTrans = new SnapTransformer(snapTolerance, snapPts, true);
  19424. const snappedGeom = snapTrans.transform(this._srcGeom);
  19425. let result = snappedGeom;
  19426. if (cleanResult && hasInterface(result, Polygonal)) result = snappedGeom.buffer(0);
  19427. return result;
  19428. }
  19429. computeSnapTolerance(ringPts) {
  19430. const minSegLen = this.computeMinimumSegmentLength(ringPts);
  19431. const snapTol = minSegLen / 10;
  19432. return snapTol;
  19433. }
  19434. extractTargetCoordinates(g) {
  19435. const ptSet = new TreeSet();
  19436. const pts = g.getCoordinates();
  19437. for (let i = 0; i < pts.length; i++) ptSet.add(pts[i]);
  19438. return ptSet.toArray(new Array(0).fill(null));
  19439. }
  19440. computeMinimumSegmentLength(pts) {
  19441. let minSegLen = Double.MAX_VALUE;
  19442. for (let i = 0; i < pts.length - 1; i++) {
  19443. const segLen = pts[i].distance(pts[i + 1]);
  19444. if (segLen < minSegLen) minSegLen = segLen;
  19445. }
  19446. return minSegLen;
  19447. }
  19448. }
  19449. GeometrySnapper.SNAP_PRECISION_FACTOR = 1e-9;
  19450. class SnapTransformer extends GeometryTransformer {
  19451. constructor() {
  19452. super();
  19453. SnapTransformer.constructor_.apply(this, arguments);
  19454. }
  19455. static constructor_() {
  19456. this._snapTolerance = null;
  19457. this._snapPts = null;
  19458. this._isSelfSnap = false;
  19459. if (arguments.length === 2) {
  19460. const snapTolerance = arguments[0],
  19461. snapPts = arguments[1];
  19462. this._snapTolerance = snapTolerance;
  19463. this._snapPts = snapPts;
  19464. } else if (arguments.length === 3) {
  19465. const snapTolerance = arguments[0],
  19466. snapPts = arguments[1],
  19467. isSelfSnap = arguments[2];
  19468. this._snapTolerance = snapTolerance;
  19469. this._snapPts = snapPts;
  19470. this._isSelfSnap = isSelfSnap;
  19471. }
  19472. }
  19473. snapLine(srcPts, snapPts) {
  19474. const snapper = new LineStringSnapper(srcPts, this._snapTolerance);
  19475. snapper.setAllowSnappingToSourceVertices(this._isSelfSnap);
  19476. return snapper.snapTo(snapPts);
  19477. }
  19478. transformCoordinates(coords, parent) {
  19479. const srcPts = coords.toCoordinateArray();
  19480. const newPts = this.snapLine(srcPts, this._snapPts);
  19481. return this._factory.getCoordinateSequenceFactory().create(newPts);
  19482. }
  19483. }
  19484. var snap = /*#__PURE__*/Object.freeze({
  19485. __proto__: null,
  19486. GeometrySnapper: GeometrySnapper,
  19487. LineStringSnapper: LineStringSnapper
  19488. });
  19489. class BasicSegmentString {
  19490. constructor() {
  19491. BasicSegmentString.constructor_.apply(this, arguments);
  19492. }
  19493. static constructor_() {
  19494. this._pts = null;
  19495. this._data = null;
  19496. const pts = arguments[0],
  19497. data = arguments[1];
  19498. this._pts = pts;
  19499. this._data = data;
  19500. }
  19501. getCoordinates() {
  19502. return this._pts;
  19503. }
  19504. size() {
  19505. return this._pts.length;
  19506. }
  19507. getCoordinate(i) {
  19508. return this._pts[i];
  19509. }
  19510. isClosed() {
  19511. return this._pts[0].equals(this._pts[this._pts.length - 1]);
  19512. }
  19513. getSegmentOctant(index) {
  19514. if (index === this._pts.length - 1) return -1;
  19515. return Octant.octant(this.getCoordinate(index), this.getCoordinate(index + 1));
  19516. }
  19517. setData(data) {
  19518. this._data = data;
  19519. }
  19520. getData() {
  19521. return this._data;
  19522. }
  19523. toString() {
  19524. return WKTWriter.toLineString(new CoordinateArraySequence(this._pts));
  19525. }
  19526. get interfaces_() {
  19527. return [SegmentString];
  19528. }
  19529. }
  19530. class NodingIntersectionFinder {
  19531. constructor() {
  19532. NodingIntersectionFinder.constructor_.apply(this, arguments);
  19533. }
  19534. static constructor_() {
  19535. this._findAllIntersections = false;
  19536. this._isCheckEndSegmentsOnly = false;
  19537. this._keepIntersections = true;
  19538. this._isInteriorIntersectionsOnly = false;
  19539. this._li = null;
  19540. this._interiorIntersection = null;
  19541. this._intSegments = null;
  19542. this._intersections = new ArrayList();
  19543. this._intersectionCount = 0;
  19544. const li = arguments[0];
  19545. this._li = li;
  19546. this._interiorIntersection = null;
  19547. }
  19548. static createAllIntersectionsFinder(li) {
  19549. const finder = new NodingIntersectionFinder(li);
  19550. finder.setFindAllIntersections(true);
  19551. return finder;
  19552. }
  19553. static isInteriorVertexIntersection() {
  19554. if (arguments.length === 4) {
  19555. const p0 = arguments[0],
  19556. p1 = arguments[1],
  19557. isEnd0 = arguments[2],
  19558. isEnd1 = arguments[3];
  19559. if (isEnd0 && isEnd1) return false;
  19560. if (p0.equals2D(p1)) return true;
  19561. return false;
  19562. } else if (arguments.length === 8) {
  19563. const p00 = arguments[0],
  19564. p01 = arguments[1],
  19565. p10 = arguments[2],
  19566. p11 = arguments[3],
  19567. isEnd00 = arguments[4],
  19568. isEnd01 = arguments[5],
  19569. isEnd10 = arguments[6],
  19570. isEnd11 = arguments[7];
  19571. if (NodingIntersectionFinder.isInteriorVertexIntersection(p00, p10, isEnd00, isEnd10)) return true;
  19572. if (NodingIntersectionFinder.isInteriorVertexIntersection(p00, p11, isEnd00, isEnd11)) return true;
  19573. if (NodingIntersectionFinder.isInteriorVertexIntersection(p01, p10, isEnd01, isEnd10)) return true;
  19574. if (NodingIntersectionFinder.isInteriorVertexIntersection(p01, p11, isEnd01, isEnd11)) return true;
  19575. return false;
  19576. }
  19577. }
  19578. static createInteriorIntersectionCounter(li) {
  19579. const finder = new NodingIntersectionFinder(li);
  19580. finder.setInteriorIntersectionsOnly(true);
  19581. finder.setFindAllIntersections(true);
  19582. finder.setKeepIntersections(false);
  19583. return finder;
  19584. }
  19585. static createIntersectionCounter(li) {
  19586. const finder = new NodingIntersectionFinder(li);
  19587. finder.setFindAllIntersections(true);
  19588. finder.setKeepIntersections(false);
  19589. return finder;
  19590. }
  19591. static isEndSegment(segStr, index) {
  19592. if (index === 0) return true;
  19593. if (index >= segStr.size() - 2) return true;
  19594. return false;
  19595. }
  19596. static createAnyIntersectionFinder(li) {
  19597. return new NodingIntersectionFinder(li);
  19598. }
  19599. static createInteriorIntersectionsFinder(li) {
  19600. const finder = new NodingIntersectionFinder(li);
  19601. finder.setFindAllIntersections(true);
  19602. finder.setInteriorIntersectionsOnly(true);
  19603. return finder;
  19604. }
  19605. setCheckEndSegmentsOnly(isCheckEndSegmentsOnly) {
  19606. this._isCheckEndSegmentsOnly = isCheckEndSegmentsOnly;
  19607. }
  19608. getIntersectionSegments() {
  19609. return this._intSegments;
  19610. }
  19611. count() {
  19612. return this._intersectionCount;
  19613. }
  19614. getIntersections() {
  19615. return this._intersections;
  19616. }
  19617. setFindAllIntersections(findAllIntersections) {
  19618. this._findAllIntersections = findAllIntersections;
  19619. }
  19620. setKeepIntersections(keepIntersections) {
  19621. this._keepIntersections = keepIntersections;
  19622. }
  19623. getIntersection() {
  19624. return this._interiorIntersection;
  19625. }
  19626. processIntersections(e0, segIndex0, e1, segIndex1) {
  19627. if (!this._findAllIntersections && this.hasIntersection()) return null;
  19628. const isSameSegString = e0 === e1;
  19629. const isSameSegment = isSameSegString && segIndex0 === segIndex1;
  19630. if (isSameSegment) return null;
  19631. if (this._isCheckEndSegmentsOnly) {
  19632. const isEndSegPresent = NodingIntersectionFinder.isEndSegment(e0, segIndex0) || NodingIntersectionFinder.isEndSegment(e1, segIndex1);
  19633. if (!isEndSegPresent) return null;
  19634. }
  19635. const p00 = e0.getCoordinate(segIndex0);
  19636. const p01 = e0.getCoordinate(segIndex0 + 1);
  19637. const p10 = e1.getCoordinate(segIndex1);
  19638. const p11 = e1.getCoordinate(segIndex1 + 1);
  19639. const isEnd00 = segIndex0 === 0;
  19640. const isEnd01 = segIndex0 + 2 === e0.size();
  19641. const isEnd10 = segIndex1 === 0;
  19642. const isEnd11 = segIndex1 + 2 === e1.size();
  19643. this._li.computeIntersection(p00, p01, p10, p11);
  19644. const isInteriorInt = this._li.hasIntersection() && this._li.isInteriorIntersection();
  19645. let isInteriorVertexInt = false;
  19646. if (!this._isInteriorIntersectionsOnly) {
  19647. const isAdjacentSegment = isSameSegString && Math.abs(segIndex1 - segIndex0) <= 1;
  19648. isInteriorVertexInt = !isAdjacentSegment && NodingIntersectionFinder.isInteriorVertexIntersection(p00, p01, p10, p11, isEnd00, isEnd01, isEnd10, isEnd11);
  19649. }
  19650. if (isInteriorInt || isInteriorVertexInt) {
  19651. this._intSegments = new Array(4).fill(null);
  19652. this._intSegments[0] = p00;
  19653. this._intSegments[1] = p01;
  19654. this._intSegments[2] = p10;
  19655. this._intSegments[3] = p11;
  19656. this._interiorIntersection = this._li.getIntersection(0);
  19657. if (this._keepIntersections) this._intersections.add(this._interiorIntersection);
  19658. this._intersectionCount++;
  19659. }
  19660. }
  19661. hasIntersection() {
  19662. return this._interiorIntersection !== null;
  19663. }
  19664. isDone() {
  19665. if (this._findAllIntersections) return false;
  19666. return this._interiorIntersection !== null;
  19667. }
  19668. setInteriorIntersectionsOnly(isInteriorIntersectionsOnly) {
  19669. this._isInteriorIntersectionsOnly = isInteriorIntersectionsOnly;
  19670. }
  19671. get interfaces_() {
  19672. return [SegmentIntersector];
  19673. }
  19674. }
  19675. class FastNodingValidator {
  19676. constructor() {
  19677. FastNodingValidator.constructor_.apply(this, arguments);
  19678. }
  19679. static constructor_() {
  19680. this._li = new RobustLineIntersector();
  19681. this._segStrings = null;
  19682. this._findAllIntersections = false;
  19683. this._segInt = null;
  19684. this._isValid = true;
  19685. const segStrings = arguments[0];
  19686. this._segStrings = segStrings;
  19687. }
  19688. static computeIntersections(segStrings) {
  19689. const nv = new FastNodingValidator(segStrings);
  19690. nv.setFindAllIntersections(true);
  19691. nv.isValid();
  19692. return nv.getIntersections();
  19693. }
  19694. execute() {
  19695. if (this._segInt !== null) return null;
  19696. this.checkInteriorIntersections();
  19697. }
  19698. getIntersections() {
  19699. return this._segInt.getIntersections();
  19700. }
  19701. isValid() {
  19702. this.execute();
  19703. return this._isValid;
  19704. }
  19705. setFindAllIntersections(findAllIntersections) {
  19706. this._findAllIntersections = findAllIntersections;
  19707. }
  19708. checkInteriorIntersections() {
  19709. this._isValid = true;
  19710. this._segInt = new NodingIntersectionFinder(this._li);
  19711. this._segInt.setFindAllIntersections(this._findAllIntersections);
  19712. const noder = new MCIndexNoder();
  19713. noder.setSegmentIntersector(this._segInt);
  19714. noder.computeNodes(this._segStrings);
  19715. if (this._segInt.hasIntersection()) {
  19716. this._isValid = false;
  19717. return null;
  19718. }
  19719. }
  19720. checkValid() {
  19721. this.execute();
  19722. if (!this._isValid) throw new TopologyException(this.getErrorMessage(), this._segInt.getIntersection());
  19723. }
  19724. getErrorMessage() {
  19725. if (this._isValid) return 'no intersections found';
  19726. const intSegs = this._segInt.getIntersectionSegments();
  19727. return 'found non-noded intersection between ' + WKTWriter.toLineString(intSegs[0], intSegs[1]) + ' and ' + WKTWriter.toLineString(intSegs[2], intSegs[3]);
  19728. }
  19729. }
  19730. class EdgeNodingValidator {
  19731. constructor() {
  19732. EdgeNodingValidator.constructor_.apply(this, arguments);
  19733. }
  19734. static constructor_() {
  19735. this._nv = null;
  19736. const edges = arguments[0];
  19737. this._nv = new FastNodingValidator(EdgeNodingValidator.toSegmentStrings(edges));
  19738. }
  19739. static toSegmentStrings(edges) {
  19740. const segStrings = new ArrayList();
  19741. for (let i = edges.iterator(); i.hasNext();) {
  19742. const e = i.next();
  19743. segStrings.add(new BasicSegmentString(e.getCoordinates(), e));
  19744. }
  19745. return segStrings;
  19746. }
  19747. static checkValid(edges) {
  19748. const validator = new EdgeNodingValidator(edges);
  19749. validator.checkValid();
  19750. }
  19751. checkValid() {
  19752. this._nv.checkValid();
  19753. }
  19754. }
  19755. class LineBuilder {
  19756. constructor() {
  19757. LineBuilder.constructor_.apply(this, arguments);
  19758. }
  19759. static constructor_() {
  19760. this._op = null;
  19761. this._geometryFactory = null;
  19762. this._ptLocator = null;
  19763. this._lineEdgesList = new ArrayList();
  19764. this._resultLineList = new ArrayList();
  19765. const op = arguments[0],
  19766. geometryFactory = arguments[1],
  19767. ptLocator = arguments[2];
  19768. this._op = op;
  19769. this._geometryFactory = geometryFactory;
  19770. this._ptLocator = ptLocator;
  19771. }
  19772. collectLines(opCode) {
  19773. for (let it = this._op.getGraph().getEdgeEnds().iterator(); it.hasNext();) {
  19774. const de = it.next();
  19775. this.collectLineEdge(de, opCode, this._lineEdgesList);
  19776. this.collectBoundaryTouchEdge(de, opCode, this._lineEdgesList);
  19777. }
  19778. }
  19779. labelIsolatedLine(e, targetIndex) {
  19780. const loc = this._ptLocator.locate(e.getCoordinate(), this._op.getArgGeometry(targetIndex));
  19781. e.getLabel().setLocation(targetIndex, loc);
  19782. }
  19783. build(opCode) {
  19784. this.findCoveredLineEdges();
  19785. this.collectLines(opCode);
  19786. this.buildLines(opCode);
  19787. return this._resultLineList;
  19788. }
  19789. collectLineEdge(de, opCode, edges) {
  19790. const label = de.getLabel();
  19791. const e = de.getEdge();
  19792. if (de.isLineEdge()) if (!de.isVisited() && OverlayOp.isResultOfOp(label, opCode) && !e.isCovered()) {
  19793. edges.add(e);
  19794. de.setVisitedEdge(true);
  19795. }
  19796. }
  19797. findCoveredLineEdges() {
  19798. for (let nodeit = this._op.getGraph().getNodes().iterator(); nodeit.hasNext();) {
  19799. const node = nodeit.next();
  19800. node.getEdges().findCoveredLineEdges();
  19801. }
  19802. for (let it = this._op.getGraph().getEdgeEnds().iterator(); it.hasNext();) {
  19803. const de = it.next();
  19804. const e = de.getEdge();
  19805. if (de.isLineEdge() && !e.isCoveredSet()) {
  19806. const isCovered = this._op.isCoveredByA(de.getCoordinate());
  19807. e.setCovered(isCovered);
  19808. }
  19809. }
  19810. }
  19811. labelIsolatedLines(edgesList) {
  19812. for (let it = edgesList.iterator(); it.hasNext();) {
  19813. const e = it.next();
  19814. const label = e.getLabel();
  19815. if (e.isIsolated()) if (label.isNull(0)) this.labelIsolatedLine(e, 0);else this.labelIsolatedLine(e, 1);
  19816. }
  19817. }
  19818. buildLines(opCode) {
  19819. for (let it = this._lineEdgesList.iterator(); it.hasNext();) {
  19820. const e = it.next();
  19821. const line = this._geometryFactory.createLineString(e.getCoordinates());
  19822. this._resultLineList.add(line);
  19823. e.setInResult(true);
  19824. }
  19825. }
  19826. collectBoundaryTouchEdge(de, opCode, edges) {
  19827. const label = de.getLabel();
  19828. if (de.isLineEdge()) return null;
  19829. if (de.isVisited()) return null;
  19830. if (de.isInteriorAreaEdge()) return null;
  19831. if (de.getEdge().isInResult()) return null;
  19832. Assert.isTrue(!(de.isInResult() || de.getSym().isInResult()) || !de.getEdge().isInResult());
  19833. if (OverlayOp.isResultOfOp(label, opCode) && opCode === OverlayOp.INTERSECTION) {
  19834. edges.add(de.getEdge());
  19835. de.setVisitedEdge(true);
  19836. }
  19837. }
  19838. }
  19839. class PointBuilder {
  19840. constructor() {
  19841. PointBuilder.constructor_.apply(this, arguments);
  19842. }
  19843. static constructor_() {
  19844. this._op = null;
  19845. this._geometryFactory = null;
  19846. this._resultPointList = new ArrayList();
  19847. const op = arguments[0],
  19848. geometryFactory = arguments[1];
  19849. this._op = op;
  19850. this._geometryFactory = geometryFactory;
  19851. }
  19852. filterCoveredNodeToPoint(n) {
  19853. const coord = n.getCoordinate();
  19854. if (!this._op.isCoveredByLA(coord)) {
  19855. const pt = this._geometryFactory.createPoint(coord);
  19856. this._resultPointList.add(pt);
  19857. }
  19858. }
  19859. extractNonCoveredResultNodes(opCode) {
  19860. for (let nodeit = this._op.getGraph().getNodes().iterator(); nodeit.hasNext();) {
  19861. const n = nodeit.next();
  19862. if (n.isInResult()) continue;
  19863. if (n.isIncidentEdgeInResult()) continue;
  19864. if (n.getEdges().getDegree() === 0 || opCode === OverlayOp.INTERSECTION) {
  19865. const label = n.getLabel();
  19866. if (OverlayOp.isResultOfOp(label, opCode)) this.filterCoveredNodeToPoint(n);
  19867. }
  19868. }
  19869. }
  19870. build(opCode) {
  19871. this.extractNonCoveredResultNodes(opCode);
  19872. return this._resultPointList;
  19873. }
  19874. }
  19875. class CommonBits {
  19876. constructor() {
  19877. this._isFirst = true;
  19878. this._commonMantissaBitsCount = 53;
  19879. this._commonBits = new Long();
  19880. this._commonSignExp = null;
  19881. }
  19882. getCommon() {
  19883. return Double.longBitsToDouble(this._commonBits);
  19884. }
  19885. add(num) {
  19886. const numBits = Double.doubleToLongBits(num);
  19887. if (this._isFirst) {
  19888. this._commonBits = numBits;
  19889. this._commonSignExp = CommonBits.signExpBits(this._commonBits);
  19890. this._isFirst = false;
  19891. return null;
  19892. }
  19893. const numSignExp = CommonBits.signExpBits(numBits);
  19894. if (numSignExp !== this._commonSignExp) {
  19895. this._commonBits.high = 0 | 0;
  19896. this._commonBits.low = 0 | 0;
  19897. return null;
  19898. }
  19899. this._commonMantissaBitsCount = CommonBits.numCommonMostSigMantissaBits(this._commonBits, numBits);
  19900. this._commonBits = CommonBits.zeroLowerBits(this._commonBits, 64 - (12 + this._commonMantissaBitsCount));
  19901. }
  19902. toString() {
  19903. if (arguments.length === 1) {
  19904. const bits = arguments[0];
  19905. const x = Double.longBitsToDouble(bits);
  19906. const numStr = Long.toBinaryString(bits);
  19907. const padStr = '0000000000000000000000000000000000000000000000000000000000000000' + numStr;
  19908. const bitStr = padStr.substring(padStr.length - 64);
  19909. const str = bitStr.substring(0, 1) + ' ' + bitStr.substring(1, 12) + '(exp) ' + bitStr.substring(12) + ' [ ' + x + ' ]';
  19910. return str;
  19911. }
  19912. }
  19913. getClass() {
  19914. return CommonBits;
  19915. }
  19916. get interfaces_() {
  19917. return [];
  19918. }
  19919. static getBit(bits, i) {
  19920. const mask = 1 << i % 32;
  19921. if (i < 32) return (bits.low & mask) !== 0 ? 1 : 0;
  19922. return (bits.high & mask) !== 0 ? 1 : 0;
  19923. }
  19924. static signExpBits(num) {
  19925. return num.high >>> 20;
  19926. }
  19927. static zeroLowerBits(bits, nBits) {
  19928. let prop = 'low';
  19929. if (nBits > 32) {
  19930. bits.low = 0 | 0;
  19931. nBits %= 32;
  19932. prop = 'high';
  19933. }
  19934. if (nBits > 0) {
  19935. const mask = nBits < 32 ? ~((1 << nBits) - 1) : 0;
  19936. bits[prop] &= mask;
  19937. }
  19938. return bits;
  19939. }
  19940. static numCommonMostSigMantissaBits(num1, num2) {
  19941. let count = 0;
  19942. for (let i = 52; i >= 0; i--) {
  19943. if (CommonBits.getBit(num1, i) !== CommonBits.getBit(num2, i)) return count;
  19944. count++;
  19945. }
  19946. return 52;
  19947. }
  19948. }
  19949. class CommonBitsRemover {
  19950. constructor() {
  19951. CommonBitsRemover.constructor_.apply(this, arguments);
  19952. }
  19953. static constructor_() {
  19954. this._commonCoord = null;
  19955. this._ccFilter = new CommonCoordinateFilter();
  19956. }
  19957. addCommonBits(geom) {
  19958. const trans = new Translater(this._commonCoord);
  19959. geom.apply(trans);
  19960. geom.geometryChanged();
  19961. }
  19962. removeCommonBits(geom) {
  19963. if (this._commonCoord.x === 0.0 && this._commonCoord.y === 0.0) return geom;
  19964. const invCoord = new Coordinate(this._commonCoord);
  19965. invCoord.x = -invCoord.x;
  19966. invCoord.y = -invCoord.y;
  19967. const trans = new Translater(invCoord);
  19968. geom.apply(trans);
  19969. geom.geometryChanged();
  19970. return geom;
  19971. }
  19972. getCommonCoordinate() {
  19973. return this._commonCoord;
  19974. }
  19975. add(geom) {
  19976. geom.apply(this._ccFilter);
  19977. this._commonCoord = this._ccFilter.getCommonCoordinate();
  19978. }
  19979. }
  19980. class CommonCoordinateFilter {
  19981. constructor() {
  19982. CommonCoordinateFilter.constructor_.apply(this, arguments);
  19983. }
  19984. static constructor_() {
  19985. this._commonBitsX = new CommonBits();
  19986. this._commonBitsY = new CommonBits();
  19987. }
  19988. filter(coord) {
  19989. this._commonBitsX.add(coord.x);
  19990. this._commonBitsY.add(coord.y);
  19991. }
  19992. getCommonCoordinate() {
  19993. return new Coordinate(this._commonBitsX.getCommon(), this._commonBitsY.getCommon());
  19994. }
  19995. get interfaces_() {
  19996. return [CoordinateFilter];
  19997. }
  19998. }
  19999. class Translater {
  20000. constructor() {
  20001. Translater.constructor_.apply(this, arguments);
  20002. }
  20003. static constructor_() {
  20004. this.trans = null;
  20005. const trans = arguments[0];
  20006. this.trans = trans;
  20007. }
  20008. filter(seq, i) {
  20009. const xp = seq.getOrdinate(i, 0) + this.trans.x;
  20010. const yp = seq.getOrdinate(i, 1) + this.trans.y;
  20011. seq.setOrdinate(i, 0, xp);
  20012. seq.setOrdinate(i, 1, yp);
  20013. }
  20014. isDone() {
  20015. return false;
  20016. }
  20017. isGeometryChanged() {
  20018. return true;
  20019. }
  20020. get interfaces_() {
  20021. return [CoordinateSequenceFilter];
  20022. }
  20023. }
  20024. CommonBitsRemover.CommonCoordinateFilter = CommonCoordinateFilter;
  20025. CommonBitsRemover.Translater = Translater;
  20026. class SnapOverlayOp {
  20027. constructor() {
  20028. SnapOverlayOp.constructor_.apply(this, arguments);
  20029. }
  20030. static constructor_() {
  20031. this._geom = new Array(2).fill(null);
  20032. this._snapTolerance = null;
  20033. this._cbr = null;
  20034. const g1 = arguments[0],
  20035. g2 = arguments[1];
  20036. this._geom[0] = g1;
  20037. this._geom[1] = g2;
  20038. this.computeSnapTolerance();
  20039. }
  20040. static overlayOp(g0, g1, opCode) {
  20041. const op = new SnapOverlayOp(g0, g1);
  20042. return op.getResultGeometry(opCode);
  20043. }
  20044. static union(g0, g1) {
  20045. return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.UNION);
  20046. }
  20047. static intersection(g0, g1) {
  20048. return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.INTERSECTION);
  20049. }
  20050. static symDifference(g0, g1) {
  20051. return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.SYMDIFFERENCE);
  20052. }
  20053. static difference(g0, g1) {
  20054. return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.DIFFERENCE);
  20055. }
  20056. selfSnap(geom) {
  20057. const snapper0 = new GeometrySnapper(geom);
  20058. const snapGeom = snapper0.snapTo(geom, this._snapTolerance);
  20059. return snapGeom;
  20060. }
  20061. removeCommonBits(geom) {
  20062. this._cbr = new CommonBitsRemover();
  20063. this._cbr.add(geom[0]);
  20064. this._cbr.add(geom[1]);
  20065. const remGeom = new Array(2).fill(null);
  20066. remGeom[0] = this._cbr.removeCommonBits(geom[0].copy());
  20067. remGeom[1] = this._cbr.removeCommonBits(geom[1].copy());
  20068. return remGeom;
  20069. }
  20070. prepareResult(geom) {
  20071. this._cbr.addCommonBits(geom);
  20072. return geom;
  20073. }
  20074. getResultGeometry(opCode) {
  20075. const prepGeom = this.snap(this._geom);
  20076. const result = OverlayOp.overlayOp(prepGeom[0], prepGeom[1], opCode);
  20077. return this.prepareResult(result);
  20078. }
  20079. checkValid(g) {
  20080. if (!g.isValid()) System.out.println('Snapped geometry is invalid');
  20081. }
  20082. computeSnapTolerance() {
  20083. this._snapTolerance = GeometrySnapper.computeOverlaySnapTolerance(this._geom[0], this._geom[1]);
  20084. }
  20085. snap(geom) {
  20086. const remGeom = this.removeCommonBits(geom);
  20087. const snapGeom = GeometrySnapper.snap(remGeom[0], remGeom[1], this._snapTolerance);
  20088. return snapGeom;
  20089. }
  20090. }
  20091. class SnapIfNeededOverlayOp {
  20092. constructor() {
  20093. SnapIfNeededOverlayOp.constructor_.apply(this, arguments);
  20094. }
  20095. static constructor_() {
  20096. this._geom = new Array(2).fill(null);
  20097. const g1 = arguments[0],
  20098. g2 = arguments[1];
  20099. this._geom[0] = g1;
  20100. this._geom[1] = g2;
  20101. }
  20102. static overlayOp(g0, g1, opCode) {
  20103. const op = new SnapIfNeededOverlayOp(g0, g1);
  20104. return op.getResultGeometry(opCode);
  20105. }
  20106. static union(g0, g1) {
  20107. return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.UNION);
  20108. }
  20109. static intersection(g0, g1) {
  20110. return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.INTERSECTION);
  20111. }
  20112. static symDifference(g0, g1) {
  20113. return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.SYMDIFFERENCE);
  20114. }
  20115. static difference(g0, g1) {
  20116. return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.DIFFERENCE);
  20117. }
  20118. getResultGeometry(opCode) {
  20119. let result = null;
  20120. let isSuccess = false;
  20121. let savedException = null;
  20122. try {
  20123. result = OverlayOp.overlayOp(this._geom[0], this._geom[1], opCode);
  20124. const isValid = true;
  20125. if (isValid) isSuccess = true;
  20126. } catch (ex) {
  20127. if (ex instanceof RuntimeException) savedException = ex;else throw ex;
  20128. } finally {}
  20129. if (!isSuccess) try {
  20130. result = SnapOverlayOp.overlayOp(this._geom[0], this._geom[1], opCode);
  20131. } catch (ex) {
  20132. if (ex instanceof RuntimeException) throw savedException;else throw ex;
  20133. } finally {}
  20134. return result;
  20135. }
  20136. }
  20137. class GeometryGraphOperation {
  20138. constructor() {
  20139. GeometryGraphOperation.constructor_.apply(this, arguments);
  20140. }
  20141. static constructor_() {
  20142. this._li = new RobustLineIntersector();
  20143. this._resultPrecisionModel = null;
  20144. this._arg = null;
  20145. if (arguments.length === 1) {
  20146. const g0 = arguments[0];
  20147. this.setComputationPrecision(g0.getPrecisionModel());
  20148. this._arg = new Array(1).fill(null);
  20149. this._arg[0] = new GeometryGraph(0, g0);
  20150. } else if (arguments.length === 2) {
  20151. const g0 = arguments[0],
  20152. g1 = arguments[1];
  20153. GeometryGraphOperation.constructor_.call(this, g0, g1, BoundaryNodeRule.OGC_SFS_BOUNDARY_RULE);
  20154. } else if (arguments.length === 3) {
  20155. const g0 = arguments[0],
  20156. g1 = arguments[1],
  20157. boundaryNodeRule = arguments[2];
  20158. if (g0.getPrecisionModel().compareTo(g1.getPrecisionModel()) >= 0) this.setComputationPrecision(g0.getPrecisionModel());else this.setComputationPrecision(g1.getPrecisionModel());
  20159. this._arg = new Array(2).fill(null);
  20160. this._arg[0] = new GeometryGraph(0, g0, boundaryNodeRule);
  20161. this._arg[1] = new GeometryGraph(1, g1, boundaryNodeRule);
  20162. }
  20163. }
  20164. getArgGeometry(i) {
  20165. return this._arg[i].getGeometry();
  20166. }
  20167. setComputationPrecision(pm) {
  20168. this._resultPrecisionModel = pm;
  20169. this._li.setPrecisionModel(this._resultPrecisionModel);
  20170. }
  20171. }
  20172. class OverlayOp extends GeometryGraphOperation {
  20173. constructor() {
  20174. super();
  20175. OverlayOp.constructor_.apply(this, arguments);
  20176. }
  20177. static constructor_() {
  20178. this._ptLocator = new PointLocator();
  20179. this._geomFact = null;
  20180. this._resultGeom = null;
  20181. this._graph = null;
  20182. this._edgeList = new EdgeList();
  20183. this._resultPolyList = new ArrayList();
  20184. this._resultLineList = new ArrayList();
  20185. this._resultPointList = new ArrayList();
  20186. const g0 = arguments[0],
  20187. g1 = arguments[1];
  20188. GeometryGraphOperation.constructor_.call(this, g0, g1);
  20189. this._graph = new PlanarGraph$1(new OverlayNodeFactory());
  20190. this._geomFact = g0.getFactory();
  20191. }
  20192. static overlayOp(geom0, geom1, opCode) {
  20193. const gov = new OverlayOp(geom0, geom1);
  20194. const geomOv = gov.getResultGeometry(opCode);
  20195. return geomOv;
  20196. }
  20197. static union(geom, other) {
  20198. if (geom.isEmpty() || other.isEmpty()) {
  20199. if (geom.isEmpty() && other.isEmpty()) return OverlayOp.createEmptyResult(OverlayOp.UNION, geom, other, geom.getFactory());
  20200. if (geom.isEmpty()) return other.copy();
  20201. if (other.isEmpty()) return geom.copy();
  20202. }
  20203. if (geom.isGeometryCollection() || other.isGeometryCollection()) throw new IllegalArgumentException('This method does not support GeometryCollection arguments');
  20204. return SnapIfNeededOverlayOp.overlayOp(geom, other, OverlayOp.UNION);
  20205. }
  20206. static intersection(geom, other) {
  20207. if (geom.isEmpty() || other.isEmpty()) return OverlayOp.createEmptyResult(OverlayOp.INTERSECTION, geom, other, geom.getFactory());
  20208. if (geom.isGeometryCollection()) {
  20209. const g2 = other;
  20210. return GeometryCollectionMapper.map(geom, new class {
  20211. get interfaces_() {
  20212. return [MapOp];
  20213. }
  20214. map(g) {
  20215. return OverlayOp.intersection(g, g2);
  20216. }
  20217. }());
  20218. }
  20219. return SnapIfNeededOverlayOp.overlayOp(geom, other, OverlayOp.INTERSECTION);
  20220. }
  20221. static symDifference(geom, other) {
  20222. if (geom.isEmpty() || other.isEmpty()) {
  20223. if (geom.isEmpty() && other.isEmpty()) return OverlayOp.createEmptyResult(OverlayOp.SYMDIFFERENCE, geom, other, geom.getFactory());
  20224. if (geom.isEmpty()) return other.copy();
  20225. if (other.isEmpty()) return geom.copy();
  20226. }
  20227. if (geom.isGeometryCollection() || other.isGeometryCollection()) throw new IllegalArgumentException('This method does not support GeometryCollection arguments');
  20228. return SnapIfNeededOverlayOp.overlayOp(geom, other, OverlayOp.SYMDIFFERENCE);
  20229. }
  20230. static resultDimension(opCode, g0, g1) {
  20231. const dim0 = g0.getDimension();
  20232. const dim1 = g1.getDimension();
  20233. let resultDimension = -1;
  20234. switch (opCode) {
  20235. case OverlayOp.INTERSECTION:
  20236. resultDimension = Math.min(dim0, dim1);
  20237. break;
  20238. case OverlayOp.UNION:
  20239. resultDimension = Math.max(dim0, dim1);
  20240. break;
  20241. case OverlayOp.DIFFERENCE:
  20242. resultDimension = dim0;
  20243. break;
  20244. case OverlayOp.SYMDIFFERENCE:
  20245. resultDimension = Math.max(dim0, dim1);
  20246. break;
  20247. }
  20248. return resultDimension;
  20249. }
  20250. static createEmptyResult(overlayOpCode, a, b, geomFact) {
  20251. const resultDim = OverlayOp.resultDimension(overlayOpCode, a, b);
  20252. return geomFact.createEmpty(resultDim);
  20253. }
  20254. static difference(geom, other) {
  20255. if (geom.isEmpty()) return OverlayOp.createEmptyResult(OverlayOp.DIFFERENCE, geom, other, geom.getFactory());
  20256. if (other.isEmpty()) return geom.copy();
  20257. if (geom.isGeometryCollection() || other.isGeometryCollection()) throw new IllegalArgumentException('This method does not support GeometryCollection arguments');
  20258. return SnapIfNeededOverlayOp.overlayOp(geom, other, OverlayOp.DIFFERENCE);
  20259. }
  20260. static isResultOfOp() {
  20261. if (arguments.length === 2) {
  20262. const label = arguments[0],
  20263. opCode = arguments[1];
  20264. const loc0 = label.getLocation(0);
  20265. const loc1 = label.getLocation(1);
  20266. return OverlayOp.isResultOfOp(loc0, loc1, opCode);
  20267. } else if (arguments.length === 3) {
  20268. let loc0 = arguments[0],
  20269. loc1 = arguments[1],
  20270. overlayOpCode = arguments[2];
  20271. if (loc0 === Location.BOUNDARY) loc0 = Location.INTERIOR;
  20272. if (loc1 === Location.BOUNDARY) loc1 = Location.INTERIOR;
  20273. switch (overlayOpCode) {
  20274. case OverlayOp.INTERSECTION:
  20275. return loc0 === Location.INTERIOR && loc1 === Location.INTERIOR;
  20276. case OverlayOp.UNION:
  20277. return loc0 === Location.INTERIOR || loc1 === Location.INTERIOR;
  20278. case OverlayOp.DIFFERENCE:
  20279. return loc0 === Location.INTERIOR && loc1 !== Location.INTERIOR;
  20280. case OverlayOp.SYMDIFFERENCE:
  20281. return loc0 === Location.INTERIOR && loc1 !== Location.INTERIOR || loc0 !== Location.INTERIOR && loc1 === Location.INTERIOR;
  20282. }
  20283. return false;
  20284. }
  20285. }
  20286. insertUniqueEdge(e) {
  20287. const existingEdge = this._edgeList.findEqualEdge(e);
  20288. if (existingEdge !== null) {
  20289. const existingLabel = existingEdge.getLabel();
  20290. let labelToMerge = e.getLabel();
  20291. if (!existingEdge.isPointwiseEqual(e)) {
  20292. labelToMerge = new Label(e.getLabel());
  20293. labelToMerge.flip();
  20294. }
  20295. const depth = existingEdge.getDepth();
  20296. if (depth.isNull()) depth.add(existingLabel);
  20297. depth.add(labelToMerge);
  20298. existingLabel.merge(labelToMerge);
  20299. } else {
  20300. this._edgeList.add(e);
  20301. }
  20302. }
  20303. getGraph() {
  20304. return this._graph;
  20305. }
  20306. cancelDuplicateResultEdges() {
  20307. for (let it = this._graph.getEdgeEnds().iterator(); it.hasNext();) {
  20308. const de = it.next();
  20309. const sym = de.getSym();
  20310. if (de.isInResult() && sym.isInResult()) {
  20311. de.setInResult(false);
  20312. sym.setInResult(false);
  20313. }
  20314. }
  20315. }
  20316. isCoveredByLA(coord) {
  20317. if (this.isCovered(coord, this._resultLineList)) return true;
  20318. if (this.isCovered(coord, this._resultPolyList)) return true;
  20319. return false;
  20320. }
  20321. computeGeometry(resultPointList, resultLineList, resultPolyList, opcode) {
  20322. const geomList = new ArrayList();
  20323. geomList.addAll(resultPointList);
  20324. geomList.addAll(resultLineList);
  20325. geomList.addAll(resultPolyList);
  20326. if (geomList.isEmpty()) return OverlayOp.createEmptyResult(opcode, this._arg[0].getGeometry(), this._arg[1].getGeometry(), this._geomFact);
  20327. return this._geomFact.buildGeometry(geomList);
  20328. }
  20329. mergeSymLabels() {
  20330. for (let nodeit = this._graph.getNodes().iterator(); nodeit.hasNext();) {
  20331. const node = nodeit.next();
  20332. node.getEdges().mergeSymLabels();
  20333. }
  20334. }
  20335. isCovered(coord, geomList) {
  20336. for (let it = geomList.iterator(); it.hasNext();) {
  20337. const geom = it.next();
  20338. const loc = this._ptLocator.locate(coord, geom);
  20339. if (loc !== Location.EXTERIOR) return true;
  20340. }
  20341. return false;
  20342. }
  20343. replaceCollapsedEdges() {
  20344. const newEdges = new ArrayList();
  20345. for (let it = this._edgeList.iterator(); it.hasNext();) {
  20346. const e = it.next();
  20347. if (e.isCollapsed()) {
  20348. it.remove();
  20349. newEdges.add(e.getCollapsedEdge());
  20350. }
  20351. }
  20352. this._edgeList.addAll(newEdges);
  20353. }
  20354. updateNodeLabelling() {
  20355. for (let nodeit = this._graph.getNodes().iterator(); nodeit.hasNext();) {
  20356. const node = nodeit.next();
  20357. const lbl = node.getEdges().getLabel();
  20358. node.getLabel().merge(lbl);
  20359. }
  20360. }
  20361. getResultGeometry(overlayOpCode) {
  20362. this.computeOverlay(overlayOpCode);
  20363. return this._resultGeom;
  20364. }
  20365. insertUniqueEdges(edges) {
  20366. for (let i = edges.iterator(); i.hasNext();) {
  20367. const e = i.next();
  20368. this.insertUniqueEdge(e);
  20369. }
  20370. }
  20371. computeOverlay(opCode) {
  20372. this.copyPoints(0);
  20373. this.copyPoints(1);
  20374. this._arg[0].computeSelfNodes(this._li, false);
  20375. this._arg[1].computeSelfNodes(this._li, false);
  20376. this._arg[0].computeEdgeIntersections(this._arg[1], this._li, true);
  20377. const baseSplitEdges = new ArrayList();
  20378. this._arg[0].computeSplitEdges(baseSplitEdges);
  20379. this._arg[1].computeSplitEdges(baseSplitEdges);
  20380. this.insertUniqueEdges(baseSplitEdges);
  20381. this.computeLabelsFromDepths();
  20382. this.replaceCollapsedEdges();
  20383. EdgeNodingValidator.checkValid(this._edgeList.getEdges());
  20384. this._graph.addEdges(this._edgeList.getEdges());
  20385. this.computeLabelling();
  20386. this.labelIncompleteNodes();
  20387. this.findResultAreaEdges(opCode);
  20388. this.cancelDuplicateResultEdges();
  20389. const polyBuilder = new PolygonBuilder(this._geomFact);
  20390. polyBuilder.add(this._graph);
  20391. this._resultPolyList = polyBuilder.getPolygons();
  20392. const lineBuilder = new LineBuilder(this, this._geomFact, this._ptLocator);
  20393. this._resultLineList = lineBuilder.build(opCode);
  20394. const pointBuilder = new PointBuilder(this, this._geomFact, this._ptLocator);
  20395. this._resultPointList = pointBuilder.build(opCode);
  20396. this._resultGeom = this.computeGeometry(this._resultPointList, this._resultLineList, this._resultPolyList, opCode);
  20397. }
  20398. labelIncompleteNode(n, targetIndex) {
  20399. const loc = this._ptLocator.locate(n.getCoordinate(), this._arg[targetIndex].getGeometry());
  20400. n.getLabel().setLocation(targetIndex, loc);
  20401. }
  20402. copyPoints(argIndex) {
  20403. for (let i = this._arg[argIndex].getNodeIterator(); i.hasNext();) {
  20404. const graphNode = i.next();
  20405. const newNode = this._graph.addNode(graphNode.getCoordinate());
  20406. newNode.setLabel(argIndex, graphNode.getLabel().getLocation(argIndex));
  20407. }
  20408. }
  20409. findResultAreaEdges(opCode) {
  20410. for (let it = this._graph.getEdgeEnds().iterator(); it.hasNext();) {
  20411. const de = it.next();
  20412. const label = de.getLabel();
  20413. if (label.isArea() && !de.isInteriorAreaEdge() && OverlayOp.isResultOfOp(label.getLocation(0, Position.RIGHT), label.getLocation(1, Position.RIGHT), opCode)) de.setInResult(true);
  20414. }
  20415. }
  20416. computeLabelsFromDepths() {
  20417. for (let it = this._edgeList.iterator(); it.hasNext();) {
  20418. const e = it.next();
  20419. const lbl = e.getLabel();
  20420. const depth = e.getDepth();
  20421. if (!depth.isNull()) {
  20422. depth.normalize();
  20423. for (let i = 0; i < 2; i++) if (!lbl.isNull(i) && lbl.isArea() && !depth.isNull(i)) if (depth.getDelta(i) === 0) {
  20424. lbl.toLine(i);
  20425. } else {
  20426. Assert.isTrue(!depth.isNull(i, Position.LEFT), 'depth of LEFT side has not been initialized');
  20427. lbl.setLocation(i, Position.LEFT, depth.getLocation(i, Position.LEFT));
  20428. Assert.isTrue(!depth.isNull(i, Position.RIGHT), 'depth of RIGHT side has not been initialized');
  20429. lbl.setLocation(i, Position.RIGHT, depth.getLocation(i, Position.RIGHT));
  20430. }
  20431. }
  20432. }
  20433. }
  20434. computeLabelling() {
  20435. for (let nodeit = this._graph.getNodes().iterator(); nodeit.hasNext();) {
  20436. const node = nodeit.next();
  20437. node.getEdges().computeLabelling(this._arg);
  20438. }
  20439. this.mergeSymLabels();
  20440. this.updateNodeLabelling();
  20441. }
  20442. labelIncompleteNodes() {
  20443. for (let ni = this._graph.getNodes().iterator(); ni.hasNext();) {
  20444. const n = ni.next();
  20445. const label = n.getLabel();
  20446. if (n.isIsolated()) if (label.isNull(0)) this.labelIncompleteNode(n, 0);else this.labelIncompleteNode(n, 1);
  20447. n.getEdges().updateLabelling(label);
  20448. }
  20449. }
  20450. isCoveredByA(coord) {
  20451. if (this.isCovered(coord, this._resultPolyList)) return true;
  20452. return false;
  20453. }
  20454. }
  20455. OverlayOp.INTERSECTION = 1;
  20456. OverlayOp.UNION = 2;
  20457. OverlayOp.DIFFERENCE = 3;
  20458. OverlayOp.SYMDIFFERENCE = 4;
  20459. var overlay = /*#__PURE__*/Object.freeze({
  20460. __proto__: null,
  20461. snap: snap,
  20462. OverlayOp: OverlayOp
  20463. });
  20464. class PolygonizeDirectedEdge extends DirectedEdge {
  20465. constructor() {
  20466. super();
  20467. PolygonizeDirectedEdge.constructor_.apply(this, arguments);
  20468. }
  20469. static constructor_() {
  20470. this._edgeRing = null;
  20471. this._next = null;
  20472. this._label = -1;
  20473. const from = arguments[0],
  20474. to = arguments[1],
  20475. directionPt = arguments[2],
  20476. edgeDirection = arguments[3];
  20477. DirectedEdge.constructor_.call(this, from, to, directionPt, edgeDirection);
  20478. }
  20479. getNext() {
  20480. return this._next;
  20481. }
  20482. isInRing() {
  20483. return this._edgeRing !== null;
  20484. }
  20485. setRing(edgeRing) {
  20486. this._edgeRing = edgeRing;
  20487. }
  20488. setLabel(label) {
  20489. this._label = label;
  20490. }
  20491. getLabel() {
  20492. return this._label;
  20493. }
  20494. setNext(next) {
  20495. this._next = next;
  20496. }
  20497. getRing() {
  20498. return this._edgeRing;
  20499. }
  20500. }
  20501. class PolygonizeEdge extends Edge {
  20502. constructor() {
  20503. super();
  20504. PolygonizeEdge.constructor_.apply(this, arguments);
  20505. }
  20506. static constructor_() {
  20507. this._line = null;
  20508. const line = arguments[0];
  20509. this._line = line;
  20510. }
  20511. getLine() {
  20512. return this._line;
  20513. }
  20514. }
  20515. class ConnectedInteriorTester {
  20516. constructor() {
  20517. ConnectedInteriorTester.constructor_.apply(this, arguments);
  20518. }
  20519. static constructor_() {
  20520. this._geometryFactory = new GeometryFactory();
  20521. this._geomGraph = null;
  20522. this._disconnectedRingcoord = null;
  20523. const geomGraph = arguments[0];
  20524. this._geomGraph = geomGraph;
  20525. }
  20526. static findDifferentPoint(coord, pt) {
  20527. for (let i = 0; i < coord.length; i++) if (!coord[i].equals(pt)) return coord[i];
  20528. return null;
  20529. }
  20530. visitInteriorRing(ring, graph) {
  20531. if (ring.isEmpty()) return null;
  20532. const pts = ring.getCoordinates();
  20533. const pt0 = pts[0];
  20534. const pt1 = ConnectedInteriorTester.findDifferentPoint(pts, pt0);
  20535. const e = graph.findEdgeInSameDirection(pt0, pt1);
  20536. const de = graph.findEdgeEnd(e);
  20537. let intDe = null;
  20538. if (de.getLabel().getLocation(0, Position.RIGHT) === Location.INTERIOR) intDe = de;else if (de.getSym().getLabel().getLocation(0, Position.RIGHT) === Location.INTERIOR) intDe = de.getSym();
  20539. Assert.isTrue(intDe !== null, 'unable to find dirEdge with Interior on RHS');
  20540. this.visitLinkedDirectedEdges(intDe);
  20541. }
  20542. visitShellInteriors(g, graph) {
  20543. if (g instanceof Polygon) {
  20544. const p = g;
  20545. this.visitInteriorRing(p.getExteriorRing(), graph);
  20546. }
  20547. if (g instanceof MultiPolygon) {
  20548. const mp = g;
  20549. for (let i = 0; i < mp.getNumGeometries(); i++) {
  20550. const p = mp.getGeometryN(i);
  20551. this.visitInteriorRing(p.getExteriorRing(), graph);
  20552. }
  20553. }
  20554. }
  20555. getCoordinate() {
  20556. return this._disconnectedRingcoord;
  20557. }
  20558. setInteriorEdgesInResult(graph) {
  20559. for (let it = graph.getEdgeEnds().iterator(); it.hasNext();) {
  20560. const de = it.next();
  20561. if (de.getLabel().getLocation(0, Position.RIGHT) === Location.INTERIOR) de.setInResult(true);
  20562. }
  20563. }
  20564. visitLinkedDirectedEdges(start) {
  20565. const startDe = start;
  20566. let de = start;
  20567. do {
  20568. Assert.isTrue(de !== null, 'found null Directed Edge');
  20569. de.setVisited(true);
  20570. de = de.getNext();
  20571. } while (de !== startDe);
  20572. }
  20573. buildEdgeRings(dirEdges) {
  20574. const edgeRings = new ArrayList();
  20575. for (let it = dirEdges.iterator(); it.hasNext();) {
  20576. const de = it.next();
  20577. if (de.isInResult() && de.getEdgeRing() === null) {
  20578. const er = new MaximalEdgeRing(de, this._geometryFactory);
  20579. er.linkDirectedEdgesForMinimalEdgeRings();
  20580. const minEdgeRings = er.buildMinimalRings();
  20581. edgeRings.addAll(minEdgeRings);
  20582. }
  20583. }
  20584. return edgeRings;
  20585. }
  20586. hasUnvisitedShellEdge(edgeRings) {
  20587. for (let i = 0; i < edgeRings.size(); i++) {
  20588. const er = edgeRings.get(i);
  20589. if (er.isHole()) continue;
  20590. const edges = er.getEdges();
  20591. let de = edges.get(0);
  20592. if (de.getLabel().getLocation(0, Position.RIGHT) !== Location.INTERIOR) continue;
  20593. for (let j = 0; j < edges.size(); j++) {
  20594. de = edges.get(j);
  20595. if (!de.isVisited()) {
  20596. this._disconnectedRingcoord = de.getCoordinate();
  20597. return true;
  20598. }
  20599. }
  20600. }
  20601. return false;
  20602. }
  20603. isInteriorsConnected() {
  20604. const splitEdges = new ArrayList();
  20605. this._geomGraph.computeSplitEdges(splitEdges);
  20606. const graph = new PlanarGraph$1(new OverlayNodeFactory());
  20607. graph.addEdges(splitEdges);
  20608. this.setInteriorEdgesInResult(graph);
  20609. graph.linkResultDirectedEdges();
  20610. const edgeRings = this.buildEdgeRings(graph.getEdgeEnds());
  20611. this.visitShellInteriors(this._geomGraph.getGeometry(), graph);
  20612. return !this.hasUnvisitedShellEdge(edgeRings);
  20613. }
  20614. }
  20615. class EdgeEndBuilder {
  20616. createEdgeEndForNext(edge, l, eiCurr, eiNext) {
  20617. const iNext = eiCurr.segmentIndex + 1;
  20618. if (iNext >= edge.getNumPoints() && eiNext === null) return null;
  20619. let pNext = edge.getCoordinate(iNext);
  20620. if (eiNext !== null && eiNext.segmentIndex === eiCurr.segmentIndex) pNext = eiNext.coord;
  20621. const e = new EdgeEnd(edge, eiCurr.coord, pNext, new Label(edge.getLabel()));
  20622. l.add(e);
  20623. }
  20624. createEdgeEndForPrev(edge, l, eiCurr, eiPrev) {
  20625. let iPrev = eiCurr.segmentIndex;
  20626. if (eiCurr.dist === 0.0) {
  20627. if (iPrev === 0) return null;
  20628. iPrev--;
  20629. }
  20630. let pPrev = edge.getCoordinate(iPrev);
  20631. if (eiPrev !== null && eiPrev.segmentIndex >= iPrev) pPrev = eiPrev.coord;
  20632. const label = new Label(edge.getLabel());
  20633. label.flip();
  20634. const e = new EdgeEnd(edge, eiCurr.coord, pPrev, label);
  20635. l.add(e);
  20636. }
  20637. computeEdgeEnds() {
  20638. if (arguments.length === 1) {
  20639. const edges = arguments[0];
  20640. const l = new ArrayList();
  20641. for (let i = edges; i.hasNext();) {
  20642. const e = i.next();
  20643. this.computeEdgeEnds(e, l);
  20644. }
  20645. return l;
  20646. } else if (arguments.length === 2) {
  20647. const edge = arguments[0],
  20648. l = arguments[1];
  20649. const eiList = edge.getEdgeIntersectionList();
  20650. eiList.addEndpoints();
  20651. const it = eiList.iterator();
  20652. let eiPrev = null;
  20653. let eiCurr = null;
  20654. if (!it.hasNext()) return null;
  20655. let eiNext = it.next();
  20656. do {
  20657. eiPrev = eiCurr;
  20658. eiCurr = eiNext;
  20659. eiNext = null;
  20660. if (it.hasNext()) eiNext = it.next();
  20661. if (eiCurr !== null) {
  20662. this.createEdgeEndForPrev(edge, l, eiCurr, eiPrev);
  20663. this.createEdgeEndForNext(edge, l, eiCurr, eiNext);
  20664. }
  20665. } while (eiCurr !== null);
  20666. }
  20667. }
  20668. }
  20669. class EdgeEndBundle extends EdgeEnd {
  20670. constructor() {
  20671. super();
  20672. EdgeEndBundle.constructor_.apply(this, arguments);
  20673. }
  20674. static constructor_() {
  20675. this._edgeEnds = new ArrayList();
  20676. if (arguments.length === 1) {
  20677. const e = arguments[0];
  20678. EdgeEndBundle.constructor_.call(this, null, e);
  20679. } else if (arguments.length === 2) {
  20680. const e = arguments[1];
  20681. EdgeEnd.constructor_.call(this, e.getEdge(), e.getCoordinate(), e.getDirectedCoordinate(), new Label(e.getLabel()));
  20682. this.insert(e);
  20683. }
  20684. }
  20685. insert(e) {
  20686. this._edgeEnds.add(e);
  20687. }
  20688. print(out) {
  20689. out.println('EdgeEndBundle--> Label: ' + this._label);
  20690. for (let it = this.iterator(); it.hasNext();) {
  20691. const ee = it.next();
  20692. ee.print(out);
  20693. out.println();
  20694. }
  20695. }
  20696. iterator() {
  20697. return this._edgeEnds.iterator();
  20698. }
  20699. getEdgeEnds() {
  20700. return this._edgeEnds;
  20701. }
  20702. computeLabelOn(geomIndex, boundaryNodeRule) {
  20703. let boundaryCount = 0;
  20704. let foundInterior = false;
  20705. for (let it = this.iterator(); it.hasNext();) {
  20706. const e = it.next();
  20707. const loc = e.getLabel().getLocation(geomIndex);
  20708. if (loc === Location.BOUNDARY) boundaryCount++;
  20709. if (loc === Location.INTERIOR) foundInterior = true;
  20710. }
  20711. let loc = Location.NONE;
  20712. if (foundInterior) loc = Location.INTERIOR;
  20713. if (boundaryCount > 0) loc = GeometryGraph.determineBoundary(boundaryNodeRule, boundaryCount);
  20714. this._label.setLocation(geomIndex, loc);
  20715. }
  20716. computeLabelSide(geomIndex, side) {
  20717. for (let it = this.iterator(); it.hasNext();) {
  20718. const e = it.next();
  20719. if (e.getLabel().isArea()) {
  20720. const loc = e.getLabel().getLocation(geomIndex, side);
  20721. if (loc === Location.INTERIOR) {
  20722. this._label.setLocation(geomIndex, side, Location.INTERIOR);
  20723. return null;
  20724. } else if (loc === Location.EXTERIOR) {
  20725. this._label.setLocation(geomIndex, side, Location.EXTERIOR);
  20726. }
  20727. }
  20728. }
  20729. }
  20730. getLabel() {
  20731. return this._label;
  20732. }
  20733. computeLabelSides(geomIndex) {
  20734. this.computeLabelSide(geomIndex, Position.LEFT);
  20735. this.computeLabelSide(geomIndex, Position.RIGHT);
  20736. }
  20737. updateIM(im) {
  20738. Edge$1.updateIM(this._label, im);
  20739. }
  20740. computeLabel(boundaryNodeRule) {
  20741. let isArea = false;
  20742. for (let it = this.iterator(); it.hasNext();) {
  20743. const e = it.next();
  20744. if (e.getLabel().isArea()) isArea = true;
  20745. }
  20746. if (isArea) this._label = new Label(Location.NONE, Location.NONE, Location.NONE);else this._label = new Label(Location.NONE);
  20747. for (let i = 0; i < 2; i++) {
  20748. this.computeLabelOn(i, boundaryNodeRule);
  20749. if (isArea) this.computeLabelSides(i);
  20750. }
  20751. }
  20752. }
  20753. class EdgeEndBundleStar extends EdgeEndStar {
  20754. constructor() {
  20755. super();
  20756. }
  20757. updateIM(im) {
  20758. for (let it = this.iterator(); it.hasNext();) {
  20759. const esb = it.next();
  20760. esb.updateIM(im);
  20761. }
  20762. }
  20763. insert(e) {
  20764. let eb = this._edgeMap.get(e);
  20765. if (eb === null) {
  20766. eb = new EdgeEndBundle(e);
  20767. this.insertEdgeEnd(e, eb);
  20768. } else {
  20769. eb.insert(e);
  20770. }
  20771. }
  20772. }
  20773. class RelateNode extends Node$2 {
  20774. constructor() {
  20775. super();
  20776. RelateNode.constructor_.apply(this, arguments);
  20777. }
  20778. static constructor_() {
  20779. const coord = arguments[0],
  20780. edges = arguments[1];
  20781. Node$2.constructor_.call(this, coord, edges);
  20782. }
  20783. updateIMFromEdges(im) {
  20784. this._edges.updateIM(im);
  20785. }
  20786. computeIM(im) {
  20787. im.setAtLeastIfValid(this._label.getLocation(0), this._label.getLocation(1), 0);
  20788. }
  20789. }
  20790. class RelateNodeFactory extends NodeFactory {
  20791. constructor() {
  20792. super();
  20793. }
  20794. createNode(coord) {
  20795. return new RelateNode(coord, new EdgeEndBundleStar());
  20796. }
  20797. }
  20798. class RelateNodeGraph {
  20799. constructor() {
  20800. RelateNodeGraph.constructor_.apply(this, arguments);
  20801. }
  20802. static constructor_() {
  20803. this._nodes = new NodeMap$1(new RelateNodeFactory());
  20804. }
  20805. insertEdgeEnds(ee) {
  20806. for (let i = ee.iterator(); i.hasNext();) {
  20807. const e = i.next();
  20808. this._nodes.add(e);
  20809. }
  20810. }
  20811. getNodeIterator() {
  20812. return this._nodes.iterator();
  20813. }
  20814. copyNodesAndLabels(geomGraph, argIndex) {
  20815. for (let nodeIt = geomGraph.getNodeIterator(); nodeIt.hasNext();) {
  20816. const graphNode = nodeIt.next();
  20817. const newNode = this._nodes.addNode(graphNode.getCoordinate());
  20818. newNode.setLabel(argIndex, graphNode.getLabel().getLocation(argIndex));
  20819. }
  20820. }
  20821. build(geomGraph) {
  20822. this.computeIntersectionNodes(geomGraph, 0);
  20823. this.copyNodesAndLabels(geomGraph, 0);
  20824. const eeBuilder = new EdgeEndBuilder();
  20825. const eeList = eeBuilder.computeEdgeEnds(geomGraph.getEdgeIterator());
  20826. this.insertEdgeEnds(eeList);
  20827. }
  20828. computeIntersectionNodes(geomGraph, argIndex) {
  20829. for (let edgeIt = geomGraph.getEdgeIterator(); edgeIt.hasNext();) {
  20830. const e = edgeIt.next();
  20831. const eLoc = e.getLabel().getLocation(argIndex);
  20832. for (let eiIt = e.getEdgeIntersectionList().iterator(); eiIt.hasNext();) {
  20833. const ei = eiIt.next();
  20834. const n = this._nodes.addNode(ei.coord);
  20835. if (eLoc === Location.BOUNDARY) n.setLabelBoundary(argIndex);else if (n.getLabel().isNull(argIndex)) n.setLabel(argIndex, Location.INTERIOR);
  20836. }
  20837. }
  20838. }
  20839. }
  20840. class ConsistentAreaTester {
  20841. constructor() {
  20842. ConsistentAreaTester.constructor_.apply(this, arguments);
  20843. }
  20844. static constructor_() {
  20845. this._li = new RobustLineIntersector();
  20846. this._geomGraph = null;
  20847. this._nodeGraph = new RelateNodeGraph();
  20848. this._invalidPoint = null;
  20849. const geomGraph = arguments[0];
  20850. this._geomGraph = geomGraph;
  20851. }
  20852. isNodeEdgeAreaLabelsConsistent() {
  20853. for (let nodeIt = this._nodeGraph.getNodeIterator(); nodeIt.hasNext();) {
  20854. const node = nodeIt.next();
  20855. if (!node.getEdges().isAreaLabelsConsistent(this._geomGraph)) {
  20856. this._invalidPoint = node.getCoordinate().copy();
  20857. return false;
  20858. }
  20859. }
  20860. return true;
  20861. }
  20862. getInvalidPoint() {
  20863. return this._invalidPoint;
  20864. }
  20865. hasDuplicateRings() {
  20866. for (let nodeIt = this._nodeGraph.getNodeIterator(); nodeIt.hasNext();) {
  20867. const node = nodeIt.next();
  20868. for (let i = node.getEdges().iterator(); i.hasNext();) {
  20869. const eeb = i.next();
  20870. if (eeb.getEdgeEnds().size() > 1) {
  20871. this._invalidPoint = eeb.getEdge().getCoordinate(0);
  20872. return true;
  20873. }
  20874. }
  20875. }
  20876. return false;
  20877. }
  20878. isNodeConsistentArea() {
  20879. const intersector = this._geomGraph.computeSelfNodes(this._li, true, true);
  20880. if (intersector.hasProperIntersection()) {
  20881. this._invalidPoint = intersector.getProperIntersectionPoint();
  20882. return false;
  20883. }
  20884. this._nodeGraph.build(this._geomGraph);
  20885. return this.isNodeEdgeAreaLabelsConsistent();
  20886. }
  20887. }
  20888. class IndexedNestedRingTester {
  20889. constructor() {
  20890. IndexedNestedRingTester.constructor_.apply(this, arguments);
  20891. }
  20892. static constructor_() {
  20893. this._graph = null;
  20894. this._rings = new ArrayList();
  20895. this._totalEnv = new Envelope();
  20896. this._index = null;
  20897. this._nestedPt = null;
  20898. const graph = arguments[0];
  20899. this._graph = graph;
  20900. }
  20901. buildIndex() {
  20902. this._index = new STRtree();
  20903. for (let i = 0; i < this._rings.size(); i++) {
  20904. const ring = this._rings.get(i);
  20905. const env = ring.getEnvelopeInternal();
  20906. this._index.insert(env, ring);
  20907. }
  20908. }
  20909. getNestedPoint() {
  20910. return this._nestedPt;
  20911. }
  20912. isNonNested() {
  20913. this.buildIndex();
  20914. for (let i = 0; i < this._rings.size(); i++) {
  20915. const innerRing = this._rings.get(i);
  20916. const innerRingPts = innerRing.getCoordinates();
  20917. const results = this._index.query(innerRing.getEnvelopeInternal());
  20918. for (let j = 0; j < results.size(); j++) {
  20919. const searchRing = results.get(j);
  20920. const searchRingPts = searchRing.getCoordinates();
  20921. if (innerRing === searchRing) continue;
  20922. if (!innerRing.getEnvelopeInternal().intersects(searchRing.getEnvelopeInternal())) continue;
  20923. const innerRingPt = IsValidOp.findPtNotNode(innerRingPts, searchRing, this._graph);
  20924. if (innerRingPt === null) continue;
  20925. const isInside = PointLocation.isInRing(innerRingPt, searchRingPts);
  20926. if (isInside) {
  20927. this._nestedPt = innerRingPt;
  20928. return false;
  20929. }
  20930. }
  20931. }
  20932. return true;
  20933. }
  20934. add(ring) {
  20935. this._rings.add(ring);
  20936. this._totalEnv.expandToInclude(ring.getEnvelopeInternal());
  20937. }
  20938. }
  20939. class TopologyValidationError {
  20940. constructor() {
  20941. TopologyValidationError.constructor_.apply(this, arguments);
  20942. }
  20943. static constructor_() {
  20944. this._errorType = null;
  20945. this._pt = null;
  20946. if (arguments.length === 1) {
  20947. const errorType = arguments[0];
  20948. TopologyValidationError.constructor_.call(this, errorType, null);
  20949. } else if (arguments.length === 2) {
  20950. const errorType = arguments[0],
  20951. pt = arguments[1];
  20952. this._errorType = errorType;
  20953. if (pt !== null) this._pt = pt.copy();
  20954. }
  20955. }
  20956. getErrorType() {
  20957. return this._errorType;
  20958. }
  20959. getMessage() {
  20960. return TopologyValidationError.errMsg[this._errorType];
  20961. }
  20962. getCoordinate() {
  20963. return this._pt;
  20964. }
  20965. toString() {
  20966. let locStr = '';
  20967. if (this._pt !== null) locStr = ' at or near point ' + this._pt;
  20968. return this.getMessage() + locStr;
  20969. }
  20970. }
  20971. TopologyValidationError.ERROR = 0;
  20972. TopologyValidationError.REPEATED_POINT = 1;
  20973. TopologyValidationError.HOLE_OUTSIDE_SHELL = 2;
  20974. TopologyValidationError.NESTED_HOLES = 3;
  20975. TopologyValidationError.DISCONNECTED_INTERIOR = 4;
  20976. TopologyValidationError.SELF_INTERSECTION = 5;
  20977. TopologyValidationError.RING_SELF_INTERSECTION = 6;
  20978. TopologyValidationError.NESTED_SHELLS = 7;
  20979. TopologyValidationError.DUPLICATE_RINGS = 8;
  20980. TopologyValidationError.TOO_FEW_POINTS = 9;
  20981. TopologyValidationError.INVALID_COORDINATE = 10;
  20982. TopologyValidationError.RING_NOT_CLOSED = 11;
  20983. TopologyValidationError.errMsg = ['Topology Validation Error', 'Repeated Point', 'Hole lies outside shell', 'Holes are nested', 'Interior is disconnected', 'Self-intersection', 'Ring Self-intersection', 'Nested shells', 'Duplicate Rings', 'Too few distinct points in geometry component', 'Invalid Coordinate', 'Ring is not closed'];
  20984. class IsValidOp {
  20985. constructor() {
  20986. IsValidOp.constructor_.apply(this, arguments);
  20987. }
  20988. static constructor_() {
  20989. this._parentGeometry = null;
  20990. this._isSelfTouchingRingFormingHoleValid = false;
  20991. this._validErr = null;
  20992. const parentGeometry = arguments[0];
  20993. this._parentGeometry = parentGeometry;
  20994. }
  20995. static findPtNotNode(testCoords, searchRing, graph) {
  20996. const searchEdge = graph.findEdge(searchRing);
  20997. const eiList = searchEdge.getEdgeIntersectionList();
  20998. for (let i = 0; i < testCoords.length; i++) {
  20999. const pt = testCoords[i];
  21000. if (!eiList.isIntersection(pt)) return pt;
  21001. }
  21002. return null;
  21003. }
  21004. static isValid() {
  21005. if (arguments[0] instanceof Geometry) {
  21006. const geom = arguments[0];
  21007. const isValidOp = new IsValidOp(geom);
  21008. return isValidOp.isValid();
  21009. } else if (arguments[0] instanceof Coordinate) {
  21010. const coord = arguments[0];
  21011. if (Double.isNaN(coord.x)) return false;
  21012. if (Double.isInfinite(coord.x)) return false;
  21013. if (Double.isNaN(coord.y)) return false;
  21014. if (Double.isInfinite(coord.y)) return false;
  21015. return true;
  21016. }
  21017. }
  21018. checkInvalidCoordinates() {
  21019. if (arguments[0] instanceof Array) {
  21020. const coords = arguments[0];
  21021. for (let i = 0; i < coords.length; i++) if (!IsValidOp.isValid(coords[i])) {
  21022. this._validErr = new TopologyValidationError(TopologyValidationError.INVALID_COORDINATE, coords[i]);
  21023. return null;
  21024. }
  21025. } else if (arguments[0] instanceof Polygon) {
  21026. const poly = arguments[0];
  21027. this.checkInvalidCoordinates(poly.getExteriorRing().getCoordinates());
  21028. if (this._validErr !== null) return null;
  21029. for (let i = 0; i < poly.getNumInteriorRing(); i++) {
  21030. this.checkInvalidCoordinates(poly.getInteriorRingN(i).getCoordinates());
  21031. if (this._validErr !== null) return null;
  21032. }
  21033. }
  21034. }
  21035. checkHolesNotNested(p, graph) {
  21036. if (p.getNumInteriorRing() <= 0) return null;
  21037. const nestedTester = new IndexedNestedRingTester(graph);
  21038. for (let i = 0; i < p.getNumInteriorRing(); i++) {
  21039. const innerHole = p.getInteriorRingN(i);
  21040. if (innerHole.isEmpty()) continue;
  21041. nestedTester.add(innerHole);
  21042. }
  21043. const isNonNested = nestedTester.isNonNested();
  21044. if (!isNonNested) this._validErr = new TopologyValidationError(TopologyValidationError.NESTED_HOLES, nestedTester.getNestedPoint());
  21045. }
  21046. checkConsistentArea(graph) {
  21047. const cat = new ConsistentAreaTester(graph);
  21048. const isValidArea = cat.isNodeConsistentArea();
  21049. if (!isValidArea) {
  21050. this._validErr = new TopologyValidationError(TopologyValidationError.SELF_INTERSECTION, cat.getInvalidPoint());
  21051. return null;
  21052. }
  21053. if (cat.hasDuplicateRings()) this._validErr = new TopologyValidationError(TopologyValidationError.DUPLICATE_RINGS, cat.getInvalidPoint());
  21054. }
  21055. isValid() {
  21056. this.checkValid(this._parentGeometry);
  21057. return this._validErr === null;
  21058. }
  21059. checkShellInsideHole(shell, hole, graph) {
  21060. const shellPts = shell.getCoordinates();
  21061. const holePts = hole.getCoordinates();
  21062. const shellPt = IsValidOp.findPtNotNode(shellPts, hole, graph);
  21063. if (shellPt !== null) {
  21064. const insideHole = PointLocation.isInRing(shellPt, holePts);
  21065. if (!insideHole) return shellPt;
  21066. }
  21067. const holePt = IsValidOp.findPtNotNode(holePts, shell, graph);
  21068. if (holePt !== null) {
  21069. const insideShell = PointLocation.isInRing(holePt, shellPts);
  21070. if (insideShell) return holePt;
  21071. return null;
  21072. }
  21073. Assert.shouldNeverReachHere('points in shell and hole appear to be equal');
  21074. return null;
  21075. }
  21076. checkNoSelfIntersectingRings(graph) {
  21077. for (let i = graph.getEdgeIterator(); i.hasNext();) {
  21078. const e = i.next();
  21079. this.checkNoSelfIntersectingRing(e.getEdgeIntersectionList());
  21080. if (this._validErr !== null) return null;
  21081. }
  21082. }
  21083. checkConnectedInteriors(graph) {
  21084. const cit = new ConnectedInteriorTester(graph);
  21085. if (!cit.isInteriorsConnected()) this._validErr = new TopologyValidationError(TopologyValidationError.DISCONNECTED_INTERIOR, cit.getCoordinate());
  21086. }
  21087. checkNoSelfIntersectingRing(eiList) {
  21088. const nodeSet = new TreeSet();
  21089. let isFirst = true;
  21090. for (let i = eiList.iterator(); i.hasNext();) {
  21091. const ei = i.next();
  21092. if (isFirst) {
  21093. isFirst = false;
  21094. continue;
  21095. }
  21096. if (nodeSet.contains(ei.coord)) {
  21097. this._validErr = new TopologyValidationError(TopologyValidationError.RING_SELF_INTERSECTION, ei.coord);
  21098. return null;
  21099. } else {
  21100. nodeSet.add(ei.coord);
  21101. }
  21102. }
  21103. }
  21104. checkHolesInShell(p, graph) {
  21105. if (p.getNumInteriorRing() <= 0) return null;
  21106. const shell = p.getExteriorRing();
  21107. const isShellEmpty = shell.isEmpty();
  21108. const pir = new IndexedPointInAreaLocator(shell);
  21109. for (let i = 0; i < p.getNumInteriorRing(); i++) {
  21110. const hole = p.getInteriorRingN(i);
  21111. let holePt = null;
  21112. if (hole.isEmpty()) continue;
  21113. holePt = IsValidOp.findPtNotNode(hole.getCoordinates(), shell, graph);
  21114. if (holePt === null) return null;
  21115. const outside = isShellEmpty || Location.EXTERIOR === pir.locate(holePt);
  21116. if (outside) {
  21117. this._validErr = new TopologyValidationError(TopologyValidationError.HOLE_OUTSIDE_SHELL, holePt);
  21118. return null;
  21119. }
  21120. }
  21121. }
  21122. checkTooFewPoints(graph) {
  21123. if (graph.hasTooFewPoints()) {
  21124. this._validErr = new TopologyValidationError(TopologyValidationError.TOO_FEW_POINTS, graph.getInvalidPoint());
  21125. return null;
  21126. }
  21127. }
  21128. getValidationError() {
  21129. this.checkValid(this._parentGeometry);
  21130. return this._validErr;
  21131. }
  21132. checkValid() {
  21133. if (arguments[0] instanceof Point) {
  21134. const g = arguments[0];
  21135. this.checkInvalidCoordinates(g.getCoordinates());
  21136. } else if (arguments[0] instanceof MultiPoint) {
  21137. const g = arguments[0];
  21138. this.checkInvalidCoordinates(g.getCoordinates());
  21139. } else if (arguments[0] instanceof LinearRing) {
  21140. const g = arguments[0];
  21141. this.checkInvalidCoordinates(g.getCoordinates());
  21142. if (this._validErr !== null) return null;
  21143. this.checkClosedRing(g);
  21144. if (this._validErr !== null) return null;
  21145. const graph = new GeometryGraph(0, g);
  21146. this.checkTooFewPoints(graph);
  21147. if (this._validErr !== null) return null;
  21148. const li = new RobustLineIntersector();
  21149. graph.computeSelfNodes(li, true, true);
  21150. this.checkNoSelfIntersectingRings(graph);
  21151. } else if (arguments[0] instanceof LineString) {
  21152. const g = arguments[0];
  21153. this.checkInvalidCoordinates(g.getCoordinates());
  21154. if (this._validErr !== null) return null;
  21155. const graph = new GeometryGraph(0, g);
  21156. this.checkTooFewPoints(graph);
  21157. } else if (arguments[0] instanceof Polygon) {
  21158. const g = arguments[0];
  21159. this.checkInvalidCoordinates(g);
  21160. if (this._validErr !== null) return null;
  21161. this.checkClosedRings(g);
  21162. if (this._validErr !== null) return null;
  21163. const graph = new GeometryGraph(0, g);
  21164. this.checkTooFewPoints(graph);
  21165. if (this._validErr !== null) return null;
  21166. this.checkConsistentArea(graph);
  21167. if (this._validErr !== null) return null;
  21168. if (!this._isSelfTouchingRingFormingHoleValid) {
  21169. this.checkNoSelfIntersectingRings(graph);
  21170. if (this._validErr !== null) return null;
  21171. }
  21172. this.checkHolesInShell(g, graph);
  21173. if (this._validErr !== null) return null;
  21174. this.checkHolesNotNested(g, graph);
  21175. if (this._validErr !== null) return null;
  21176. this.checkConnectedInteriors(graph);
  21177. } else if (arguments[0] instanceof MultiPolygon) {
  21178. const g = arguments[0];
  21179. for (let i = 0; i < g.getNumGeometries(); i++) {
  21180. const p = g.getGeometryN(i);
  21181. this.checkInvalidCoordinates(p);
  21182. if (this._validErr !== null) return null;
  21183. this.checkClosedRings(p);
  21184. if (this._validErr !== null) return null;
  21185. }
  21186. const graph = new GeometryGraph(0, g);
  21187. this.checkTooFewPoints(graph);
  21188. if (this._validErr !== null) return null;
  21189. this.checkConsistentArea(graph);
  21190. if (this._validErr !== null) return null;
  21191. if (!this._isSelfTouchingRingFormingHoleValid) {
  21192. this.checkNoSelfIntersectingRings(graph);
  21193. if (this._validErr !== null) return null;
  21194. }
  21195. for (let i = 0; i < g.getNumGeometries(); i++) {
  21196. const p = g.getGeometryN(i);
  21197. this.checkHolesInShell(p, graph);
  21198. if (this._validErr !== null) return null;
  21199. }
  21200. for (let i = 0; i < g.getNumGeometries(); i++) {
  21201. const p = g.getGeometryN(i);
  21202. this.checkHolesNotNested(p, graph);
  21203. if (this._validErr !== null) return null;
  21204. }
  21205. this.checkShellsNotNested(g, graph);
  21206. if (this._validErr !== null) return null;
  21207. this.checkConnectedInteriors(graph);
  21208. } else if (arguments[0] instanceof GeometryCollection) {
  21209. const gc = arguments[0];
  21210. for (let i = 0; i < gc.getNumGeometries(); i++) {
  21211. const g = gc.getGeometryN(i);
  21212. this.checkValid(g);
  21213. if (this._validErr !== null) return null;
  21214. }
  21215. } else if (arguments[0] instanceof Geometry) {
  21216. const g = arguments[0];
  21217. this._validErr = null;
  21218. if (g.isEmpty()) return null;
  21219. if (g instanceof Point) this.checkValid(g);else if (g instanceof MultiPoint) this.checkValid(g);else if (g instanceof LinearRing) this.checkValid(g);else if (g instanceof LineString) this.checkValid(g);else if (g instanceof Polygon) this.checkValid(g);else if (g instanceof MultiPolygon) this.checkValid(g);else if (g instanceof GeometryCollection) this.checkValid(g);else throw new UnsupportedOperationException(g.getGeometryType());
  21220. }
  21221. }
  21222. setSelfTouchingRingFormingHoleValid(isValid) {
  21223. this._isSelfTouchingRingFormingHoleValid = isValid;
  21224. }
  21225. checkShellNotNested(shell, p, graph) {
  21226. const shellPts = shell.getCoordinates();
  21227. const polyShell = p.getExteriorRing();
  21228. if (polyShell.isEmpty()) return null;
  21229. const polyPts = polyShell.getCoordinates();
  21230. const shellPt = IsValidOp.findPtNotNode(shellPts, polyShell, graph);
  21231. if (shellPt === null) return null;
  21232. const insidePolyShell = PointLocation.isInRing(shellPt, polyPts);
  21233. if (!insidePolyShell) return null;
  21234. if (p.getNumInteriorRing() <= 0) {
  21235. this._validErr = new TopologyValidationError(TopologyValidationError.NESTED_SHELLS, shellPt);
  21236. return null;
  21237. }
  21238. let badNestedPt = null;
  21239. for (let i = 0; i < p.getNumInteriorRing(); i++) {
  21240. const hole = p.getInteriorRingN(i);
  21241. badNestedPt = this.checkShellInsideHole(shell, hole, graph);
  21242. if (badNestedPt === null) return null;
  21243. }
  21244. this._validErr = new TopologyValidationError(TopologyValidationError.NESTED_SHELLS, badNestedPt);
  21245. }
  21246. checkClosedRings(poly) {
  21247. this.checkClosedRing(poly.getExteriorRing());
  21248. if (this._validErr !== null) return null;
  21249. for (let i = 0; i < poly.getNumInteriorRing(); i++) {
  21250. this.checkClosedRing(poly.getInteriorRingN(i));
  21251. if (this._validErr !== null) return null;
  21252. }
  21253. }
  21254. checkClosedRing(ring) {
  21255. if (ring.isEmpty()) return null;
  21256. if (!ring.isClosed()) {
  21257. let pt = null;
  21258. if (ring.getNumPoints() >= 1) pt = ring.getCoordinateN(0);
  21259. this._validErr = new TopologyValidationError(TopologyValidationError.RING_NOT_CLOSED, pt);
  21260. }
  21261. }
  21262. checkShellsNotNested(mp, graph) {
  21263. for (let i = 0; i < mp.getNumGeometries(); i++) {
  21264. const p = mp.getGeometryN(i);
  21265. const shell = p.getExteriorRing();
  21266. for (let j = 0; j < mp.getNumGeometries(); j++) {
  21267. if (i === j) continue;
  21268. const p2 = mp.getGeometryN(j);
  21269. this.checkShellNotNested(shell, p2, graph);
  21270. if (this._validErr !== null) return null;
  21271. }
  21272. }
  21273. }
  21274. }
  21275. class EdgeRing {
  21276. constructor() {
  21277. EdgeRing.constructor_.apply(this, arguments);
  21278. }
  21279. static constructor_() {
  21280. this._factory = null;
  21281. this._deList = new ArrayList();
  21282. this._lowestEdge = null;
  21283. this._ring = null;
  21284. this._locator = null;
  21285. this._ringPts = null;
  21286. this._holes = null;
  21287. this._shell = null;
  21288. this._isHole = null;
  21289. this._isProcessed = false;
  21290. this._isIncludedSet = false;
  21291. this._isIncluded = false;
  21292. const factory = arguments[0];
  21293. this._factory = factory;
  21294. }
  21295. static findDirEdgesInRing(startDE) {
  21296. let de = startDE;
  21297. const edges = new ArrayList();
  21298. do {
  21299. edges.add(de);
  21300. de = de.getNext();
  21301. Assert.isTrue(de !== null, 'found null DE in ring');
  21302. Assert.isTrue(de === startDE || !de.isInRing(), 'found DE already in ring');
  21303. } while (de !== startDE);
  21304. return edges;
  21305. }
  21306. static addEdge(coords, isForward, coordList) {
  21307. if (isForward) for (let i = 0; i < coords.length; i++) coordList.add(coords[i], false);else for (let i = coords.length - 1; i >= 0; i--) coordList.add(coords[i], false);
  21308. }
  21309. static findEdgeRingContaining(testEr, erList) {
  21310. const testRing = testEr.getRing();
  21311. const testEnv = testRing.getEnvelopeInternal();
  21312. let testPt = testRing.getCoordinateN(0);
  21313. let minRing = null;
  21314. let minRingEnv = null;
  21315. for (let it = erList.iterator(); it.hasNext();) {
  21316. const tryEdgeRing = it.next();
  21317. const tryRing = tryEdgeRing.getRing();
  21318. const tryShellEnv = tryRing.getEnvelopeInternal();
  21319. if (tryShellEnv.equals(testEnv)) continue;
  21320. if (!tryShellEnv.contains(testEnv)) continue;
  21321. testPt = CoordinateArrays.ptNotInList(testRing.getCoordinates(), tryEdgeRing.getCoordinates());
  21322. const isContained = tryEdgeRing.isInRing(testPt);
  21323. if (isContained) if (minRing === null || minRingEnv.contains(tryShellEnv)) {
  21324. minRing = tryEdgeRing;
  21325. minRingEnv = minRing.getRing().getEnvelopeInternal();
  21326. }
  21327. }
  21328. return minRing;
  21329. }
  21330. isIncluded() {
  21331. return this._isIncluded;
  21332. }
  21333. getCoordinates() {
  21334. if (this._ringPts === null) {
  21335. const coordList = new CoordinateList();
  21336. for (let i = this._deList.iterator(); i.hasNext();) {
  21337. const de = i.next();
  21338. const edge = de.getEdge();
  21339. EdgeRing.addEdge(edge.getLine().getCoordinates(), de.getEdgeDirection(), coordList);
  21340. }
  21341. this._ringPts = coordList.toCoordinateArray();
  21342. }
  21343. return this._ringPts;
  21344. }
  21345. isIncludedSet() {
  21346. return this._isIncludedSet;
  21347. }
  21348. isValid() {
  21349. this.getCoordinates();
  21350. if (this._ringPts.length <= 3) return false;
  21351. this.getRing();
  21352. return IsValidOp.isValid(this._ring);
  21353. }
  21354. build(startDE) {
  21355. let de = startDE;
  21356. do {
  21357. this.add(de);
  21358. de.setRing(this);
  21359. de = de.getNext();
  21360. Assert.isTrue(de !== null, 'found null DE in ring');
  21361. Assert.isTrue(de === startDE || !de.isInRing(), 'found DE already in ring');
  21362. } while (de !== startDE);
  21363. }
  21364. isInRing(pt) {
  21365. return Location.EXTERIOR !== this.getLocator().locate(pt);
  21366. }
  21367. isOuterHole() {
  21368. if (!this._isHole) return false;
  21369. return !this.hasShell();
  21370. }
  21371. getPolygon() {
  21372. let holeLR = null;
  21373. if (this._holes !== null) {
  21374. holeLR = new Array(this._holes.size()).fill(null);
  21375. for (let i = 0; i < this._holes.size(); i++) holeLR[i] = this._holes.get(i);
  21376. }
  21377. const poly = this._factory.createPolygon(this._ring, holeLR);
  21378. return poly;
  21379. }
  21380. isHole() {
  21381. return this._isHole;
  21382. }
  21383. isProcessed() {
  21384. return this._isProcessed;
  21385. }
  21386. addHole() {
  21387. if (arguments[0] instanceof LinearRing) {
  21388. const hole = arguments[0];
  21389. if (this._holes === null) this._holes = new ArrayList();
  21390. this._holes.add(hole);
  21391. } else if (arguments[0] instanceof EdgeRing) {
  21392. const holeER = arguments[0];
  21393. holeER.setShell(this);
  21394. const hole = holeER.getRing();
  21395. if (this._holes === null) this._holes = new ArrayList();
  21396. this._holes.add(hole);
  21397. }
  21398. }
  21399. setIncluded(isIncluded) {
  21400. this._isIncluded = isIncluded;
  21401. this._isIncludedSet = true;
  21402. }
  21403. getOuterHole() {
  21404. if (this.isHole()) return null;
  21405. for (let i = 0; i < this._deList.size(); i++) {
  21406. const de = this._deList.get(i);
  21407. const adjRing = de.getSym().getRing();
  21408. if (adjRing.isOuterHole()) return adjRing;
  21409. }
  21410. return null;
  21411. }
  21412. computeHole() {
  21413. const ring = this.getRing();
  21414. this._isHole = Orientation.isCCW(ring.getCoordinates());
  21415. }
  21416. hasShell() {
  21417. return this._shell !== null;
  21418. }
  21419. isOuterShell() {
  21420. return this.getOuterHole() !== null;
  21421. }
  21422. getLineString() {
  21423. this.getCoordinates();
  21424. return this._factory.createLineString(this._ringPts);
  21425. }
  21426. toString() {
  21427. return WKTWriter.toLineString(new CoordinateArraySequence(this.getCoordinates()));
  21428. }
  21429. getLocator() {
  21430. if (this._locator === null) this._locator = new IndexedPointInAreaLocator(this.getRing());
  21431. return this._locator;
  21432. }
  21433. getShell() {
  21434. if (this.isHole()) return this._shell;
  21435. return this;
  21436. }
  21437. add(de) {
  21438. this._deList.add(de);
  21439. }
  21440. getRing() {
  21441. if (this._ring !== null) return this._ring;
  21442. this.getCoordinates();
  21443. if (this._ringPts.length < 3) System.out.println(this._ringPts);
  21444. try {
  21445. this._ring = this._factory.createLinearRing(this._ringPts);
  21446. } catch (ex) {
  21447. if (ex instanceof Exception) System.out.println(this._ringPts);else throw ex;
  21448. } finally {}
  21449. return this._ring;
  21450. }
  21451. updateIncluded() {
  21452. if (this.isHole()) return null;
  21453. for (let i = 0; i < this._deList.size(); i++) {
  21454. const de = this._deList.get(i);
  21455. const adjShell = de.getSym().getRing().getShell();
  21456. if (adjShell !== null && adjShell.isIncludedSet()) {
  21457. this.setIncluded(!adjShell.isIncluded());
  21458. return null;
  21459. }
  21460. }
  21461. }
  21462. setShell(shell) {
  21463. this._shell = shell;
  21464. }
  21465. setProcessed(isProcessed) {
  21466. this._isProcessed = isProcessed;
  21467. }
  21468. }
  21469. class EnvelopeComparator {
  21470. compare(obj0, obj1) {
  21471. const r0 = obj0;
  21472. const r1 = obj1;
  21473. return r0.getRing().getEnvelope().compareTo(r1.getRing().getEnvelope());
  21474. }
  21475. get interfaces_() {
  21476. return [Comparator];
  21477. }
  21478. }
  21479. EdgeRing.EnvelopeComparator = EnvelopeComparator;
  21480. class PolygonizeGraph extends PlanarGraph {
  21481. constructor() {
  21482. super();
  21483. PolygonizeGraph.constructor_.apply(this, arguments);
  21484. }
  21485. static constructor_() {
  21486. this._factory = null;
  21487. const factory = arguments[0];
  21488. this._factory = factory;
  21489. }
  21490. static findLabeledEdgeRings(dirEdges) {
  21491. const edgeRingStarts = new ArrayList();
  21492. let currLabel = 1;
  21493. for (let i = dirEdges.iterator(); i.hasNext();) {
  21494. const de = i.next();
  21495. if (de.isMarked()) continue;
  21496. if (de.getLabel() >= 0) continue;
  21497. edgeRingStarts.add(de);
  21498. const edges = EdgeRing.findDirEdgesInRing(de);
  21499. PolygonizeGraph.label(edges, currLabel);
  21500. currLabel++;
  21501. }
  21502. return edgeRingStarts;
  21503. }
  21504. static getDegreeNonDeleted(node) {
  21505. const edges = node.getOutEdges().getEdges();
  21506. let degree = 0;
  21507. for (let i = edges.iterator(); i.hasNext();) {
  21508. const de = i.next();
  21509. if (!de.isMarked()) degree++;
  21510. }
  21511. return degree;
  21512. }
  21513. static deleteAllEdges(node) {
  21514. const edges = node.getOutEdges().getEdges();
  21515. for (let i = edges.iterator(); i.hasNext();) {
  21516. const de = i.next();
  21517. de.setMarked(true);
  21518. const sym = de.getSym();
  21519. if (sym !== null) sym.setMarked(true);
  21520. }
  21521. }
  21522. static label(dirEdges, label) {
  21523. for (let i = dirEdges.iterator(); i.hasNext();) {
  21524. const de = i.next();
  21525. de.setLabel(label);
  21526. }
  21527. }
  21528. static computeNextCWEdges(node) {
  21529. const deStar = node.getOutEdges();
  21530. let startDE = null;
  21531. let prevDE = null;
  21532. for (let i = deStar.getEdges().iterator(); i.hasNext();) {
  21533. const outDE = i.next();
  21534. if (outDE.isMarked()) continue;
  21535. if (startDE === null) startDE = outDE;
  21536. if (prevDE !== null) {
  21537. const sym = prevDE.getSym();
  21538. sym.setNext(outDE);
  21539. }
  21540. prevDE = outDE;
  21541. }
  21542. if (prevDE !== null) {
  21543. const sym = prevDE.getSym();
  21544. sym.setNext(startDE);
  21545. }
  21546. }
  21547. static computeNextCCWEdges(node, label) {
  21548. const deStar = node.getOutEdges();
  21549. let firstOutDE = null;
  21550. let prevInDE = null;
  21551. const edges = deStar.getEdges();
  21552. for (let i = edges.size() - 1; i >= 0; i--) {
  21553. const de = edges.get(i);
  21554. const sym = de.getSym();
  21555. let outDE = null;
  21556. if (de.getLabel() === label) outDE = de;
  21557. let inDE = null;
  21558. if (sym.getLabel() === label) inDE = sym;
  21559. if (outDE === null && inDE === null) continue;
  21560. if (inDE !== null) prevInDE = inDE;
  21561. if (outDE !== null) {
  21562. if (prevInDE !== null) {
  21563. prevInDE.setNext(outDE);
  21564. prevInDE = null;
  21565. }
  21566. if (firstOutDE === null) firstOutDE = outDE;
  21567. }
  21568. }
  21569. if (prevInDE !== null) {
  21570. Assert.isTrue(firstOutDE !== null);
  21571. prevInDE.setNext(firstOutDE);
  21572. }
  21573. }
  21574. static getDegree(node, label) {
  21575. const edges = node.getOutEdges().getEdges();
  21576. let degree = 0;
  21577. for (let i = edges.iterator(); i.hasNext();) {
  21578. const de = i.next();
  21579. if (de.getLabel() === label) degree++;
  21580. }
  21581. return degree;
  21582. }
  21583. static findIntersectionNodes(startDE, label) {
  21584. let de = startDE;
  21585. let intNodes = null;
  21586. do {
  21587. const node = de.getFromNode();
  21588. if (PolygonizeGraph.getDegree(node, label) > 1) {
  21589. if (intNodes === null) intNodes = new ArrayList();
  21590. intNodes.add(node);
  21591. }
  21592. de = de.getNext();
  21593. Assert.isTrue(de !== null, 'found null DE in ring');
  21594. Assert.isTrue(de === startDE || !de.isInRing(), 'found DE already in ring');
  21595. } while (de !== startDE);
  21596. return intNodes;
  21597. }
  21598. findEdgeRing(startDE) {
  21599. const er = new EdgeRing(this._factory);
  21600. er.build(startDE);
  21601. return er;
  21602. }
  21603. computeDepthParity() {
  21604. if (arguments.length === 0) {
  21605. while (true) {
  21606. return null;
  21607. }
  21608. }
  21609. }
  21610. computeNextCWEdges() {
  21611. for (let iNode = this.nodeIterator(); iNode.hasNext();) {
  21612. const node = iNode.next();
  21613. PolygonizeGraph.computeNextCWEdges(node);
  21614. }
  21615. }
  21616. addEdge(line) {
  21617. if (line.isEmpty()) return null;
  21618. const linePts = CoordinateArrays.removeRepeatedPoints(line.getCoordinates());
  21619. if (linePts.length < 2) return null;
  21620. const startPt = linePts[0];
  21621. const endPt = linePts[linePts.length - 1];
  21622. const nStart = this.getNode(startPt);
  21623. const nEnd = this.getNode(endPt);
  21624. const de0 = new PolygonizeDirectedEdge(nStart, nEnd, linePts[1], true);
  21625. const de1 = new PolygonizeDirectedEdge(nEnd, nStart, linePts[linePts.length - 2], false);
  21626. const edge = new PolygonizeEdge(line);
  21627. edge.setDirectedEdges(de0, de1);
  21628. this.add(edge);
  21629. }
  21630. deleteCutEdges() {
  21631. this.computeNextCWEdges();
  21632. PolygonizeGraph.findLabeledEdgeRings(this._dirEdges);
  21633. const cutLines = new ArrayList();
  21634. for (let i = this._dirEdges.iterator(); i.hasNext();) {
  21635. const de = i.next();
  21636. if (de.isMarked()) continue;
  21637. const sym = de.getSym();
  21638. if (de.getLabel() === sym.getLabel()) {
  21639. de.setMarked(true);
  21640. sym.setMarked(true);
  21641. const e = de.getEdge();
  21642. cutLines.add(e.getLine());
  21643. }
  21644. }
  21645. return cutLines;
  21646. }
  21647. getEdgeRings() {
  21648. this.computeNextCWEdges();
  21649. PolygonizeGraph.label(this._dirEdges, -1);
  21650. const maximalRings = PolygonizeGraph.findLabeledEdgeRings(this._dirEdges);
  21651. this.convertMaximalToMinimalEdgeRings(maximalRings);
  21652. const edgeRingList = new ArrayList();
  21653. for (let i = this._dirEdges.iterator(); i.hasNext();) {
  21654. const de = i.next();
  21655. if (de.isMarked()) continue;
  21656. if (de.isInRing()) continue;
  21657. const er = this.findEdgeRing(de);
  21658. edgeRingList.add(er);
  21659. }
  21660. return edgeRingList;
  21661. }
  21662. getNode(pt) {
  21663. let node = this.findNode(pt);
  21664. if (node === null) {
  21665. node = new Node(pt);
  21666. this.add(node);
  21667. }
  21668. return node;
  21669. }
  21670. convertMaximalToMinimalEdgeRings(ringEdges) {
  21671. for (let i = ringEdges.iterator(); i.hasNext();) {
  21672. const de = i.next();
  21673. const label = de.getLabel();
  21674. const intNodes = PolygonizeGraph.findIntersectionNodes(de, label);
  21675. if (intNodes === null) continue;
  21676. for (let iNode = intNodes.iterator(); iNode.hasNext();) {
  21677. const node = iNode.next();
  21678. PolygonizeGraph.computeNextCCWEdges(node, label);
  21679. }
  21680. }
  21681. }
  21682. deleteDangles() {
  21683. const nodesToRemove = this.findNodesOfDegree(1);
  21684. const dangleLines = new HashSet();
  21685. const nodeStack = new Stack();
  21686. for (let i = nodesToRemove.iterator(); i.hasNext();) nodeStack.push(i.next());
  21687. while (!nodeStack.isEmpty()) {
  21688. const node = nodeStack.pop();
  21689. PolygonizeGraph.deleteAllEdges(node);
  21690. const nodeOutEdges = node.getOutEdges().getEdges();
  21691. for (let i = nodeOutEdges.iterator(); i.hasNext();) {
  21692. const de = i.next();
  21693. de.setMarked(true);
  21694. const sym = de.getSym();
  21695. if (sym !== null) sym.setMarked(true);
  21696. const e = de.getEdge();
  21697. dangleLines.add(e.getLine());
  21698. const toNode = de.getToNode();
  21699. if (PolygonizeGraph.getDegreeNonDeleted(toNode) === 1) nodeStack.push(toNode);
  21700. }
  21701. }
  21702. return dangleLines;
  21703. }
  21704. }
  21705. class HoleAssigner {
  21706. constructor() {
  21707. HoleAssigner.constructor_.apply(this, arguments);
  21708. }
  21709. static constructor_() {
  21710. this._shells = null;
  21711. this._shellIndex = null;
  21712. const shells = arguments[0];
  21713. this._shells = shells;
  21714. this.buildIndex();
  21715. }
  21716. static assignHolesToShells(holes, shells) {
  21717. const assigner = new HoleAssigner(shells);
  21718. assigner.assignHolesToShells(holes);
  21719. }
  21720. assignHolesToShells(holeList) {
  21721. for (let i = holeList.iterator(); i.hasNext();) {
  21722. const holeER = i.next();
  21723. this.assignHoleToShell(holeER);
  21724. }
  21725. }
  21726. buildIndex() {
  21727. this._shellIndex = new STRtree();
  21728. for (const shell of this._shells) this._shellIndex.insert(shell.getRing().getEnvelopeInternal(), shell);
  21729. }
  21730. queryOverlappingShells(ringEnv) {
  21731. return this._shellIndex.query(ringEnv);
  21732. }
  21733. findShellContaining(testEr) {
  21734. const testEnv = testEr.getRing().getEnvelopeInternal();
  21735. const candidateShells = this.queryOverlappingShells(testEnv);
  21736. return EdgeRing.findEdgeRingContaining(testEr, candidateShells);
  21737. }
  21738. assignHoleToShell(holeER) {
  21739. const shell = this.findShellContaining(holeER);
  21740. if (shell !== null) shell.addHole(holeER);
  21741. }
  21742. }
  21743. class Polygonizer {
  21744. constructor() {
  21745. Polygonizer.constructor_.apply(this, arguments);
  21746. }
  21747. static constructor_() {
  21748. this._lineStringAdder = new LineStringAdder(this);
  21749. this._graph = null;
  21750. this._dangles = new ArrayList();
  21751. this._cutEdges = new ArrayList();
  21752. this._invalidRingLines = new ArrayList();
  21753. this._holeList = null;
  21754. this._shellList = null;
  21755. this._polyList = null;
  21756. this._isCheckingRingsValid = true;
  21757. this._extractOnlyPolygonal = null;
  21758. this._geomFactory = null;
  21759. if (arguments.length === 0) {
  21760. Polygonizer.constructor_.call(this, false);
  21761. } else if (arguments.length === 1) {
  21762. const extractOnlyPolygonal = arguments[0];
  21763. this._extractOnlyPolygonal = extractOnlyPolygonal;
  21764. }
  21765. }
  21766. static extractPolygons(shellList, includeAll) {
  21767. const polyList = new ArrayList();
  21768. for (let i = shellList.iterator(); i.hasNext();) {
  21769. const er = i.next();
  21770. if (includeAll || er.isIncluded()) polyList.add(er.getPolygon());
  21771. }
  21772. return polyList;
  21773. }
  21774. static findOuterShells(shellList) {
  21775. for (let i = shellList.iterator(); i.hasNext();) {
  21776. const er = i.next();
  21777. const outerHoleER = er.getOuterHole();
  21778. if (outerHoleER !== null && !outerHoleER.isProcessed()) {
  21779. er.setIncluded(true);
  21780. outerHoleER.setProcessed(true);
  21781. }
  21782. }
  21783. }
  21784. static findDisjointShells(shellList) {
  21785. Polygonizer.findOuterShells(shellList);
  21786. let isMoreToScan = null;
  21787. do {
  21788. isMoreToScan = false;
  21789. for (let i = shellList.iterator(); i.hasNext();) {
  21790. const er = i.next();
  21791. if (er.isIncludedSet()) continue;
  21792. er.updateIncluded();
  21793. if (!er.isIncludedSet()) isMoreToScan = true;
  21794. }
  21795. } while (isMoreToScan);
  21796. }
  21797. getGeometry() {
  21798. if (this._geomFactory === null) this._geomFactory = new GeometryFactory();
  21799. this.polygonize();
  21800. if (this._extractOnlyPolygonal) return this._geomFactory.buildGeometry(this._polyList);
  21801. return this._geomFactory.createGeometryCollection(GeometryFactory.toGeometryArray(this._polyList));
  21802. }
  21803. getInvalidRingLines() {
  21804. this.polygonize();
  21805. return this._invalidRingLines;
  21806. }
  21807. findValidRings(edgeRingList, validEdgeRingList, invalidRingList) {
  21808. for (let i = edgeRingList.iterator(); i.hasNext();) {
  21809. const er = i.next();
  21810. if (er.isValid()) validEdgeRingList.add(er);else invalidRingList.add(er.getLineString());
  21811. }
  21812. }
  21813. polygonize() {
  21814. if (this._polyList !== null) return null;
  21815. this._polyList = new ArrayList();
  21816. if (this._graph === null) return null;
  21817. this._dangles = this._graph.deleteDangles();
  21818. this._cutEdges = this._graph.deleteCutEdges();
  21819. const edgeRingList = this._graph.getEdgeRings();
  21820. let validEdgeRingList = new ArrayList();
  21821. this._invalidRingLines = new ArrayList();
  21822. if (this._isCheckingRingsValid) this.findValidRings(edgeRingList, validEdgeRingList, this._invalidRingLines);else validEdgeRingList = edgeRingList;
  21823. this.findShellsAndHoles(validEdgeRingList);
  21824. HoleAssigner.assignHolesToShells(this._holeList, this._shellList);
  21825. Collections.sort(this._shellList, new EdgeRing.EnvelopeComparator());
  21826. let includeAll = true;
  21827. if (this._extractOnlyPolygonal) {
  21828. Polygonizer.findDisjointShells(this._shellList);
  21829. includeAll = false;
  21830. }
  21831. this._polyList = Polygonizer.extractPolygons(this._shellList, includeAll);
  21832. }
  21833. getDangles() {
  21834. this.polygonize();
  21835. return this._dangles;
  21836. }
  21837. getCutEdges() {
  21838. this.polygonize();
  21839. return this._cutEdges;
  21840. }
  21841. getPolygons() {
  21842. this.polygonize();
  21843. return this._polyList;
  21844. }
  21845. add() {
  21846. if (hasInterface(arguments[0], Collection)) {
  21847. const geomList = arguments[0];
  21848. for (let i = geomList.iterator(); i.hasNext();) {
  21849. const geometry = i.next();
  21850. this.add(geometry);
  21851. }
  21852. } else if (arguments[0] instanceof LineString) {
  21853. const line = arguments[0];
  21854. this._geomFactory = line.getFactory();
  21855. if (this._graph === null) this._graph = new PolygonizeGraph(this._geomFactory);
  21856. this._graph.addEdge(line);
  21857. } else if (arguments[0] instanceof Geometry) {
  21858. const g = arguments[0];
  21859. g.apply(this._lineStringAdder);
  21860. }
  21861. }
  21862. setCheckRingsValid(isCheckingRingsValid) {
  21863. this._isCheckingRingsValid = isCheckingRingsValid;
  21864. }
  21865. findShellsAndHoles(edgeRingList) {
  21866. this._holeList = new ArrayList();
  21867. this._shellList = new ArrayList();
  21868. for (let i = edgeRingList.iterator(); i.hasNext();) {
  21869. const er = i.next();
  21870. er.computeHole();
  21871. if (er.isHole()) this._holeList.add(er);else this._shellList.add(er);
  21872. }
  21873. }
  21874. }
  21875. class LineStringAdder {
  21876. constructor() {
  21877. LineStringAdder.constructor_.apply(this, arguments);
  21878. }
  21879. static constructor_() {
  21880. this.p = null;
  21881. const p = arguments[0];
  21882. this.p = p;
  21883. }
  21884. filter(g) {
  21885. if (g instanceof LineString) this.p.add(g);
  21886. }
  21887. get interfaces_() {
  21888. return [GeometryComponentFilter];
  21889. }
  21890. }
  21891. Polygonizer.LineStringAdder = LineStringAdder;
  21892. var polygonize = /*#__PURE__*/Object.freeze({
  21893. __proto__: null,
  21894. Polygonizer: Polygonizer
  21895. });
  21896. class RelateComputer {
  21897. constructor() {
  21898. RelateComputer.constructor_.apply(this, arguments);
  21899. }
  21900. static constructor_() {
  21901. this._li = new RobustLineIntersector();
  21902. this._ptLocator = new PointLocator();
  21903. this._arg = null;
  21904. this._nodes = new NodeMap$1(new RelateNodeFactory());
  21905. this._im = null;
  21906. this._isolatedEdges = new ArrayList();
  21907. this._invalidPoint = null;
  21908. const arg = arguments[0];
  21909. this._arg = arg;
  21910. }
  21911. insertEdgeEnds(ee) {
  21912. for (let i = ee.iterator(); i.hasNext();) {
  21913. const e = i.next();
  21914. this._nodes.add(e);
  21915. }
  21916. }
  21917. computeProperIntersectionIM(intersector, im) {
  21918. const dimA = this._arg[0].getGeometry().getDimension();
  21919. const dimB = this._arg[1].getGeometry().getDimension();
  21920. const hasProper = intersector.hasProperIntersection();
  21921. const hasProperInterior = intersector.hasProperInteriorIntersection();
  21922. if (dimA === 2 && dimB === 2) {
  21923. if (hasProper) im.setAtLeast('212101212');
  21924. } else if (dimA === 2 && dimB === 1) {
  21925. if (hasProper) im.setAtLeast('FFF0FFFF2');
  21926. if (hasProperInterior) im.setAtLeast('1FFFFF1FF');
  21927. } else if (dimA === 1 && dimB === 2) {
  21928. if (hasProper) im.setAtLeast('F0FFFFFF2');
  21929. if (hasProperInterior) im.setAtLeast('1F1FFFFFF');
  21930. } else if (dimA === 1 && dimB === 1) {
  21931. if (hasProperInterior) im.setAtLeast('0FFFFFFFF');
  21932. }
  21933. }
  21934. labelIsolatedEdges(thisIndex, targetIndex) {
  21935. for (let ei = this._arg[thisIndex].getEdgeIterator(); ei.hasNext();) {
  21936. const e = ei.next();
  21937. if (e.isIsolated()) {
  21938. this.labelIsolatedEdge(e, targetIndex, this._arg[targetIndex].getGeometry());
  21939. this._isolatedEdges.add(e);
  21940. }
  21941. }
  21942. }
  21943. labelIsolatedEdge(e, targetIndex, target) {
  21944. if (target.getDimension() > 0) {
  21945. const loc = this._ptLocator.locate(e.getCoordinate(), target);
  21946. e.getLabel().setAllLocations(targetIndex, loc);
  21947. } else {
  21948. e.getLabel().setAllLocations(targetIndex, Location.EXTERIOR);
  21949. }
  21950. }
  21951. computeIM() {
  21952. const im = new IntersectionMatrix();
  21953. im.set(Location.EXTERIOR, Location.EXTERIOR, 2);
  21954. if (!this._arg[0].getGeometry().getEnvelopeInternal().intersects(this._arg[1].getGeometry().getEnvelopeInternal())) {
  21955. this.computeDisjointIM(im);
  21956. return im;
  21957. }
  21958. this._arg[0].computeSelfNodes(this._li, false);
  21959. this._arg[1].computeSelfNodes(this._li, false);
  21960. const intersector = this._arg[0].computeEdgeIntersections(this._arg[1], this._li, false);
  21961. this.computeIntersectionNodes(0);
  21962. this.computeIntersectionNodes(1);
  21963. this.copyNodesAndLabels(0);
  21964. this.copyNodesAndLabels(1);
  21965. this.labelIsolatedNodes();
  21966. this.computeProperIntersectionIM(intersector, im);
  21967. const eeBuilder = new EdgeEndBuilder();
  21968. const ee0 = eeBuilder.computeEdgeEnds(this._arg[0].getEdgeIterator());
  21969. this.insertEdgeEnds(ee0);
  21970. const ee1 = eeBuilder.computeEdgeEnds(this._arg[1].getEdgeIterator());
  21971. this.insertEdgeEnds(ee1);
  21972. this.labelNodeEdges();
  21973. this.labelIsolatedEdges(0, 1);
  21974. this.labelIsolatedEdges(1, 0);
  21975. this.updateIM(im);
  21976. return im;
  21977. }
  21978. labelNodeEdges() {
  21979. for (let ni = this._nodes.iterator(); ni.hasNext();) {
  21980. const node = ni.next();
  21981. node.getEdges().computeLabelling(this._arg);
  21982. }
  21983. }
  21984. copyNodesAndLabels(argIndex) {
  21985. for (let i = this._arg[argIndex].getNodeIterator(); i.hasNext();) {
  21986. const graphNode = i.next();
  21987. const newNode = this._nodes.addNode(graphNode.getCoordinate());
  21988. newNode.setLabel(argIndex, graphNode.getLabel().getLocation(argIndex));
  21989. }
  21990. }
  21991. labelIntersectionNodes(argIndex) {
  21992. for (let i = this._arg[argIndex].getEdgeIterator(); i.hasNext();) {
  21993. const e = i.next();
  21994. const eLoc = e.getLabel().getLocation(argIndex);
  21995. for (let eiIt = e.getEdgeIntersectionList().iterator(); eiIt.hasNext();) {
  21996. const ei = eiIt.next();
  21997. const n = this._nodes.find(ei.coord);
  21998. if (n.getLabel().isNull(argIndex)) if (eLoc === Location.BOUNDARY) n.setLabelBoundary(argIndex);else n.setLabel(argIndex, Location.INTERIOR);
  21999. }
  22000. }
  22001. }
  22002. labelIsolatedNode(n, targetIndex) {
  22003. const loc = this._ptLocator.locate(n.getCoordinate(), this._arg[targetIndex].getGeometry());
  22004. n.getLabel().setAllLocations(targetIndex, loc);
  22005. }
  22006. computeIntersectionNodes(argIndex) {
  22007. for (let i = this._arg[argIndex].getEdgeIterator(); i.hasNext();) {
  22008. const e = i.next();
  22009. const eLoc = e.getLabel().getLocation(argIndex);
  22010. for (let eiIt = e.getEdgeIntersectionList().iterator(); eiIt.hasNext();) {
  22011. const ei = eiIt.next();
  22012. const n = this._nodes.addNode(ei.coord);
  22013. if (eLoc === Location.BOUNDARY) n.setLabelBoundary(argIndex);else if (n.getLabel().isNull(argIndex)) n.setLabel(argIndex, Location.INTERIOR);
  22014. }
  22015. }
  22016. }
  22017. labelIsolatedNodes() {
  22018. for (let ni = this._nodes.iterator(); ni.hasNext();) {
  22019. const n = ni.next();
  22020. const label = n.getLabel();
  22021. Assert.isTrue(label.getGeometryCount() > 0, 'node with empty label found');
  22022. if (n.isIsolated()) if (label.isNull(0)) this.labelIsolatedNode(n, 0);else this.labelIsolatedNode(n, 1);
  22023. }
  22024. }
  22025. updateIM(im) {
  22026. for (let ei = this._isolatedEdges.iterator(); ei.hasNext();) {
  22027. const e = ei.next();
  22028. e.updateIM(im);
  22029. }
  22030. for (let ni = this._nodes.iterator(); ni.hasNext();) {
  22031. const node = ni.next();
  22032. node.updateIM(im);
  22033. node.updateIMFromEdges(im);
  22034. }
  22035. }
  22036. computeDisjointIM(im) {
  22037. const ga = this._arg[0].getGeometry();
  22038. if (!ga.isEmpty()) {
  22039. im.set(Location.INTERIOR, Location.EXTERIOR, ga.getDimension());
  22040. im.set(Location.BOUNDARY, Location.EXTERIOR, ga.getBoundaryDimension());
  22041. }
  22042. const gb = this._arg[1].getGeometry();
  22043. if (!gb.isEmpty()) {
  22044. im.set(Location.EXTERIOR, Location.INTERIOR, gb.getDimension());
  22045. im.set(Location.EXTERIOR, Location.BOUNDARY, gb.getBoundaryDimension());
  22046. }
  22047. }
  22048. }
  22049. class RectangleContains {
  22050. constructor() {
  22051. RectangleContains.constructor_.apply(this, arguments);
  22052. }
  22053. static constructor_() {
  22054. this._rectEnv = null;
  22055. const rectangle = arguments[0];
  22056. this._rectEnv = rectangle.getEnvelopeInternal();
  22057. }
  22058. static contains(rectangle, b) {
  22059. const rc = new RectangleContains(rectangle);
  22060. return rc.contains(b);
  22061. }
  22062. isContainedInBoundary(geom) {
  22063. if (geom instanceof Polygon) return false;
  22064. if (geom instanceof Point) return this.isPointContainedInBoundary(geom);
  22065. if (geom instanceof LineString) return this.isLineStringContainedInBoundary(geom);
  22066. for (let i = 0; i < geom.getNumGeometries(); i++) {
  22067. const comp = geom.getGeometryN(i);
  22068. if (!this.isContainedInBoundary(comp)) return false;
  22069. }
  22070. return true;
  22071. }
  22072. isLineSegmentContainedInBoundary(p0, p1) {
  22073. if (p0.equals(p1)) return this.isPointContainedInBoundary(p0);
  22074. if (p0.x === p1.x) {
  22075. if (p0.x === this._rectEnv.getMinX() || p0.x === this._rectEnv.getMaxX()) return true;
  22076. } else if (p0.y === p1.y) {
  22077. if (p0.y === this._rectEnv.getMinY() || p0.y === this._rectEnv.getMaxY()) return true;
  22078. }
  22079. return false;
  22080. }
  22081. isLineStringContainedInBoundary(line) {
  22082. const seq = line.getCoordinateSequence();
  22083. const p0 = new Coordinate();
  22084. const p1 = new Coordinate();
  22085. for (let i = 0; i < seq.size() - 1; i++) {
  22086. seq.getCoordinate(i, p0);
  22087. seq.getCoordinate(i + 1, p1);
  22088. if (!this.isLineSegmentContainedInBoundary(p0, p1)) return false;
  22089. }
  22090. return true;
  22091. }
  22092. isPointContainedInBoundary() {
  22093. if (arguments[0] instanceof Point) {
  22094. const point = arguments[0];
  22095. return this.isPointContainedInBoundary(point.getCoordinate());
  22096. } else if (arguments[0] instanceof Coordinate) {
  22097. const pt = arguments[0];
  22098. return pt.x === this._rectEnv.getMinX() || pt.x === this._rectEnv.getMaxX() || pt.y === this._rectEnv.getMinY() || pt.y === this._rectEnv.getMaxY();
  22099. }
  22100. }
  22101. contains(geom) {
  22102. if (!this._rectEnv.contains(geom.getEnvelopeInternal())) return false;
  22103. if (this.isContainedInBoundary(geom)) return false;
  22104. return true;
  22105. }
  22106. }
  22107. class RectangleLineIntersector {
  22108. constructor() {
  22109. RectangleLineIntersector.constructor_.apply(this, arguments);
  22110. }
  22111. static constructor_() {
  22112. this._li = new RobustLineIntersector();
  22113. this._rectEnv = null;
  22114. this._diagUp0 = null;
  22115. this._diagUp1 = null;
  22116. this._diagDown0 = null;
  22117. this._diagDown1 = null;
  22118. const rectEnv = arguments[0];
  22119. this._rectEnv = rectEnv;
  22120. this._diagUp0 = new Coordinate(rectEnv.getMinX(), rectEnv.getMinY());
  22121. this._diagUp1 = new Coordinate(rectEnv.getMaxX(), rectEnv.getMaxY());
  22122. this._diagDown0 = new Coordinate(rectEnv.getMinX(), rectEnv.getMaxY());
  22123. this._diagDown1 = new Coordinate(rectEnv.getMaxX(), rectEnv.getMinY());
  22124. }
  22125. intersects(p0, p1) {
  22126. const segEnv = new Envelope(p0, p1);
  22127. if (!this._rectEnv.intersects(segEnv)) return false;
  22128. if (this._rectEnv.intersects(p0)) return true;
  22129. if (this._rectEnv.intersects(p1)) return true;
  22130. if (p0.compareTo(p1) > 0) {
  22131. const tmp = p0;
  22132. p0 = p1;
  22133. p1 = tmp;
  22134. }
  22135. let isSegUpwards = false;
  22136. if (p1.y > p0.y) isSegUpwards = true;
  22137. if (isSegUpwards) this._li.computeIntersection(p0, p1, this._diagDown0, this._diagDown1);else this._li.computeIntersection(p0, p1, this._diagUp0, this._diagUp1);
  22138. if (this._li.hasIntersection()) return true;
  22139. return false;
  22140. }
  22141. }
  22142. class RectangleIntersects {
  22143. constructor() {
  22144. RectangleIntersects.constructor_.apply(this, arguments);
  22145. }
  22146. static constructor_() {
  22147. this._rectangle = null;
  22148. this._rectEnv = null;
  22149. const rectangle = arguments[0];
  22150. this._rectangle = rectangle;
  22151. this._rectEnv = rectangle.getEnvelopeInternal();
  22152. }
  22153. static intersects(rectangle, b) {
  22154. const rp = new RectangleIntersects(rectangle);
  22155. return rp.intersects(b);
  22156. }
  22157. intersects(geom) {
  22158. if (!this._rectEnv.intersects(geom.getEnvelopeInternal())) return false;
  22159. const visitor = new EnvelopeIntersectsVisitor(this._rectEnv);
  22160. visitor.applyTo(geom);
  22161. if (visitor.intersects()) return true;
  22162. const ecpVisitor = new GeometryContainsPointVisitor(this._rectangle);
  22163. ecpVisitor.applyTo(geom);
  22164. if (ecpVisitor.containsPoint()) return true;
  22165. const riVisitor = new RectangleIntersectsSegmentVisitor(this._rectangle);
  22166. riVisitor.applyTo(geom);
  22167. if (riVisitor.intersects()) return true;
  22168. return false;
  22169. }
  22170. }
  22171. class EnvelopeIntersectsVisitor extends ShortCircuitedGeometryVisitor {
  22172. constructor() {
  22173. super();
  22174. EnvelopeIntersectsVisitor.constructor_.apply(this, arguments);
  22175. }
  22176. static constructor_() {
  22177. this._rectEnv = null;
  22178. this._intersects = false;
  22179. const rectEnv = arguments[0];
  22180. this._rectEnv = rectEnv;
  22181. }
  22182. isDone() {
  22183. return this._intersects === true;
  22184. }
  22185. visit(element) {
  22186. const elementEnv = element.getEnvelopeInternal();
  22187. if (!this._rectEnv.intersects(elementEnv)) return null;
  22188. if (this._rectEnv.contains(elementEnv)) {
  22189. this._intersects = true;
  22190. return null;
  22191. }
  22192. if (elementEnv.getMinX() >= this._rectEnv.getMinX() && elementEnv.getMaxX() <= this._rectEnv.getMaxX()) {
  22193. this._intersects = true;
  22194. return null;
  22195. }
  22196. if (elementEnv.getMinY() >= this._rectEnv.getMinY() && elementEnv.getMaxY() <= this._rectEnv.getMaxY()) {
  22197. this._intersects = true;
  22198. return null;
  22199. }
  22200. }
  22201. intersects() {
  22202. return this._intersects;
  22203. }
  22204. }
  22205. class GeometryContainsPointVisitor extends ShortCircuitedGeometryVisitor {
  22206. constructor() {
  22207. super();
  22208. GeometryContainsPointVisitor.constructor_.apply(this, arguments);
  22209. }
  22210. static constructor_() {
  22211. this._rectSeq = null;
  22212. this._rectEnv = null;
  22213. this._containsPoint = false;
  22214. const rectangle = arguments[0];
  22215. this._rectSeq = rectangle.getExteriorRing().getCoordinateSequence();
  22216. this._rectEnv = rectangle.getEnvelopeInternal();
  22217. }
  22218. isDone() {
  22219. return this._containsPoint === true;
  22220. }
  22221. visit(geom) {
  22222. if (!(geom instanceof Polygon)) return null;
  22223. const elementEnv = geom.getEnvelopeInternal();
  22224. if (!this._rectEnv.intersects(elementEnv)) return null;
  22225. const rectPt = new Coordinate();
  22226. for (let i = 0; i < 4; i++) {
  22227. this._rectSeq.getCoordinate(i, rectPt);
  22228. if (!elementEnv.contains(rectPt)) continue;
  22229. if (SimplePointInAreaLocator.containsPointInPolygon(rectPt, geom)) {
  22230. this._containsPoint = true;
  22231. return null;
  22232. }
  22233. }
  22234. }
  22235. containsPoint() {
  22236. return this._containsPoint;
  22237. }
  22238. }
  22239. class RectangleIntersectsSegmentVisitor extends ShortCircuitedGeometryVisitor {
  22240. constructor() {
  22241. super();
  22242. RectangleIntersectsSegmentVisitor.constructor_.apply(this, arguments);
  22243. }
  22244. static constructor_() {
  22245. this._rectEnv = null;
  22246. this._rectIntersector = null;
  22247. this._hasIntersection = false;
  22248. this._p0 = new Coordinate();
  22249. this._p1 = new Coordinate();
  22250. const rectangle = arguments[0];
  22251. this._rectEnv = rectangle.getEnvelopeInternal();
  22252. this._rectIntersector = new RectangleLineIntersector(this._rectEnv);
  22253. }
  22254. intersects() {
  22255. return this._hasIntersection;
  22256. }
  22257. isDone() {
  22258. return this._hasIntersection === true;
  22259. }
  22260. visit(geom) {
  22261. const elementEnv = geom.getEnvelopeInternal();
  22262. if (!this._rectEnv.intersects(elementEnv)) return null;
  22263. const lines = LinearComponentExtracter.getLines(geom);
  22264. this.checkIntersectionWithLineStrings(lines);
  22265. }
  22266. checkIntersectionWithLineStrings(lines) {
  22267. for (let i = lines.iterator(); i.hasNext();) {
  22268. const testLine = i.next();
  22269. this.checkIntersectionWithSegments(testLine);
  22270. if (this._hasIntersection) return null;
  22271. }
  22272. }
  22273. checkIntersectionWithSegments(testLine) {
  22274. const seq1 = testLine.getCoordinateSequence();
  22275. for (let j = 1; j < seq1.size(); j++) {
  22276. seq1.getCoordinate(j - 1, this._p0);
  22277. seq1.getCoordinate(j, this._p1);
  22278. if (this._rectIntersector.intersects(this._p0, this._p1)) {
  22279. this._hasIntersection = true;
  22280. return null;
  22281. }
  22282. }
  22283. }
  22284. }
  22285. class RelateOp extends GeometryGraphOperation {
  22286. constructor() {
  22287. super();
  22288. RelateOp.constructor_.apply(this, arguments);
  22289. }
  22290. static constructor_() {
  22291. this._relate = null;
  22292. if (arguments.length === 2) {
  22293. const g0 = arguments[0],
  22294. g1 = arguments[1];
  22295. GeometryGraphOperation.constructor_.call(this, g0, g1);
  22296. this._relate = new RelateComputer(this._arg);
  22297. } else if (arguments.length === 3) {
  22298. const g0 = arguments[0],
  22299. g1 = arguments[1],
  22300. boundaryNodeRule = arguments[2];
  22301. GeometryGraphOperation.constructor_.call(this, g0, g1, boundaryNodeRule);
  22302. this._relate = new RelateComputer(this._arg);
  22303. }
  22304. }
  22305. static covers(g1, g2) {
  22306. if (g2.getDimension() === 2 && g1.getDimension() < 2) return false;
  22307. if (g2.getDimension() === 1 && g1.getDimension() < 1 && g2.getLength() > 0.0) return false;
  22308. if (!g1.getEnvelopeInternal().covers(g2.getEnvelopeInternal())) return false;
  22309. if (g1.isRectangle()) return true;
  22310. return new RelateOp(g1, g2).getIntersectionMatrix().isCovers();
  22311. }
  22312. static intersects(g1, g2) {
  22313. if (!g1.getEnvelopeInternal().intersects(g2.getEnvelopeInternal())) return false;
  22314. if (g1.isRectangle()) return RectangleIntersects.intersects(g1, g2);
  22315. if (g2.isRectangle()) return RectangleIntersects.intersects(g2, g1);
  22316. if (g1.isGeometryCollection() || g2.isGeometryCollection()) {
  22317. for (let i = 0; i < g1.getNumGeometries(); i++) for (let j = 0; j < g2.getNumGeometries(); j++) if (g1.getGeometryN(i).intersects(g2.getGeometryN(j))) return true;
  22318. return false;
  22319. }
  22320. return new RelateOp(g1, g2).getIntersectionMatrix().isIntersects();
  22321. }
  22322. static touches(g1, g2) {
  22323. if (!g1.getEnvelopeInternal().intersects(g2.getEnvelopeInternal())) return false;
  22324. return new RelateOp(g1, g2).getIntersectionMatrix().isTouches(g1.getDimension(), g2.getDimension());
  22325. }
  22326. static equalsTopo(g1, g2) {
  22327. if (!g1.getEnvelopeInternal().equals(g2.getEnvelopeInternal())) return false;
  22328. return RelateOp.relate(g1, g2).isEquals(g1.getDimension(), g2.getDimension());
  22329. }
  22330. static relate() {
  22331. if (arguments.length === 2) {
  22332. const a = arguments[0],
  22333. b = arguments[1];
  22334. const relOp = new RelateOp(a, b);
  22335. const im = relOp.getIntersectionMatrix();
  22336. return im;
  22337. } else if (arguments.length === 3) {
  22338. const a = arguments[0],
  22339. b = arguments[1],
  22340. boundaryNodeRule = arguments[2];
  22341. const relOp = new RelateOp(a, b, boundaryNodeRule);
  22342. const im = relOp.getIntersectionMatrix();
  22343. return im;
  22344. }
  22345. }
  22346. static overlaps(g1, g2) {
  22347. if (!g1.getEnvelopeInternal().intersects(g2.getEnvelopeInternal())) return false;
  22348. return new RelateOp(g1, g2).getIntersectionMatrix().isOverlaps(g1.getDimension(), g2.getDimension());
  22349. }
  22350. static crosses(g1, g2) {
  22351. if (!g1.getEnvelopeInternal().intersects(g2.getEnvelopeInternal())) return false;
  22352. return new RelateOp(g1, g2).getIntersectionMatrix().isCrosses(g1.getDimension(), g2.getDimension());
  22353. }
  22354. static contains(g1, g2) {
  22355. if (g2.getDimension() === 2 && g1.getDimension() < 2) return false;
  22356. if (g2.getDimension() === 1 && g1.getDimension() < 1 && g2.getLength() > 0.0) return false;
  22357. if (!g1.getEnvelopeInternal().contains(g2.getEnvelopeInternal())) return false;
  22358. if (g1.isRectangle()) return RectangleContains.contains(g1, g2);
  22359. return new RelateOp(g1, g2).getIntersectionMatrix().isContains();
  22360. }
  22361. getIntersectionMatrix() {
  22362. return this._relate.computeIM();
  22363. }
  22364. }
  22365. var relate = /*#__PURE__*/Object.freeze({
  22366. __proto__: null,
  22367. RelateOp: RelateOp
  22368. });
  22369. class PointGeometryUnion {
  22370. constructor() {
  22371. PointGeometryUnion.constructor_.apply(this, arguments);
  22372. }
  22373. static constructor_() {
  22374. this._pointGeom = null;
  22375. this._otherGeom = null;
  22376. this._geomFact = null;
  22377. const pointGeom = arguments[0],
  22378. otherGeom = arguments[1];
  22379. this._pointGeom = pointGeom;
  22380. this._otherGeom = otherGeom;
  22381. this._geomFact = otherGeom.getFactory();
  22382. }
  22383. static union(pointGeom, otherGeom) {
  22384. const unioner = new PointGeometryUnion(pointGeom, otherGeom);
  22385. return unioner.union();
  22386. }
  22387. union() {
  22388. const locater = new PointLocator();
  22389. const exteriorCoords = new TreeSet();
  22390. for (let i = 0; i < this._pointGeom.getNumGeometries(); i++) {
  22391. const point = this._pointGeom.getGeometryN(i);
  22392. const coord = point.getCoordinate();
  22393. const loc = locater.locate(coord, this._otherGeom);
  22394. if (loc === Location.EXTERIOR) exteriorCoords.add(coord);
  22395. }
  22396. if (exteriorCoords.size() === 0) return this._otherGeom;
  22397. let ptComp = null;
  22398. const coords = CoordinateArrays.toCoordinateArray(exteriorCoords);
  22399. if (coords.length === 1) ptComp = this._geomFact.createPoint(coords[0]);else ptComp = this._geomFact.createMultiPointFromCoords(coords);
  22400. return GeometryCombiner.combine(ptComp, this._otherGeom);
  22401. }
  22402. }
  22403. class InputExtracter {
  22404. constructor() {
  22405. InputExtracter.constructor_.apply(this, arguments);
  22406. }
  22407. static constructor_() {
  22408. this._geomFactory = null;
  22409. this._polygons = new ArrayList();
  22410. this._lines = new ArrayList();
  22411. this._points = new ArrayList();
  22412. this._dimension = Dimension.FALSE;
  22413. }
  22414. static extract() {
  22415. if (hasInterface(arguments[0], Collection)) {
  22416. const geoms = arguments[0];
  22417. const extracter = new InputExtracter();
  22418. extracter.add(geoms);
  22419. return extracter;
  22420. } else if (arguments[0] instanceof Geometry) {
  22421. const geom = arguments[0];
  22422. const extracter = new InputExtracter();
  22423. extracter.add(geom);
  22424. return extracter;
  22425. }
  22426. }
  22427. getFactory() {
  22428. return this._geomFactory;
  22429. }
  22430. recordDimension(dim) {
  22431. if (dim > this._dimension) this._dimension = dim;
  22432. }
  22433. getDimension() {
  22434. return this._dimension;
  22435. }
  22436. filter(geom) {
  22437. this.recordDimension(geom.getDimension());
  22438. if (geom instanceof GeometryCollection) return null;
  22439. if (geom.isEmpty()) return null;
  22440. if (geom instanceof Polygon) {
  22441. this._polygons.add(geom);
  22442. return null;
  22443. } else if (geom instanceof LineString) {
  22444. this._lines.add(geom);
  22445. return null;
  22446. } else if (geom instanceof Point) {
  22447. this._points.add(geom);
  22448. return null;
  22449. }
  22450. Assert.shouldNeverReachHere('Unhandled geometry type: ' + geom.getGeometryType());
  22451. }
  22452. getExtract(dim) {
  22453. switch (dim) {
  22454. case 0:
  22455. return this._points;
  22456. case 1:
  22457. return this._lines;
  22458. case 2:
  22459. return this._polygons;
  22460. }
  22461. Assert.shouldNeverReachHere('Invalid dimension: ' + dim);
  22462. return null;
  22463. }
  22464. isEmpty() {
  22465. return this._polygons.isEmpty() && this._lines.isEmpty() && this._points.isEmpty();
  22466. }
  22467. add() {
  22468. if (hasInterface(arguments[0], Collection)) {
  22469. const geoms = arguments[0];
  22470. for (const geom of geoms) this.add(geom);
  22471. } else if (arguments[0] instanceof Geometry) {
  22472. const geom = arguments[0];
  22473. if (this._geomFactory === null) this._geomFactory = geom.getFactory();
  22474. geom.apply(this);
  22475. }
  22476. }
  22477. get interfaces_() {
  22478. return [GeometryFilter];
  22479. }
  22480. }
  22481. class OverlapUnion {
  22482. constructor() {
  22483. OverlapUnion.constructor_.apply(this, arguments);
  22484. }
  22485. static constructor_() {
  22486. this._geomFactory = null;
  22487. this._g0 = null;
  22488. this._g1 = null;
  22489. this._isUnionSafe = null;
  22490. const g0 = arguments[0],
  22491. g1 = arguments[1];
  22492. this._g0 = g0;
  22493. this._g1 = g1;
  22494. this._geomFactory = g0.getFactory();
  22495. }
  22496. static containsProperly() {
  22497. if (arguments.length === 2) {
  22498. const env = arguments[0],
  22499. p = arguments[1];
  22500. if (env.isNull()) return false;
  22501. return p.getX() > env.getMinX() && p.getX() < env.getMaxX() && p.getY() > env.getMinY() && p.getY() < env.getMaxY();
  22502. } else if (arguments.length === 3) {
  22503. const env = arguments[0],
  22504. p0 = arguments[1],
  22505. p1 = arguments[2];
  22506. return OverlapUnion.containsProperly(env, p0) && OverlapUnion.containsProperly(env, p1);
  22507. }
  22508. }
  22509. static union(g0, g1) {
  22510. const union = new OverlapUnion(g0, g1);
  22511. return union.union();
  22512. }
  22513. static intersects(env, p0, p1) {
  22514. return env.intersects(p0) || env.intersects(p1);
  22515. }
  22516. static overlapEnvelope(g0, g1) {
  22517. const g0Env = g0.getEnvelopeInternal();
  22518. const g1Env = g1.getEnvelopeInternal();
  22519. const overlapEnv = g0Env.intersection(g1Env);
  22520. return overlapEnv;
  22521. }
  22522. static extractBorderSegments(geom, env, segs) {
  22523. geom.apply(new class {
  22524. get interfaces_() {
  22525. return [CoordinateSequenceFilter];
  22526. }
  22527. filter(seq, i) {
  22528. if (i <= 0) return null;
  22529. const p0 = seq.getCoordinate(i - 1);
  22530. const p1 = seq.getCoordinate(i);
  22531. const isBorder = OverlapUnion.intersects(env, p0, p1) && !OverlapUnion.containsProperly(env, p0, p1);
  22532. if (isBorder) {
  22533. const seg = new LineSegment(p0, p1);
  22534. segs.add(seg);
  22535. }
  22536. }
  22537. isDone() {
  22538. return false;
  22539. }
  22540. isGeometryChanged() {
  22541. return false;
  22542. }
  22543. }());
  22544. }
  22545. static unionBuffer(g0, g1) {
  22546. const factory = g0.getFactory();
  22547. const gColl = factory.createGeometryCollection([g0, g1]);
  22548. const union = gColl.buffer(0.0);
  22549. return union;
  22550. }
  22551. isBorderSegmentsSame(result, env) {
  22552. const segsBefore = this.extractBorderSegments(this._g0, this._g1, env);
  22553. const segsAfter = new ArrayList();
  22554. OverlapUnion.extractBorderSegments(result, env, segsAfter);
  22555. return this.isEqual(segsBefore, segsAfter);
  22556. }
  22557. extractByEnvelope(env, geom, disjointGeoms) {
  22558. const intersectingGeoms = new ArrayList();
  22559. for (let i = 0; i < geom.getNumGeometries(); i++) {
  22560. const elem = geom.getGeometryN(i);
  22561. if (elem.getEnvelopeInternal().intersects(env)) {
  22562. intersectingGeoms.add(elem);
  22563. } else {
  22564. const copy = elem.copy();
  22565. disjointGeoms.add(copy);
  22566. }
  22567. }
  22568. return this._geomFactory.buildGeometry(intersectingGeoms);
  22569. }
  22570. isEqual(segs0, segs1) {
  22571. if (segs0.size() !== segs1.size()) return false;
  22572. const segIndex = new HashSet(segs0);
  22573. for (const seg of segs1) if (!segIndex.contains(seg)) return false;
  22574. return true;
  22575. }
  22576. union() {
  22577. const overlapEnv = OverlapUnion.overlapEnvelope(this._g0, this._g1);
  22578. if (overlapEnv.isNull()) {
  22579. const g0Copy = this._g0.copy();
  22580. const g1Copy = this._g1.copy();
  22581. return GeometryCombiner.combine(g0Copy, g1Copy);
  22582. }
  22583. const disjointPolys = new ArrayList();
  22584. const g0Overlap = this.extractByEnvelope(overlapEnv, this._g0, disjointPolys);
  22585. const g1Overlap = this.extractByEnvelope(overlapEnv, this._g1, disjointPolys);
  22586. const unionGeom = this.unionFull(g0Overlap, g1Overlap);
  22587. let result = null;
  22588. this._isUnionSafe = this.isBorderSegmentsSame(unionGeom, overlapEnv);
  22589. if (!this._isUnionSafe) result = this.unionFull(this._g0, this._g1);else result = this.combine(unionGeom, disjointPolys);
  22590. return result;
  22591. }
  22592. combine(unionGeom, disjointPolys) {
  22593. if (disjointPolys.size() <= 0) return unionGeom;
  22594. disjointPolys.add(unionGeom);
  22595. const result = GeometryCombiner.combine(disjointPolys);
  22596. return result;
  22597. }
  22598. unionFull(geom0, geom1) {
  22599. try {
  22600. return geom0.union(geom1);
  22601. } catch (ex) {
  22602. if (ex instanceof TopologyException) return OverlapUnion.unionBuffer(geom0, geom1);else throw ex;
  22603. } finally {}
  22604. }
  22605. extractBorderSegments(geom0, geom1, env) {
  22606. const segs = new ArrayList();
  22607. OverlapUnion.extractBorderSegments(geom0, env, segs);
  22608. if (geom1 !== null) OverlapUnion.extractBorderSegments(geom1, env, segs);
  22609. return segs;
  22610. }
  22611. isUnionOptimized() {
  22612. return this._isUnionSafe;
  22613. }
  22614. }
  22615. class CascadedPolygonUnion {
  22616. constructor() {
  22617. CascadedPolygonUnion.constructor_.apply(this, arguments);
  22618. }
  22619. static constructor_() {
  22620. this._inputPolys = null;
  22621. this._geomFactory = null;
  22622. const polys = arguments[0];
  22623. this._inputPolys = polys;
  22624. if (this._inputPolys === null) this._inputPolys = new ArrayList();
  22625. }
  22626. static restrictToPolygons(g) {
  22627. if (hasInterface(g, Polygonal)) return g;
  22628. const polygons = PolygonExtracter.getPolygons(g);
  22629. if (polygons.size() === 1) return polygons.get(0);
  22630. return g.getFactory().createMultiPolygon(GeometryFactory.toPolygonArray(polygons));
  22631. }
  22632. static getGeometry(list, index) {
  22633. if (index >= list.size()) return null;
  22634. return list.get(index);
  22635. }
  22636. static union(polys) {
  22637. const op = new CascadedPolygonUnion(polys);
  22638. return op.union();
  22639. }
  22640. reduceToGeometries(geomTree) {
  22641. const geoms = new ArrayList();
  22642. for (let i = geomTree.iterator(); i.hasNext();) {
  22643. const o = i.next();
  22644. let geom = null;
  22645. if (hasInterface(o, List)) geom = this.unionTree(o);else if (o instanceof Geometry) geom = o;
  22646. geoms.add(geom);
  22647. }
  22648. return geoms;
  22649. }
  22650. union() {
  22651. if (this._inputPolys === null) throw new IllegalStateException('union() method cannot be called twice');
  22652. if (this._inputPolys.isEmpty()) return null;
  22653. this._geomFactory = this._inputPolys.iterator().next().getFactory();
  22654. const index = new STRtree(CascadedPolygonUnion.STRTREE_NODE_CAPACITY);
  22655. for (let i = this._inputPolys.iterator(); i.hasNext();) {
  22656. const item = i.next();
  22657. index.insert(item.getEnvelopeInternal(), item);
  22658. }
  22659. this._inputPolys = null;
  22660. const itemTree = index.itemsTree();
  22661. const unionAll = this.unionTree(itemTree);
  22662. return unionAll;
  22663. }
  22664. binaryUnion() {
  22665. if (arguments.length === 1) {
  22666. const geoms = arguments[0];
  22667. return this.binaryUnion(geoms, 0, geoms.size());
  22668. } else if (arguments.length === 3) {
  22669. const geoms = arguments[0],
  22670. start = arguments[1],
  22671. end = arguments[2];
  22672. if (end - start <= 1) {
  22673. const g0 = CascadedPolygonUnion.getGeometry(geoms, start);
  22674. return this.unionSafe(g0, null);
  22675. } else if (end - start === 2) {
  22676. return this.unionSafe(CascadedPolygonUnion.getGeometry(geoms, start), CascadedPolygonUnion.getGeometry(geoms, start + 1));
  22677. } else {
  22678. const mid = Math.trunc((end + start) / 2);
  22679. const g0 = this.binaryUnion(geoms, start, mid);
  22680. const g1 = this.binaryUnion(geoms, mid, end);
  22681. return this.unionSafe(g0, g1);
  22682. }
  22683. }
  22684. }
  22685. repeatedUnion(geoms) {
  22686. let union = null;
  22687. for (let i = geoms.iterator(); i.hasNext();) {
  22688. const g = i.next();
  22689. if (union === null) union = g.copy();else union = union.union(g);
  22690. }
  22691. return union;
  22692. }
  22693. unionSafe(g0, g1) {
  22694. if (g0 === null && g1 === null) return null;
  22695. if (g0 === null) return g1.copy();
  22696. if (g1 === null) return g0.copy();
  22697. return this.unionActual(g0, g1);
  22698. }
  22699. unionActual(g0, g1) {
  22700. const union = OverlapUnion.union(g0, g1);
  22701. return CascadedPolygonUnion.restrictToPolygons(union);
  22702. }
  22703. unionTree(geomTree) {
  22704. const geoms = this.reduceToGeometries(geomTree);
  22705. const union = this.binaryUnion(geoms);
  22706. return union;
  22707. }
  22708. bufferUnion() {
  22709. if (arguments.length === 1) {
  22710. const geoms = arguments[0];
  22711. const factory = geoms.get(0).getFactory();
  22712. const gColl = factory.buildGeometry(geoms);
  22713. const unionAll = gColl.buffer(0.0);
  22714. return unionAll;
  22715. } else if (arguments.length === 2) {
  22716. const g0 = arguments[0],
  22717. g1 = arguments[1];
  22718. const factory = g0.getFactory();
  22719. const gColl = factory.createGeometryCollection([g0, g1]);
  22720. const unionAll = gColl.buffer(0.0);
  22721. return unionAll;
  22722. }
  22723. }
  22724. }
  22725. CascadedPolygonUnion.STRTREE_NODE_CAPACITY = 4;
  22726. class UnaryUnionOp {
  22727. constructor() {
  22728. UnaryUnionOp.constructor_.apply(this, arguments);
  22729. }
  22730. static constructor_() {
  22731. this._geomFact = null;
  22732. this._extracter = null;
  22733. if (arguments.length === 1) {
  22734. if (hasInterface(arguments[0], Collection)) {
  22735. const geoms = arguments[0];
  22736. this.extract(geoms);
  22737. } else if (arguments[0] instanceof Geometry) {
  22738. const geom = arguments[0];
  22739. this.extract(geom);
  22740. }
  22741. } else if (arguments.length === 2) {
  22742. const geoms = arguments[0],
  22743. geomFact = arguments[1];
  22744. this._geomFact = geomFact;
  22745. this.extract(geoms);
  22746. }
  22747. }
  22748. static union() {
  22749. if (arguments.length === 1) {
  22750. if (hasInterface(arguments[0], Collection)) {
  22751. const geoms = arguments[0];
  22752. const op = new UnaryUnionOp(geoms);
  22753. return op.union();
  22754. } else if (arguments[0] instanceof Geometry) {
  22755. const geom = arguments[0];
  22756. const op = new UnaryUnionOp(geom);
  22757. return op.union();
  22758. }
  22759. } else if (arguments.length === 2) {
  22760. const geoms = arguments[0],
  22761. geomFact = arguments[1];
  22762. const op = new UnaryUnionOp(geoms, geomFact);
  22763. return op.union();
  22764. }
  22765. }
  22766. unionNoOpt(g0) {
  22767. const empty = this._geomFact.createPoint();
  22768. return SnapIfNeededOverlayOp.overlayOp(g0, empty, OverlayOp.UNION);
  22769. }
  22770. unionWithNull(g0, g1) {
  22771. if (g0 === null && g1 === null) return null;
  22772. if (g1 === null) return g0;
  22773. if (g0 === null) return g1;
  22774. return g0.union(g1);
  22775. }
  22776. extract() {
  22777. if (hasInterface(arguments[0], Collection)) {
  22778. const geoms = arguments[0];
  22779. this._extracter = InputExtracter.extract(geoms);
  22780. } else if (arguments[0] instanceof Geometry) {
  22781. const geom = arguments[0];
  22782. this._extracter = InputExtracter.extract(geom);
  22783. }
  22784. }
  22785. union() {
  22786. if (this._geomFact === null) this._geomFact = this._extracter.getFactory();
  22787. if (this._geomFact === null) return null;
  22788. if (this._extracter.isEmpty()) return this._geomFact.createEmpty(this._extracter.getDimension());
  22789. const points = this._extracter.getExtract(0);
  22790. const lines = this._extracter.getExtract(1);
  22791. const polygons = this._extracter.getExtract(2);
  22792. let unionPoints = null;
  22793. if (points.size() > 0) {
  22794. const ptGeom = this._geomFact.buildGeometry(points);
  22795. unionPoints = this.unionNoOpt(ptGeom);
  22796. }
  22797. let unionLines = null;
  22798. if (lines.size() > 0) {
  22799. const lineGeom = this._geomFact.buildGeometry(lines);
  22800. unionLines = this.unionNoOpt(lineGeom);
  22801. }
  22802. let unionPolygons = null;
  22803. if (polygons.size() > 0) unionPolygons = CascadedPolygonUnion.union(polygons);
  22804. const unionLA = this.unionWithNull(unionLines, unionPolygons);
  22805. let union = null;
  22806. if (unionPoints === null) union = unionLA;else if (unionLA === null) union = unionPoints;else union = PointGeometryUnion.union(unionPoints, unionLA);
  22807. if (union === null) return this._geomFact.createGeometryCollection();
  22808. return union;
  22809. }
  22810. }
  22811. var union = /*#__PURE__*/Object.freeze({
  22812. __proto__: null,
  22813. UnaryUnionOp: UnaryUnionOp
  22814. });
  22815. var valid = /*#__PURE__*/Object.freeze({
  22816. __proto__: null,
  22817. IsValidOp: IsValidOp,
  22818. ConsistentAreaTester: ConsistentAreaTester
  22819. });
  22820. var operation = /*#__PURE__*/Object.freeze({
  22821. __proto__: null,
  22822. BoundaryOp: BoundaryOp,
  22823. IsSimpleOp: IsSimpleOp,
  22824. buffer: buffer,
  22825. distance: distance,
  22826. linemerge: linemerge,
  22827. overlay: overlay,
  22828. polygonize: polygonize,
  22829. relate: relate,
  22830. union: union,
  22831. valid: valid
  22832. });
  22833. class CommonBitsOp {
  22834. constructor() {
  22835. CommonBitsOp.constructor_.apply(this, arguments);
  22836. }
  22837. static constructor_() {
  22838. this._returnToOriginalPrecision = true;
  22839. this._cbr = null;
  22840. if (arguments.length === 0) {
  22841. CommonBitsOp.constructor_.call(this, true);
  22842. } else if (arguments.length === 1) {
  22843. const returnToOriginalPrecision = arguments[0];
  22844. this._returnToOriginalPrecision = returnToOriginalPrecision;
  22845. }
  22846. }
  22847. computeResultPrecision(result) {
  22848. if (this._returnToOriginalPrecision) this._cbr.addCommonBits(result);
  22849. return result;
  22850. }
  22851. union(geom0, geom1) {
  22852. const geom = this.removeCommonBits(geom0, geom1);
  22853. return this.computeResultPrecision(geom[0].union(geom[1]));
  22854. }
  22855. intersection(geom0, geom1) {
  22856. const geom = this.removeCommonBits(geom0, geom1);
  22857. return this.computeResultPrecision(geom[0].intersection(geom[1]));
  22858. }
  22859. removeCommonBits() {
  22860. if (arguments.length === 1) {
  22861. const geom0 = arguments[0];
  22862. this._cbr = new CommonBitsRemover();
  22863. this._cbr.add(geom0);
  22864. const geom = this._cbr.removeCommonBits(geom0.copy());
  22865. return geom;
  22866. } else if (arguments.length === 2) {
  22867. const geom0 = arguments[0],
  22868. geom1 = arguments[1];
  22869. this._cbr = new CommonBitsRemover();
  22870. this._cbr.add(geom0);
  22871. this._cbr.add(geom1);
  22872. const geom = new Array(2).fill(null);
  22873. geom[0] = this._cbr.removeCommonBits(geom0.copy());
  22874. geom[1] = this._cbr.removeCommonBits(geom1.copy());
  22875. return geom;
  22876. }
  22877. }
  22878. buffer(geom0, distance) {
  22879. const geom = this.removeCommonBits(geom0);
  22880. return this.computeResultPrecision(geom.buffer(distance));
  22881. }
  22882. symDifference(geom0, geom1) {
  22883. const geom = this.removeCommonBits(geom0, geom1);
  22884. return this.computeResultPrecision(geom[0].symDifference(geom[1]));
  22885. }
  22886. difference(geom0, geom1) {
  22887. const geom = this.removeCommonBits(geom0, geom1);
  22888. return this.computeResultPrecision(geom[0].difference(geom[1]));
  22889. }
  22890. }
  22891. class EnhancedPrecisionOp {
  22892. static union(geom0, geom1) {
  22893. let originalEx = null;
  22894. try {
  22895. const result = geom0.union(geom1);
  22896. return result;
  22897. } catch (ex) {
  22898. if (ex instanceof RuntimeException) originalEx = ex;else throw ex;
  22899. } finally {}
  22900. try {
  22901. const cbo = new CommonBitsOp(true);
  22902. const resultEP = cbo.union(geom0, geom1);
  22903. if (!resultEP.isValid()) throw originalEx;
  22904. return resultEP;
  22905. } catch (ex2) {
  22906. if (ex2 instanceof RuntimeException) throw originalEx;else throw ex2;
  22907. } finally {}
  22908. }
  22909. static intersection(geom0, geom1) {
  22910. let originalEx = null;
  22911. try {
  22912. const result = geom0.intersection(geom1);
  22913. return result;
  22914. } catch (ex) {
  22915. if (ex instanceof RuntimeException) originalEx = ex;else throw ex;
  22916. } finally {}
  22917. try {
  22918. const cbo = new CommonBitsOp(true);
  22919. const resultEP = cbo.intersection(geom0, geom1);
  22920. if (!resultEP.isValid()) throw originalEx;
  22921. return resultEP;
  22922. } catch (ex2) {
  22923. if (ex2 instanceof RuntimeException) throw originalEx;else throw ex2;
  22924. } finally {}
  22925. }
  22926. static buffer(geom, distance) {
  22927. let originalEx = null;
  22928. try {
  22929. const result = geom.buffer(distance);
  22930. return result;
  22931. } catch (ex) {
  22932. if (ex instanceof RuntimeException) originalEx = ex;else throw ex;
  22933. } finally {}
  22934. try {
  22935. const cbo = new CommonBitsOp(true);
  22936. const resultEP = cbo.buffer(geom, distance);
  22937. if (!resultEP.isValid()) throw originalEx;
  22938. return resultEP;
  22939. } catch (ex2) {
  22940. if (ex2 instanceof RuntimeException) throw originalEx;else throw ex2;
  22941. } finally {}
  22942. }
  22943. static symDifference(geom0, geom1) {
  22944. let originalEx = null;
  22945. try {
  22946. const result = geom0.symDifference(geom1);
  22947. return result;
  22948. } catch (ex) {
  22949. if (ex instanceof RuntimeException) originalEx = ex;else throw ex;
  22950. } finally {}
  22951. try {
  22952. const cbo = new CommonBitsOp(true);
  22953. const resultEP = cbo.symDifference(geom0, geom1);
  22954. if (!resultEP.isValid()) throw originalEx;
  22955. return resultEP;
  22956. } catch (ex2) {
  22957. if (ex2 instanceof RuntimeException) throw originalEx;else throw ex2;
  22958. } finally {}
  22959. }
  22960. static difference(geom0, geom1) {
  22961. let originalEx = null;
  22962. try {
  22963. const result = geom0.difference(geom1);
  22964. return result;
  22965. } catch (ex) {
  22966. if (ex instanceof RuntimeException) originalEx = ex;else throw ex;
  22967. } finally {}
  22968. try {
  22969. const cbo = new CommonBitsOp(true);
  22970. const resultEP = cbo.difference(geom0, geom1);
  22971. if (!resultEP.isValid()) throw originalEx;
  22972. return resultEP;
  22973. } catch (ex2) {
  22974. if (ex2 instanceof RuntimeException) throw originalEx;else throw ex2;
  22975. } finally {}
  22976. }
  22977. }
  22978. class PrecisionReducerCoordinateOperation extends GeometryEditor.CoordinateOperation {
  22979. constructor() {
  22980. super();
  22981. PrecisionReducerCoordinateOperation.constructor_.apply(this, arguments);
  22982. }
  22983. static constructor_() {
  22984. this._targetPM = null;
  22985. this._removeCollapsed = true;
  22986. const targetPM = arguments[0],
  22987. removeCollapsed = arguments[1];
  22988. this._targetPM = targetPM;
  22989. this._removeCollapsed = removeCollapsed;
  22990. }
  22991. edit() {
  22992. if (arguments.length === 2 && arguments[1] instanceof Geometry && arguments[0] instanceof Array) {
  22993. const coordinates = arguments[0],
  22994. geom = arguments[1];
  22995. if (coordinates.length === 0) return null;
  22996. const reducedCoords = new Array(coordinates.length).fill(null);
  22997. for (let i = 0; i < coordinates.length; i++) {
  22998. const coord = new Coordinate(coordinates[i]);
  22999. this._targetPM.makePrecise(coord);
  23000. reducedCoords[i] = coord;
  23001. }
  23002. const noRepeatedCoordList = new CoordinateList(reducedCoords, false);
  23003. const noRepeatedCoords = noRepeatedCoordList.toCoordinateArray();
  23004. let minLength = 0;
  23005. if (geom instanceof LineString) minLength = 2;
  23006. if (geom instanceof LinearRing) minLength = 4;
  23007. let collapsedCoords = reducedCoords;
  23008. if (this._removeCollapsed) collapsedCoords = null;
  23009. if (noRepeatedCoords.length < minLength) return collapsedCoords;
  23010. return noRepeatedCoords;
  23011. } else {
  23012. return super.edit.apply(this, arguments);
  23013. }
  23014. }
  23015. }
  23016. class GeometryPrecisionReducer {
  23017. constructor() {
  23018. GeometryPrecisionReducer.constructor_.apply(this, arguments);
  23019. }
  23020. static constructor_() {
  23021. this._targetPM = null;
  23022. this._removeCollapsed = true;
  23023. this._changePrecisionModel = false;
  23024. this._isPointwise = false;
  23025. const pm = arguments[0];
  23026. this._targetPM = pm;
  23027. }
  23028. static reduce(g, precModel) {
  23029. const reducer = new GeometryPrecisionReducer(precModel);
  23030. return reducer.reduce(g);
  23031. }
  23032. static reducePointwise(g, precModel) {
  23033. const reducer = new GeometryPrecisionReducer(precModel);
  23034. reducer.setPointwise(true);
  23035. return reducer.reduce(g);
  23036. }
  23037. fixPolygonalTopology(geom) {
  23038. let geomToBuffer = geom;
  23039. if (!this._changePrecisionModel) geomToBuffer = this.changePM(geom, this._targetPM);
  23040. const bufGeom = BufferOp.bufferOp(geomToBuffer, 0);
  23041. return bufGeom;
  23042. }
  23043. reducePointwise(geom) {
  23044. let geomEdit = null;
  23045. if (this._changePrecisionModel) {
  23046. const newFactory = this.createFactory(geom.getFactory(), this._targetPM);
  23047. geomEdit = new GeometryEditor(newFactory);
  23048. } else {
  23049. geomEdit = new GeometryEditor();
  23050. }
  23051. let finalRemoveCollapsed = this._removeCollapsed;
  23052. if (geom.getDimension() >= 2) finalRemoveCollapsed = true;
  23053. const reduceGeom = geomEdit.edit(geom, new PrecisionReducerCoordinateOperation(this._targetPM, finalRemoveCollapsed));
  23054. return reduceGeom;
  23055. }
  23056. changePM(geom, newPM) {
  23057. const geomEditor = this.createEditor(geom.getFactory(), newPM);
  23058. return geomEditor.edit(geom, new GeometryEditor.NoOpGeometryOperation());
  23059. }
  23060. setRemoveCollapsedComponents(removeCollapsed) {
  23061. this._removeCollapsed = removeCollapsed;
  23062. }
  23063. createFactory(inputFactory, pm) {
  23064. const newFactory = new GeometryFactory(pm, inputFactory.getSRID(), inputFactory.getCoordinateSequenceFactory());
  23065. return newFactory;
  23066. }
  23067. setChangePrecisionModel(changePrecisionModel) {
  23068. this._changePrecisionModel = changePrecisionModel;
  23069. }
  23070. reduce(geom) {
  23071. const reducePW = this.reducePointwise(geom);
  23072. if (this._isPointwise) return reducePW;
  23073. if (!hasInterface(reducePW, Polygonal)) return reducePW;
  23074. if (IsValidOp.isValid(reducePW)) return reducePW;
  23075. return this.fixPolygonalTopology(reducePW);
  23076. }
  23077. setPointwise(isPointwise) {
  23078. this._isPointwise = isPointwise;
  23079. }
  23080. createEditor(geomFactory, newPM) {
  23081. if (geomFactory.getPrecisionModel() === newPM) return new GeometryEditor();
  23082. const newFactory = this.createFactory(geomFactory, newPM);
  23083. const geomEdit = new GeometryEditor(newFactory);
  23084. return geomEdit;
  23085. }
  23086. }
  23087. class FacetSequence {
  23088. constructor() {
  23089. FacetSequence.constructor_.apply(this, arguments);
  23090. }
  23091. static constructor_() {
  23092. this._geom = null;
  23093. this._pts = null;
  23094. this._start = null;
  23095. this._end = null;
  23096. if (arguments.length === 2) {
  23097. const pts = arguments[0],
  23098. start = arguments[1];
  23099. this._pts = pts;
  23100. this._start = start;
  23101. this._end = start + 1;
  23102. } else if (arguments.length === 3) {
  23103. const pts = arguments[0],
  23104. start = arguments[1],
  23105. end = arguments[2];
  23106. this._pts = pts;
  23107. this._start = start;
  23108. this._end = end;
  23109. } else if (arguments.length === 4) {
  23110. const geom = arguments[0],
  23111. pts = arguments[1],
  23112. start = arguments[2],
  23113. end = arguments[3];
  23114. this._geom = geom;
  23115. this._pts = pts;
  23116. this._start = start;
  23117. this._end = end;
  23118. }
  23119. }
  23120. computeDistanceLineLine(facetSeq, locs) {
  23121. let minDistance = Double.MAX_VALUE;
  23122. for (let i = this._start; i < this._end - 1; i++) {
  23123. const p0 = this._pts.getCoordinate(i);
  23124. const p1 = this._pts.getCoordinate(i + 1);
  23125. for (let j = facetSeq._start; j < facetSeq._end - 1; j++) {
  23126. const q0 = facetSeq._pts.getCoordinate(j);
  23127. const q1 = facetSeq._pts.getCoordinate(j + 1);
  23128. const dist = Distance.segmentToSegment(p0, p1, q0, q1);
  23129. if (dist < minDistance) {
  23130. minDistance = dist;
  23131. if (locs !== null) this.updateNearestLocationsLineLine(i, p0, p1, facetSeq, j, q0, q1, locs);
  23132. if (minDistance <= 0.0) return minDistance;
  23133. }
  23134. }
  23135. }
  23136. return minDistance;
  23137. }
  23138. updateNearestLocationsPointLine(pt, facetSeq, i, q0, q1, locs) {
  23139. locs[0] = new GeometryLocation(this._geom, this._start, new Coordinate(pt));
  23140. const seg = new LineSegment(q0, q1);
  23141. const segClosestPoint = seg.closestPoint(pt);
  23142. locs[1] = new GeometryLocation(facetSeq._geom, i, new Coordinate(segClosestPoint));
  23143. }
  23144. size() {
  23145. return this._end - this._start;
  23146. }
  23147. getCoordinate(index) {
  23148. return this._pts.getCoordinate(this._start + index);
  23149. }
  23150. nearestLocations(facetSeq) {
  23151. const isPoint = this.isPoint();
  23152. const isPointOther = facetSeq.isPoint();
  23153. const locs = new Array(2).fill(null);
  23154. if (isPoint && isPointOther) {
  23155. const pt = this._pts.getCoordinate(this._start);
  23156. const seqPt = facetSeq._pts.getCoordinate(facetSeq._start);
  23157. locs[0] = new GeometryLocation(this._geom, this._start, new Coordinate(pt));
  23158. locs[1] = new GeometryLocation(facetSeq._geom, facetSeq._start, new Coordinate(seqPt));
  23159. } else if (isPoint) {
  23160. const pt = this._pts.getCoordinate(this._start);
  23161. this.computeDistancePointLine(pt, facetSeq, locs);
  23162. } else if (isPointOther) {
  23163. const seqPt = facetSeq._pts.getCoordinate(facetSeq._start);
  23164. this.computeDistancePointLine(seqPt, this, locs);
  23165. const tmp = locs[0];
  23166. locs[0] = locs[1];
  23167. locs[1] = tmp;
  23168. } else {
  23169. this.computeDistanceLineLine(facetSeq, locs);
  23170. }
  23171. return locs;
  23172. }
  23173. getEnvelope() {
  23174. const env = new Envelope();
  23175. for (let i = this._start; i < this._end; i++) env.expandToInclude(this._pts.getX(i), this._pts.getY(i));
  23176. return env;
  23177. }
  23178. updateNearestLocationsLineLine(i, p0, p1, facetSeq, j, q0, q1, locs) {
  23179. const seg0 = new LineSegment(p0, p1);
  23180. const seg1 = new LineSegment(q0, q1);
  23181. const closestPt = seg0.closestPoints(seg1);
  23182. locs[0] = new GeometryLocation(this._geom, i, new Coordinate(closestPt[0]));
  23183. locs[1] = new GeometryLocation(facetSeq._geom, j, new Coordinate(closestPt[1]));
  23184. }
  23185. toString() {
  23186. const buf = new StringBuffer();
  23187. buf.append('LINESTRING ( ');
  23188. const p = new Coordinate();
  23189. for (let i = this._start; i < this._end; i++) {
  23190. if (i > this._start) buf.append(', ');
  23191. this._pts.getCoordinate(i, p);
  23192. buf.append(p.x + ' ' + p.y);
  23193. }
  23194. buf.append(' )');
  23195. return buf.toString();
  23196. }
  23197. computeDistancePointLine(pt, facetSeq, locs) {
  23198. let minDistance = Double.MAX_VALUE;
  23199. for (let i = facetSeq._start; i < facetSeq._end - 1; i++) {
  23200. const q0 = facetSeq._pts.getCoordinate(i);
  23201. const q1 = facetSeq._pts.getCoordinate(i + 1);
  23202. const dist = Distance.pointToSegment(pt, q0, q1);
  23203. if (dist < minDistance) {
  23204. minDistance = dist;
  23205. if (locs !== null) this.updateNearestLocationsPointLine(pt, facetSeq, i, q0, q1, locs);
  23206. if (minDistance <= 0.0) return minDistance;
  23207. }
  23208. }
  23209. return minDistance;
  23210. }
  23211. isPoint() {
  23212. return this._end - this._start === 1;
  23213. }
  23214. distance(facetSeq) {
  23215. const isPoint = this.isPoint();
  23216. const isPointOther = facetSeq.isPoint();
  23217. let distance = null;
  23218. if (isPoint && isPointOther) {
  23219. const pt = this._pts.getCoordinate(this._start);
  23220. const seqPt = facetSeq._pts.getCoordinate(facetSeq._start);
  23221. distance = pt.distance(seqPt);
  23222. } else if (isPoint) {
  23223. const pt = this._pts.getCoordinate(this._start);
  23224. distance = this.computeDistancePointLine(pt, facetSeq, null);
  23225. } else if (isPointOther) {
  23226. const seqPt = facetSeq._pts.getCoordinate(facetSeq._start);
  23227. distance = this.computeDistancePointLine(seqPt, this, null);
  23228. } else {
  23229. distance = this.computeDistanceLineLine(facetSeq, null);
  23230. }
  23231. return distance;
  23232. }
  23233. }
  23234. class FacetSequenceTreeBuilder {
  23235. static addFacetSequences(geom, pts, sections) {
  23236. let i = 0;
  23237. const size = pts.size();
  23238. while (i <= size - 1) {
  23239. let end = i + FacetSequenceTreeBuilder.FACET_SEQUENCE_SIZE + 1;
  23240. if (end >= size - 1) end = size;
  23241. const sect = new FacetSequence(geom, pts, i, end);
  23242. sections.add(sect);
  23243. i = i + FacetSequenceTreeBuilder.FACET_SEQUENCE_SIZE;
  23244. }
  23245. }
  23246. static computeFacetSequences(g) {
  23247. const sections = new ArrayList();
  23248. g.apply(new class {
  23249. get interfaces_() {
  23250. return [GeometryComponentFilter];
  23251. }
  23252. filter(geom) {
  23253. let seq = null;
  23254. if (geom instanceof LineString) {
  23255. seq = geom.getCoordinateSequence();
  23256. FacetSequenceTreeBuilder.addFacetSequences(geom, seq, sections);
  23257. } else if (geom instanceof Point) {
  23258. seq = geom.getCoordinateSequence();
  23259. FacetSequenceTreeBuilder.addFacetSequences(geom, seq, sections);
  23260. }
  23261. }
  23262. }());
  23263. return sections;
  23264. }
  23265. static build(g) {
  23266. const tree = new STRtree(FacetSequenceTreeBuilder.STR_TREE_NODE_CAPACITY);
  23267. const sections = FacetSequenceTreeBuilder.computeFacetSequences(g);
  23268. for (let i = sections.iterator(); i.hasNext();) {
  23269. const section = i.next();
  23270. tree.insert(section.getEnvelope(), section);
  23271. }
  23272. tree.build();
  23273. return tree;
  23274. }
  23275. }
  23276. FacetSequenceTreeBuilder.FACET_SEQUENCE_SIZE = 6;
  23277. FacetSequenceTreeBuilder.STR_TREE_NODE_CAPACITY = 4;
  23278. class MinimumClearance {
  23279. constructor() {
  23280. MinimumClearance.constructor_.apply(this, arguments);
  23281. }
  23282. static constructor_() {
  23283. this._inputGeom = null;
  23284. this._minClearance = null;
  23285. this._minClearancePts = null;
  23286. const geom = arguments[0];
  23287. this._inputGeom = geom;
  23288. }
  23289. static getLine(g) {
  23290. const rp = new MinimumClearance(g);
  23291. return rp.getLine();
  23292. }
  23293. static getDistance(g) {
  23294. const rp = new MinimumClearance(g);
  23295. return rp.getDistance();
  23296. }
  23297. getLine() {
  23298. this.compute();
  23299. if (this._minClearancePts === null || this._minClearancePts[0] === null) return this._inputGeom.getFactory().createLineString();
  23300. return this._inputGeom.getFactory().createLineString(this._minClearancePts);
  23301. }
  23302. compute() {
  23303. if (this._minClearancePts !== null) return null;
  23304. this._minClearancePts = new Array(2).fill(null);
  23305. this._minClearance = Double.MAX_VALUE;
  23306. if (this._inputGeom.isEmpty()) return null;
  23307. const geomTree = FacetSequenceTreeBuilder.build(this._inputGeom);
  23308. const nearest = geomTree.nearestNeighbour(new MinClearanceDistance());
  23309. const mcd = new MinClearanceDistance();
  23310. this._minClearance = mcd.distance(nearest[0], nearest[1]);
  23311. this._minClearancePts = mcd.getCoordinates();
  23312. }
  23313. getDistance() {
  23314. this.compute();
  23315. return this._minClearance;
  23316. }
  23317. }
  23318. class MinClearanceDistance {
  23319. constructor() {
  23320. MinClearanceDistance.constructor_.apply(this, arguments);
  23321. }
  23322. static constructor_() {
  23323. this._minDist = Double.MAX_VALUE;
  23324. this._minPts = new Array(2).fill(null);
  23325. }
  23326. vertexDistance(fs1, fs2) {
  23327. for (let i1 = 0; i1 < fs1.size(); i1++) for (let i2 = 0; i2 < fs2.size(); i2++) {
  23328. const p1 = fs1.getCoordinate(i1);
  23329. const p2 = fs2.getCoordinate(i2);
  23330. if (!p1.equals2D(p2)) {
  23331. const d = p1.distance(p2);
  23332. if (d < this._minDist) {
  23333. this._minDist = d;
  23334. this._minPts[0] = p1;
  23335. this._minPts[1] = p2;
  23336. if (d === 0.0) return d;
  23337. }
  23338. }
  23339. }
  23340. return this._minDist;
  23341. }
  23342. getCoordinates() {
  23343. return this._minPts;
  23344. }
  23345. segmentDistance(fs1, fs2) {
  23346. for (let i1 = 0; i1 < fs1.size(); i1++) for (let i2 = 1; i2 < fs2.size(); i2++) {
  23347. const p = fs1.getCoordinate(i1);
  23348. const seg0 = fs2.getCoordinate(i2 - 1);
  23349. const seg1 = fs2.getCoordinate(i2);
  23350. if (!(p.equals2D(seg0) || p.equals2D(seg1))) {
  23351. const d = Distance.pointToSegment(p, seg0, seg1);
  23352. if (d < this._minDist) {
  23353. this._minDist = d;
  23354. this.updatePts(p, seg0, seg1);
  23355. if (d === 0.0) return d;
  23356. }
  23357. }
  23358. }
  23359. return this._minDist;
  23360. }
  23361. distance() {
  23362. if (arguments[0] instanceof ItemBoundable && arguments[1] instanceof ItemBoundable) {
  23363. const b1 = arguments[0],
  23364. b2 = arguments[1];
  23365. const fs1 = b1.getItem();
  23366. const fs2 = b2.getItem();
  23367. this._minDist = Double.MAX_VALUE;
  23368. return this.distance(fs1, fs2);
  23369. } else if (arguments[0] instanceof FacetSequence && arguments[1] instanceof FacetSequence) {
  23370. const fs1 = arguments[0],
  23371. fs2 = arguments[1];
  23372. this.vertexDistance(fs1, fs2);
  23373. if (fs1.size() === 1 && fs2.size() === 1) return this._minDist;
  23374. if (this._minDist <= 0.0) return this._minDist;
  23375. this.segmentDistance(fs1, fs2);
  23376. if (this._minDist <= 0.0) return this._minDist;
  23377. this.segmentDistance(fs2, fs1);
  23378. return this._minDist;
  23379. }
  23380. }
  23381. updatePts(p, seg0, seg1) {
  23382. this._minPts[0] = p;
  23383. const seg = new LineSegment(seg0, seg1);
  23384. this._minPts[1] = new Coordinate(seg.closestPoint(p));
  23385. }
  23386. get interfaces_() {
  23387. return [ItemDistance];
  23388. }
  23389. }
  23390. MinimumClearance.MinClearanceDistance = MinClearanceDistance;
  23391. class SimpleMinimumClearance {
  23392. constructor() {
  23393. SimpleMinimumClearance.constructor_.apply(this, arguments);
  23394. }
  23395. static constructor_() {
  23396. this._inputGeom = null;
  23397. this._minClearance = null;
  23398. this._minClearancePts = null;
  23399. const geom = arguments[0];
  23400. this._inputGeom = geom;
  23401. }
  23402. static getLine(g) {
  23403. const rp = new SimpleMinimumClearance(g);
  23404. return rp.getLine();
  23405. }
  23406. static getDistance(g) {
  23407. const rp = new SimpleMinimumClearance(g);
  23408. return rp.getDistance();
  23409. }
  23410. getLine() {
  23411. this.compute();
  23412. return this._inputGeom.getFactory().createLineString(this._minClearancePts);
  23413. }
  23414. updateClearance() {
  23415. if (arguments.length === 3) {
  23416. const candidateValue = arguments[0],
  23417. p0 = arguments[1],
  23418. p1 = arguments[2];
  23419. if (candidateValue < this._minClearance) {
  23420. this._minClearance = candidateValue;
  23421. this._minClearancePts[0] = new Coordinate(p0);
  23422. this._minClearancePts[1] = new Coordinate(p1);
  23423. }
  23424. } else if (arguments.length === 4) {
  23425. const candidateValue = arguments[0],
  23426. p = arguments[1],
  23427. seg0 = arguments[2],
  23428. seg1 = arguments[3];
  23429. if (candidateValue < this._minClearance) {
  23430. this._minClearance = candidateValue;
  23431. this._minClearancePts[0] = new Coordinate(p);
  23432. const seg = new LineSegment(seg0, seg1);
  23433. this._minClearancePts[1] = new Coordinate(seg.closestPoint(p));
  23434. }
  23435. }
  23436. }
  23437. compute() {
  23438. if (this._minClearancePts !== null) return null;
  23439. this._minClearancePts = new Array(2).fill(null);
  23440. this._minClearance = Double.MAX_VALUE;
  23441. this._inputGeom.apply(new VertexCoordinateFilter(this));
  23442. }
  23443. getDistance() {
  23444. this.compute();
  23445. return this._minClearance;
  23446. }
  23447. }
  23448. class VertexCoordinateFilter {
  23449. constructor() {
  23450. VertexCoordinateFilter.constructor_.apply(this, arguments);
  23451. }
  23452. static constructor_() {
  23453. this.smc = null;
  23454. const smc = arguments[0];
  23455. this.smc = smc;
  23456. }
  23457. filter(coord) {
  23458. this.smc._inputGeom.apply(new ComputeMCCoordinateSequenceFilter(this.smc, coord));
  23459. }
  23460. get interfaces_() {
  23461. return [CoordinateFilter];
  23462. }
  23463. }
  23464. class ComputeMCCoordinateSequenceFilter {
  23465. constructor() {
  23466. ComputeMCCoordinateSequenceFilter.constructor_.apply(this, arguments);
  23467. }
  23468. static constructor_() {
  23469. this.smc = null;
  23470. this._queryPt = null;
  23471. const smc = arguments[0],
  23472. queryPt = arguments[1];
  23473. this.smc = smc;
  23474. this._queryPt = queryPt;
  23475. }
  23476. isGeometryChanged() {
  23477. return false;
  23478. }
  23479. checkVertexDistance(vertex) {
  23480. const vertexDist = vertex.distance(this._queryPt);
  23481. if (vertexDist > 0) this.smc.updateClearance(vertexDist, this._queryPt, vertex);
  23482. }
  23483. filter(seq, i) {
  23484. this.checkVertexDistance(seq.getCoordinate(i));
  23485. if (i > 0) this.checkSegmentDistance(seq.getCoordinate(i - 1), seq.getCoordinate(i));
  23486. }
  23487. checkSegmentDistance(seg0, seg1) {
  23488. if (this._queryPt.equals2D(seg0) || this._queryPt.equals2D(seg1)) return null;
  23489. const segDist = Distance.pointToSegment(this._queryPt, seg1, seg0);
  23490. if (segDist > 0) this.smc.updateClearance(segDist, this._queryPt, seg1, seg0);
  23491. }
  23492. isDone() {
  23493. return false;
  23494. }
  23495. get interfaces_() {
  23496. return [CoordinateSequenceFilter];
  23497. }
  23498. }
  23499. SimpleMinimumClearance.VertexCoordinateFilter = VertexCoordinateFilter;
  23500. SimpleMinimumClearance.ComputeMCCoordinateSequenceFilter = ComputeMCCoordinateSequenceFilter;
  23501. var precision = /*#__PURE__*/Object.freeze({
  23502. __proto__: null,
  23503. CommonBits: CommonBits,
  23504. CommonBitsOp: CommonBitsOp,
  23505. CommonBitsRemover: CommonBitsRemover,
  23506. EnhancedPrecisionOp: EnhancedPrecisionOp,
  23507. GeometryPrecisionReducer: GeometryPrecisionReducer,
  23508. MinimumClearance: MinimumClearance,
  23509. SimpleMinimumClearance: SimpleMinimumClearance
  23510. });
  23511. class DouglasPeuckerLineSimplifier {
  23512. constructor() {
  23513. DouglasPeuckerLineSimplifier.constructor_.apply(this, arguments);
  23514. }
  23515. static constructor_() {
  23516. this._pts = null;
  23517. this._usePt = null;
  23518. this._distanceTolerance = null;
  23519. this._seg = new LineSegment();
  23520. const pts = arguments[0];
  23521. this._pts = pts;
  23522. }
  23523. static simplify(pts, distanceTolerance) {
  23524. const simp = new DouglasPeuckerLineSimplifier(pts);
  23525. simp.setDistanceTolerance(distanceTolerance);
  23526. return simp.simplify();
  23527. }
  23528. simplifySection(i, j) {
  23529. if (i + 1 === j) return null;
  23530. this._seg.p0 = this._pts[i];
  23531. this._seg.p1 = this._pts[j];
  23532. let maxDistance = -1.0;
  23533. let maxIndex = i;
  23534. for (let k = i + 1; k < j; k++) {
  23535. const distance = this._seg.distance(this._pts[k]);
  23536. if (distance > maxDistance) {
  23537. maxDistance = distance;
  23538. maxIndex = k;
  23539. }
  23540. }
  23541. if (maxDistance <= this._distanceTolerance) {
  23542. for (let k = i + 1; k < j; k++) this._usePt[k] = false;
  23543. } else {
  23544. this.simplifySection(i, maxIndex);
  23545. this.simplifySection(maxIndex, j);
  23546. }
  23547. }
  23548. setDistanceTolerance(distanceTolerance) {
  23549. this._distanceTolerance = distanceTolerance;
  23550. }
  23551. simplify() {
  23552. this._usePt = new Array(this._pts.length).fill(null);
  23553. for (let i = 0; i < this._pts.length; i++) this._usePt[i] = true;
  23554. this.simplifySection(0, this._pts.length - 1);
  23555. const coordList = new CoordinateList();
  23556. for (let i = 0; i < this._pts.length; i++) if (this._usePt[i]) coordList.add(new Coordinate(this._pts[i]));
  23557. return coordList.toCoordinateArray();
  23558. }
  23559. }
  23560. class DouglasPeuckerSimplifier {
  23561. constructor() {
  23562. DouglasPeuckerSimplifier.constructor_.apply(this, arguments);
  23563. }
  23564. static constructor_() {
  23565. this._inputGeom = null;
  23566. this._distanceTolerance = null;
  23567. this._isEnsureValidTopology = true;
  23568. const inputGeom = arguments[0];
  23569. this._inputGeom = inputGeom;
  23570. }
  23571. static simplify(geom, distanceTolerance) {
  23572. const tss = new DouglasPeuckerSimplifier(geom);
  23573. tss.setDistanceTolerance(distanceTolerance);
  23574. return tss.getResultGeometry();
  23575. }
  23576. setEnsureValid(isEnsureValidTopology) {
  23577. this._isEnsureValidTopology = isEnsureValidTopology;
  23578. }
  23579. getResultGeometry() {
  23580. if (this._inputGeom.isEmpty()) return this._inputGeom.copy();
  23581. return new DPTransformer(this._isEnsureValidTopology, this._distanceTolerance).transform(this._inputGeom);
  23582. }
  23583. setDistanceTolerance(distanceTolerance) {
  23584. if (distanceTolerance < 0.0) throw new IllegalArgumentException('Tolerance must be non-negative');
  23585. this._distanceTolerance = distanceTolerance;
  23586. }
  23587. }
  23588. class DPTransformer extends GeometryTransformer {
  23589. constructor() {
  23590. super();
  23591. DPTransformer.constructor_.apply(this, arguments);
  23592. }
  23593. static constructor_() {
  23594. this._isEnsureValidTopology = true;
  23595. this._distanceTolerance = null;
  23596. const isEnsureValidTopology = arguments[0],
  23597. distanceTolerance = arguments[1];
  23598. this._isEnsureValidTopology = isEnsureValidTopology;
  23599. this._distanceTolerance = distanceTolerance;
  23600. }
  23601. transformPolygon(geom, parent) {
  23602. if (geom.isEmpty()) return null;
  23603. const rawGeom = super.transformPolygon.call(this, geom, parent);
  23604. if (parent instanceof MultiPolygon) return rawGeom;
  23605. return this.createValidArea(rawGeom);
  23606. }
  23607. createValidArea(rawAreaGeom) {
  23608. if (this._isEnsureValidTopology) return rawAreaGeom.buffer(0.0);
  23609. return rawAreaGeom;
  23610. }
  23611. transformCoordinates(coords, parent) {
  23612. const inputPts = coords.toCoordinateArray();
  23613. let newPts = null;
  23614. if (inputPts.length === 0) newPts = new Array(0).fill(null);else newPts = DouglasPeuckerLineSimplifier.simplify(inputPts, this._distanceTolerance);
  23615. return this._factory.getCoordinateSequenceFactory().create(newPts);
  23616. }
  23617. transformMultiPolygon(geom, parent) {
  23618. const rawGeom = super.transformMultiPolygon.call(this, geom, parent);
  23619. return this.createValidArea(rawGeom);
  23620. }
  23621. transformLinearRing(geom, parent) {
  23622. const removeDegenerateRings = parent instanceof Polygon;
  23623. const simpResult = super.transformLinearRing.call(this, geom, parent);
  23624. if (removeDegenerateRings && !(simpResult instanceof LinearRing)) return null;
  23625. return simpResult;
  23626. }
  23627. }
  23628. DouglasPeuckerSimplifier.DPTransformer = DPTransformer;
  23629. class TaggedLineSegment extends LineSegment {
  23630. constructor() {
  23631. super();
  23632. TaggedLineSegment.constructor_.apply(this, arguments);
  23633. }
  23634. static constructor_() {
  23635. this._parent = null;
  23636. this._index = null;
  23637. if (arguments.length === 2) {
  23638. const p0 = arguments[0],
  23639. p1 = arguments[1];
  23640. TaggedLineSegment.constructor_.call(this, p0, p1, null, -1);
  23641. } else if (arguments.length === 4) {
  23642. const p0 = arguments[0],
  23643. p1 = arguments[1],
  23644. parent = arguments[2],
  23645. index = arguments[3];
  23646. LineSegment.constructor_.call(this, p0, p1);
  23647. this._parent = parent;
  23648. this._index = index;
  23649. }
  23650. }
  23651. getIndex() {
  23652. return this._index;
  23653. }
  23654. getParent() {
  23655. return this._parent;
  23656. }
  23657. }
  23658. class TaggedLineString {
  23659. constructor() {
  23660. TaggedLineString.constructor_.apply(this, arguments);
  23661. }
  23662. static constructor_() {
  23663. this._parentLine = null;
  23664. this._segs = null;
  23665. this._resultSegs = new ArrayList();
  23666. this._minimumSize = null;
  23667. if (arguments.length === 1) {
  23668. const parentLine = arguments[0];
  23669. TaggedLineString.constructor_.call(this, parentLine, 2);
  23670. } else if (arguments.length === 2) {
  23671. const parentLine = arguments[0],
  23672. minimumSize = arguments[1];
  23673. this._parentLine = parentLine;
  23674. this._minimumSize = minimumSize;
  23675. this.init();
  23676. }
  23677. }
  23678. static extractCoordinates(segs) {
  23679. const pts = new Array(segs.size() + 1).fill(null);
  23680. let seg = null;
  23681. for (let i = 0; i < segs.size(); i++) {
  23682. seg = segs.get(i);
  23683. pts[i] = seg.p0;
  23684. }
  23685. pts[pts.length - 1] = seg.p1;
  23686. return pts;
  23687. }
  23688. addToResult(seg) {
  23689. this._resultSegs.add(seg);
  23690. }
  23691. asLineString() {
  23692. return this._parentLine.getFactory().createLineString(TaggedLineString.extractCoordinates(this._resultSegs));
  23693. }
  23694. getResultSize() {
  23695. const resultSegsSize = this._resultSegs.size();
  23696. return resultSegsSize === 0 ? 0 : resultSegsSize + 1;
  23697. }
  23698. getParent() {
  23699. return this._parentLine;
  23700. }
  23701. getSegment(i) {
  23702. return this._segs[i];
  23703. }
  23704. getParentCoordinates() {
  23705. return this._parentLine.getCoordinates();
  23706. }
  23707. getMinimumSize() {
  23708. return this._minimumSize;
  23709. }
  23710. asLinearRing() {
  23711. return this._parentLine.getFactory().createLinearRing(TaggedLineString.extractCoordinates(this._resultSegs));
  23712. }
  23713. getSegments() {
  23714. return this._segs;
  23715. }
  23716. init() {
  23717. const pts = this._parentLine.getCoordinates();
  23718. this._segs = new Array(pts.length - 1).fill(null);
  23719. for (let i = 0; i < pts.length - 1; i++) {
  23720. const seg = new TaggedLineSegment(pts[i], pts[i + 1], this._parentLine, i);
  23721. this._segs[i] = seg;
  23722. }
  23723. }
  23724. getResultCoordinates() {
  23725. return TaggedLineString.extractCoordinates(this._resultSegs);
  23726. }
  23727. }
  23728. class LineSegmentIndex {
  23729. constructor() {
  23730. LineSegmentIndex.constructor_.apply(this, arguments);
  23731. }
  23732. static constructor_() {
  23733. this._index = new Quadtree();
  23734. }
  23735. remove(seg) {
  23736. this._index.remove(new Envelope(seg.p0, seg.p1), seg);
  23737. }
  23738. add() {
  23739. if (arguments[0] instanceof TaggedLineString) {
  23740. const line = arguments[0];
  23741. const segs = line.getSegments();
  23742. for (let i = 0; i < segs.length; i++) {
  23743. const seg = segs[i];
  23744. this.add(seg);
  23745. }
  23746. } else if (arguments[0] instanceof LineSegment) {
  23747. const seg = arguments[0];
  23748. this._index.insert(new Envelope(seg.p0, seg.p1), seg);
  23749. }
  23750. }
  23751. query(querySeg) {
  23752. const env = new Envelope(querySeg.p0, querySeg.p1);
  23753. const visitor = new LineSegmentVisitor(querySeg);
  23754. this._index.query(env, visitor);
  23755. const itemsFound = visitor.getItems();
  23756. return itemsFound;
  23757. }
  23758. }
  23759. class LineSegmentVisitor {
  23760. constructor() {
  23761. LineSegmentVisitor.constructor_.apply(this, arguments);
  23762. }
  23763. static constructor_() {
  23764. this._querySeg = null;
  23765. this._items = new ArrayList();
  23766. const querySeg = arguments[0];
  23767. this._querySeg = querySeg;
  23768. }
  23769. visitItem(item) {
  23770. const seg = item;
  23771. if (Envelope.intersects(seg.p0, seg.p1, this._querySeg.p0, this._querySeg.p1)) this._items.add(item);
  23772. }
  23773. getItems() {
  23774. return this._items;
  23775. }
  23776. get interfaces_() {
  23777. return [ItemVisitor];
  23778. }
  23779. }
  23780. class TaggedLineStringSimplifier {
  23781. constructor() {
  23782. TaggedLineStringSimplifier.constructor_.apply(this, arguments);
  23783. }
  23784. static constructor_() {
  23785. this._li = new RobustLineIntersector();
  23786. this._inputIndex = new LineSegmentIndex();
  23787. this._outputIndex = new LineSegmentIndex();
  23788. this._line = null;
  23789. this._linePts = null;
  23790. this._distanceTolerance = 0.0;
  23791. const inputIndex = arguments[0],
  23792. outputIndex = arguments[1];
  23793. this._inputIndex = inputIndex;
  23794. this._outputIndex = outputIndex;
  23795. }
  23796. static isInLineSection(line, sectionIndex, seg) {
  23797. if (seg.getParent() !== line.getParent()) return false;
  23798. const segIndex = seg.getIndex();
  23799. if (segIndex >= sectionIndex[0] && segIndex < sectionIndex[1]) return true;
  23800. return false;
  23801. }
  23802. flatten(start, end) {
  23803. const p0 = this._linePts[start];
  23804. const p1 = this._linePts[end];
  23805. const newSeg = new LineSegment(p0, p1);
  23806. this.remove(this._line, start, end);
  23807. this._outputIndex.add(newSeg);
  23808. return newSeg;
  23809. }
  23810. hasBadIntersection(parentLine, sectionIndex, candidateSeg) {
  23811. if (this.hasBadOutputIntersection(candidateSeg)) return true;
  23812. if (this.hasBadInputIntersection(parentLine, sectionIndex, candidateSeg)) return true;
  23813. return false;
  23814. }
  23815. setDistanceTolerance(distanceTolerance) {
  23816. this._distanceTolerance = distanceTolerance;
  23817. }
  23818. simplifySection(i, j, depth) {
  23819. depth += 1;
  23820. const sectionIndex = new Array(2).fill(null);
  23821. if (i + 1 === j) {
  23822. const newSeg = this._line.getSegment(i);
  23823. this._line.addToResult(newSeg);
  23824. return null;
  23825. }
  23826. let isValidToSimplify = true;
  23827. if (this._line.getResultSize() < this._line.getMinimumSize()) {
  23828. const worstCaseSize = depth + 1;
  23829. if (worstCaseSize < this._line.getMinimumSize()) isValidToSimplify = false;
  23830. }
  23831. const distance = new Array(1).fill(null);
  23832. const furthestPtIndex = this.findFurthestPoint(this._linePts, i, j, distance);
  23833. if (distance[0] > this._distanceTolerance) isValidToSimplify = false;
  23834. const candidateSeg = new LineSegment();
  23835. candidateSeg.p0 = this._linePts[i];
  23836. candidateSeg.p1 = this._linePts[j];
  23837. sectionIndex[0] = i;
  23838. sectionIndex[1] = j;
  23839. if (this.hasBadIntersection(this._line, sectionIndex, candidateSeg)) isValidToSimplify = false;
  23840. if (isValidToSimplify) {
  23841. const newSeg = this.flatten(i, j);
  23842. this._line.addToResult(newSeg);
  23843. return null;
  23844. }
  23845. this.simplifySection(i, furthestPtIndex, depth);
  23846. this.simplifySection(furthestPtIndex, j, depth);
  23847. }
  23848. hasBadOutputIntersection(candidateSeg) {
  23849. const querySegs = this._outputIndex.query(candidateSeg);
  23850. for (let i = querySegs.iterator(); i.hasNext();) {
  23851. const querySeg = i.next();
  23852. if (this.hasInteriorIntersection(querySeg, candidateSeg)) return true;
  23853. }
  23854. return false;
  23855. }
  23856. findFurthestPoint(pts, i, j, maxDistance) {
  23857. const seg = new LineSegment();
  23858. seg.p0 = pts[i];
  23859. seg.p1 = pts[j];
  23860. let maxDist = -1.0;
  23861. let maxIndex = i;
  23862. for (let k = i + 1; k < j; k++) {
  23863. const midPt = pts[k];
  23864. const distance = seg.distance(midPt);
  23865. if (distance > maxDist) {
  23866. maxDist = distance;
  23867. maxIndex = k;
  23868. }
  23869. }
  23870. maxDistance[0] = maxDist;
  23871. return maxIndex;
  23872. }
  23873. simplify(line) {
  23874. this._line = line;
  23875. this._linePts = line.getParentCoordinates();
  23876. this.simplifySection(0, this._linePts.length - 1, 0);
  23877. }
  23878. remove(line, start, end) {
  23879. for (let i = start; i < end; i++) {
  23880. const seg = line.getSegment(i);
  23881. this._inputIndex.remove(seg);
  23882. }
  23883. }
  23884. hasInteriorIntersection(seg0, seg1) {
  23885. this._li.computeIntersection(seg0.p0, seg0.p1, seg1.p0, seg1.p1);
  23886. return this._li.isInteriorIntersection();
  23887. }
  23888. hasBadInputIntersection(parentLine, sectionIndex, candidateSeg) {
  23889. const querySegs = this._inputIndex.query(candidateSeg);
  23890. for (let i = querySegs.iterator(); i.hasNext();) {
  23891. const querySeg = i.next();
  23892. if (this.hasInteriorIntersection(querySeg, candidateSeg)) {
  23893. if (TaggedLineStringSimplifier.isInLineSection(parentLine, sectionIndex, querySeg)) continue;
  23894. return true;
  23895. }
  23896. }
  23897. return false;
  23898. }
  23899. }
  23900. class TaggedLinesSimplifier {
  23901. constructor() {
  23902. TaggedLinesSimplifier.constructor_.apply(this, arguments);
  23903. }
  23904. static constructor_() {
  23905. this._inputIndex = new LineSegmentIndex();
  23906. this._outputIndex = new LineSegmentIndex();
  23907. this._distanceTolerance = 0.0;
  23908. }
  23909. setDistanceTolerance(distanceTolerance) {
  23910. this._distanceTolerance = distanceTolerance;
  23911. }
  23912. simplify(taggedLines) {
  23913. for (let i = taggedLines.iterator(); i.hasNext();) this._inputIndex.add(i.next());
  23914. for (let i = taggedLines.iterator(); i.hasNext();) {
  23915. const tlss = new TaggedLineStringSimplifier(this._inputIndex, this._outputIndex);
  23916. tlss.setDistanceTolerance(this._distanceTolerance);
  23917. tlss.simplify(i.next());
  23918. }
  23919. }
  23920. }
  23921. class TopologyPreservingSimplifier {
  23922. constructor() {
  23923. TopologyPreservingSimplifier.constructor_.apply(this, arguments);
  23924. }
  23925. static constructor_() {
  23926. this._inputGeom = null;
  23927. this._lineSimplifier = new TaggedLinesSimplifier();
  23928. this._linestringMap = null;
  23929. const inputGeom = arguments[0];
  23930. this._inputGeom = inputGeom;
  23931. }
  23932. static simplify(geom, distanceTolerance) {
  23933. const tss = new TopologyPreservingSimplifier(geom);
  23934. tss.setDistanceTolerance(distanceTolerance);
  23935. return tss.getResultGeometry();
  23936. }
  23937. getResultGeometry() {
  23938. if (this._inputGeom.isEmpty()) return this._inputGeom.copy();
  23939. this._linestringMap = new HashMap();
  23940. this._inputGeom.apply(new LineStringMapBuilderFilter(this));
  23941. this._lineSimplifier.simplify(this._linestringMap.values());
  23942. const result = new LineStringTransformer(this._linestringMap).transform(this._inputGeom);
  23943. return result;
  23944. }
  23945. setDistanceTolerance(distanceTolerance) {
  23946. if (distanceTolerance < 0.0) throw new IllegalArgumentException('Tolerance must be non-negative');
  23947. this._lineSimplifier.setDistanceTolerance(distanceTolerance);
  23948. }
  23949. }
  23950. class LineStringTransformer extends GeometryTransformer {
  23951. constructor() {
  23952. super();
  23953. LineStringTransformer.constructor_.apply(this, arguments);
  23954. }
  23955. static constructor_() {
  23956. this._linestringMap = null;
  23957. const linestringMap = arguments[0];
  23958. this._linestringMap = linestringMap;
  23959. }
  23960. transformCoordinates(coords, parent) {
  23961. if (coords.size() === 0) return null;
  23962. if (parent instanceof LineString) {
  23963. const taggedLine = this._linestringMap.get(parent);
  23964. return this.createCoordinateSequence(taggedLine.getResultCoordinates());
  23965. }
  23966. return super.transformCoordinates.call(this, coords, parent);
  23967. }
  23968. }
  23969. class LineStringMapBuilderFilter {
  23970. constructor() {
  23971. LineStringMapBuilderFilter.constructor_.apply(this, arguments);
  23972. }
  23973. static constructor_() {
  23974. this.tps = null;
  23975. const tps = arguments[0];
  23976. this.tps = tps;
  23977. }
  23978. filter(geom) {
  23979. if (geom instanceof LineString) {
  23980. const line = geom;
  23981. if (line.isEmpty()) return null;
  23982. const minSize = line.isClosed() ? 4 : 2;
  23983. const taggedLine = new TaggedLineString(line, minSize);
  23984. this.tps._linestringMap.put(line, taggedLine);
  23985. }
  23986. }
  23987. get interfaces_() {
  23988. return [GeometryComponentFilter];
  23989. }
  23990. }
  23991. TopologyPreservingSimplifier.LineStringTransformer = LineStringTransformer;
  23992. TopologyPreservingSimplifier.LineStringMapBuilderFilter = LineStringMapBuilderFilter;
  23993. class VWLineSimplifier {
  23994. constructor() {
  23995. VWLineSimplifier.constructor_.apply(this, arguments);
  23996. }
  23997. static constructor_() {
  23998. this._pts = null;
  23999. this._tolerance = null;
  24000. const pts = arguments[0],
  24001. distanceTolerance = arguments[1];
  24002. this._pts = pts;
  24003. this._tolerance = distanceTolerance * distanceTolerance;
  24004. }
  24005. static simplify(pts, distanceTolerance) {
  24006. const simp = new VWLineSimplifier(pts, distanceTolerance);
  24007. return simp.simplify();
  24008. }
  24009. simplifyVertex(vwLine) {
  24010. let curr = vwLine;
  24011. let minArea = curr.getArea();
  24012. let minVertex = null;
  24013. while (curr !== null) {
  24014. const area = curr.getArea();
  24015. if (area < minArea) {
  24016. minArea = area;
  24017. minVertex = curr;
  24018. }
  24019. curr = curr._next;
  24020. }
  24021. if (minVertex !== null && minArea < this._tolerance) minVertex.remove();
  24022. if (!vwLine.isLive()) return -1;
  24023. return minArea;
  24024. }
  24025. simplify() {
  24026. const vwLine = VWVertex.buildLine(this._pts);
  24027. let minArea = this._tolerance;
  24028. do minArea = this.simplifyVertex(vwLine); while (minArea < this._tolerance);
  24029. const simp = vwLine.getCoordinates();
  24030. if (simp.length < 2) return [simp[0], new Coordinate(simp[0])];
  24031. return simp;
  24032. }
  24033. }
  24034. class VWVertex {
  24035. constructor() {
  24036. VWVertex.constructor_.apply(this, arguments);
  24037. }
  24038. static constructor_() {
  24039. this._pt = null;
  24040. this._prev = null;
  24041. this._next = null;
  24042. this._area = VWVertex.MAX_AREA;
  24043. this._isLive = true;
  24044. const pt = arguments[0];
  24045. this._pt = pt;
  24046. }
  24047. static buildLine(pts) {
  24048. let first = null;
  24049. let prev = null;
  24050. for (let i = 0; i < pts.length; i++) {
  24051. const v = new VWVertex(pts[i]);
  24052. if (first === null) first = v;
  24053. v.setPrev(prev);
  24054. if (prev !== null) {
  24055. prev.setNext(v);
  24056. prev.updateArea();
  24057. }
  24058. prev = v;
  24059. }
  24060. return first;
  24061. }
  24062. getCoordinates() {
  24063. const coords = new CoordinateList();
  24064. let curr = this;
  24065. do {
  24066. coords.add(curr._pt, false);
  24067. curr = curr._next;
  24068. } while (curr !== null);
  24069. return coords.toCoordinateArray();
  24070. }
  24071. getArea() {
  24072. return this._area;
  24073. }
  24074. updateArea() {
  24075. if (this._prev === null || this._next === null) {
  24076. this._area = VWVertex.MAX_AREA;
  24077. return null;
  24078. }
  24079. this._area = Math.abs(Triangle.area(this._prev._pt, this._pt, this._next._pt));
  24080. }
  24081. remove() {
  24082. const tmpPrev = this._prev;
  24083. const tmpNext = this._next;
  24084. let result = null;
  24085. if (this._prev !== null) {
  24086. this._prev.setNext(tmpNext);
  24087. this._prev.updateArea();
  24088. result = this._prev;
  24089. }
  24090. if (this._next !== null) {
  24091. this._next.setPrev(tmpPrev);
  24092. this._next.updateArea();
  24093. if (result === null) result = this._next;
  24094. }
  24095. this._isLive = false;
  24096. return result;
  24097. }
  24098. isLive() {
  24099. return this._isLive;
  24100. }
  24101. setPrev(prev) {
  24102. this._prev = prev;
  24103. }
  24104. setNext(next) {
  24105. this._next = next;
  24106. }
  24107. }
  24108. VWVertex.MAX_AREA = Double.MAX_VALUE;
  24109. VWLineSimplifier.VWVertex = VWVertex;
  24110. class VWSimplifier {
  24111. constructor() {
  24112. VWSimplifier.constructor_.apply(this, arguments);
  24113. }
  24114. static constructor_() {
  24115. this._inputGeom = null;
  24116. this._distanceTolerance = null;
  24117. this._isEnsureValidTopology = true;
  24118. const inputGeom = arguments[0];
  24119. this._inputGeom = inputGeom;
  24120. }
  24121. static simplify(geom, distanceTolerance) {
  24122. const simp = new VWSimplifier(geom);
  24123. simp.setDistanceTolerance(distanceTolerance);
  24124. return simp.getResultGeometry();
  24125. }
  24126. setEnsureValid(isEnsureValidTopology) {
  24127. this._isEnsureValidTopology = isEnsureValidTopology;
  24128. }
  24129. getResultGeometry() {
  24130. if (this._inputGeom.isEmpty()) return this._inputGeom.copy();
  24131. return new VWTransformer(this._isEnsureValidTopology, this._distanceTolerance).transform(this._inputGeom);
  24132. }
  24133. setDistanceTolerance(distanceTolerance) {
  24134. if (distanceTolerance < 0.0) throw new IllegalArgumentException('Tolerance must be non-negative');
  24135. this._distanceTolerance = distanceTolerance;
  24136. }
  24137. }
  24138. class VWTransformer extends GeometryTransformer {
  24139. constructor() {
  24140. super();
  24141. VWTransformer.constructor_.apply(this, arguments);
  24142. }
  24143. static constructor_() {
  24144. this._isEnsureValidTopology = true;
  24145. this._distanceTolerance = null;
  24146. const isEnsureValidTopology = arguments[0],
  24147. distanceTolerance = arguments[1];
  24148. this._isEnsureValidTopology = isEnsureValidTopology;
  24149. this._distanceTolerance = distanceTolerance;
  24150. }
  24151. transformPolygon(geom, parent) {
  24152. if (geom.isEmpty()) return null;
  24153. const rawGeom = super.transformPolygon.call(this, geom, parent);
  24154. if (parent instanceof MultiPolygon) return rawGeom;
  24155. return this.createValidArea(rawGeom);
  24156. }
  24157. createValidArea(rawAreaGeom) {
  24158. if (this._isEnsureValidTopology) return rawAreaGeom.buffer(0.0);
  24159. return rawAreaGeom;
  24160. }
  24161. transformCoordinates(coords, parent) {
  24162. const inputPts = coords.toCoordinateArray();
  24163. let newPts = null;
  24164. if (inputPts.length === 0) newPts = new Array(0).fill(null);else newPts = VWLineSimplifier.simplify(inputPts, this._distanceTolerance);
  24165. return this._factory.getCoordinateSequenceFactory().create(newPts);
  24166. }
  24167. transformMultiPolygon(geom, parent) {
  24168. const rawGeom = super.transformMultiPolygon.call(this, geom, parent);
  24169. return this.createValidArea(rawGeom);
  24170. }
  24171. transformLinearRing(geom, parent) {
  24172. const removeDegenerateRings = parent instanceof Polygon;
  24173. const simpResult = super.transformLinearRing.call(this, geom, parent);
  24174. if (removeDegenerateRings && !(simpResult instanceof LinearRing)) return null;
  24175. return simpResult;
  24176. }
  24177. }
  24178. VWSimplifier.VWTransformer = VWTransformer;
  24179. var simplify = /*#__PURE__*/Object.freeze({
  24180. __proto__: null,
  24181. DouglasPeuckerSimplifier: DouglasPeuckerSimplifier,
  24182. TopologyPreservingSimplifier: TopologyPreservingSimplifier,
  24183. VWSimplifier: VWSimplifier
  24184. });
  24185. class SplitSegment {
  24186. constructor() {
  24187. SplitSegment.constructor_.apply(this, arguments);
  24188. }
  24189. static constructor_() {
  24190. this._seg = null;
  24191. this._segLen = null;
  24192. this._splitPt = null;
  24193. this._minimumLen = 0.0;
  24194. const seg = arguments[0];
  24195. this._seg = seg;
  24196. this._segLen = seg.getLength();
  24197. }
  24198. static pointAlongReverse(seg, segmentLengthFraction) {
  24199. const coord = new Coordinate();
  24200. coord.x = seg.p1.x - segmentLengthFraction * (seg.p1.x - seg.p0.x);
  24201. coord.y = seg.p1.y - segmentLengthFraction * (seg.p1.y - seg.p0.y);
  24202. return coord;
  24203. }
  24204. splitAt() {
  24205. if (arguments.length === 1) {
  24206. const pt = arguments[0];
  24207. const minFrac = this._minimumLen / this._segLen;
  24208. if (pt.distance(this._seg.p0) < this._minimumLen) {
  24209. this._splitPt = this._seg.pointAlong(minFrac);
  24210. return null;
  24211. }
  24212. if (pt.distance(this._seg.p1) < this._minimumLen) {
  24213. this._splitPt = SplitSegment.pointAlongReverse(this._seg, minFrac);
  24214. return null;
  24215. }
  24216. this._splitPt = pt;
  24217. } else if (arguments.length === 2) {
  24218. const length = arguments[0],
  24219. endPt = arguments[1];
  24220. const actualLen = this.getConstrainedLength(length);
  24221. const frac = actualLen / this._segLen;
  24222. if (endPt.equals2D(this._seg.p0)) this._splitPt = this._seg.pointAlong(frac);else this._splitPt = SplitSegment.pointAlongReverse(this._seg, frac);
  24223. }
  24224. }
  24225. setMinimumLength(minLen) {
  24226. this._minimumLen = minLen;
  24227. }
  24228. getConstrainedLength(len) {
  24229. if (len < this._minimumLen) return this._minimumLen;
  24230. return len;
  24231. }
  24232. getSplitPoint() {
  24233. return this._splitPt;
  24234. }
  24235. }
  24236. class ConstraintSplitPointFinder {
  24237. findSplitPoint(seg, encroachPt) {}
  24238. }
  24239. class NonEncroachingSplitPointFinder {
  24240. static projectedSplitPoint(seg, encroachPt) {
  24241. const lineSeg = seg.getLineSegment();
  24242. const projPt = lineSeg.project(encroachPt);
  24243. return projPt;
  24244. }
  24245. findSplitPoint(seg, encroachPt) {
  24246. const lineSeg = seg.getLineSegment();
  24247. const segLen = lineSeg.getLength();
  24248. const midPtLen = segLen / 2;
  24249. const splitSeg = new SplitSegment(lineSeg);
  24250. const projPt = NonEncroachingSplitPointFinder.projectedSplitPoint(seg, encroachPt);
  24251. const nonEncroachDiam = projPt.distance(encroachPt) * 2 * 0.8;
  24252. let maxSplitLen = nonEncroachDiam;
  24253. if (maxSplitLen > midPtLen) maxSplitLen = midPtLen;
  24254. splitSeg.setMinimumLength(maxSplitLen);
  24255. splitSeg.splitAt(projPt);
  24256. return splitSeg.getSplitPoint();
  24257. }
  24258. get interfaces_() {
  24259. return [ConstraintSplitPointFinder];
  24260. }
  24261. }
  24262. class TrianglePredicate {
  24263. static triArea(a, b, c) {
  24264. return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
  24265. }
  24266. static isInCircleDDNormalized(a, b, c, p) {
  24267. const adx = DD.valueOf(a.x).selfSubtract(p.x);
  24268. const ady = DD.valueOf(a.y).selfSubtract(p.y);
  24269. const bdx = DD.valueOf(b.x).selfSubtract(p.x);
  24270. const bdy = DD.valueOf(b.y).selfSubtract(p.y);
  24271. const cdx = DD.valueOf(c.x).selfSubtract(p.x);
  24272. const cdy = DD.valueOf(c.y).selfSubtract(p.y);
  24273. const abdet = adx.multiply(bdy).selfSubtract(bdx.multiply(ady));
  24274. const bcdet = bdx.multiply(cdy).selfSubtract(cdx.multiply(bdy));
  24275. const cadet = cdx.multiply(ady).selfSubtract(adx.multiply(cdy));
  24276. const alift = adx.multiply(adx).selfAdd(ady.multiply(ady));
  24277. const blift = bdx.multiply(bdx).selfAdd(bdy.multiply(bdy));
  24278. const clift = cdx.multiply(cdx).selfAdd(cdy.multiply(cdy));
  24279. const sum = alift.selfMultiply(bcdet).selfAdd(blift.selfMultiply(cadet)).selfAdd(clift.selfMultiply(abdet));
  24280. const isInCircle = sum.doubleValue() > 0;
  24281. return isInCircle;
  24282. }
  24283. static checkRobustInCircle(a, b, c, p) {
  24284. const nonRobustInCircle = TrianglePredicate.isInCircleNonRobust(a, b, c, p);
  24285. const isInCircleDD = TrianglePredicate.isInCircleDDSlow(a, b, c, p);
  24286. const isInCircleCC = TrianglePredicate.isInCircleCC(a, b, c, p);
  24287. const circumCentre = Triangle.circumcentre(a, b, c);
  24288. System.out.println('p radius diff a = ' + Math.abs(p.distance(circumCentre) - a.distance(circumCentre)) / a.distance(circumCentre));
  24289. if (nonRobustInCircle !== isInCircleDD || nonRobustInCircle !== isInCircleCC) {
  24290. System.out.println('inCircle robustness failure (double result = ' + nonRobustInCircle + ', DD result = ' + isInCircleDD + ', CC result = ' + isInCircleCC + ')');
  24291. System.out.println(WKTWriter.toLineString(new CoordinateArraySequence([a, b, c, p])));
  24292. System.out.println('Circumcentre = ' + WKTWriter.toPoint(circumCentre) + ' radius = ' + a.distance(circumCentre));
  24293. System.out.println('p radius diff a = ' + Math.abs(p.distance(circumCentre) / a.distance(circumCentre) - 1));
  24294. System.out.println('p radius diff b = ' + Math.abs(p.distance(circumCentre) / b.distance(circumCentre) - 1));
  24295. System.out.println('p radius diff c = ' + Math.abs(p.distance(circumCentre) / c.distance(circumCentre) - 1));
  24296. System.out.println();
  24297. }
  24298. }
  24299. static isInCircleDDFast(a, b, c, p) {
  24300. const aTerm = DD.sqr(a.x).selfAdd(DD.sqr(a.y)).selfMultiply(TrianglePredicate.triAreaDDFast(b, c, p));
  24301. const bTerm = DD.sqr(b.x).selfAdd(DD.sqr(b.y)).selfMultiply(TrianglePredicate.triAreaDDFast(a, c, p));
  24302. const cTerm = DD.sqr(c.x).selfAdd(DD.sqr(c.y)).selfMultiply(TrianglePredicate.triAreaDDFast(a, b, p));
  24303. const pTerm = DD.sqr(p.x).selfAdd(DD.sqr(p.y)).selfMultiply(TrianglePredicate.triAreaDDFast(a, b, c));
  24304. const sum = aTerm.selfSubtract(bTerm).selfAdd(cTerm).selfSubtract(pTerm);
  24305. const isInCircle = sum.doubleValue() > 0;
  24306. return isInCircle;
  24307. }
  24308. static isInCircleCC(a, b, c, p) {
  24309. const cc = Triangle.circumcentre(a, b, c);
  24310. const ccRadius = a.distance(cc);
  24311. const pRadiusDiff = p.distance(cc) - ccRadius;
  24312. return pRadiusDiff <= 0;
  24313. }
  24314. static isInCircleNormalized(a, b, c, p) {
  24315. const adx = a.x - p.x;
  24316. const ady = a.y - p.y;
  24317. const bdx = b.x - p.x;
  24318. const bdy = b.y - p.y;
  24319. const cdx = c.x - p.x;
  24320. const cdy = c.y - p.y;
  24321. const abdet = adx * bdy - bdx * ady;
  24322. const bcdet = bdx * cdy - cdx * bdy;
  24323. const cadet = cdx * ady - adx * cdy;
  24324. const alift = adx * adx + ady * ady;
  24325. const blift = bdx * bdx + bdy * bdy;
  24326. const clift = cdx * cdx + cdy * cdy;
  24327. const disc = alift * bcdet + blift * cadet + clift * abdet;
  24328. return disc > 0;
  24329. }
  24330. static isInCircleDDSlow(a, b, c, p) {
  24331. const px = DD.valueOf(p.x);
  24332. const py = DD.valueOf(p.y);
  24333. const ax = DD.valueOf(a.x);
  24334. const ay = DD.valueOf(a.y);
  24335. const bx = DD.valueOf(b.x);
  24336. const by = DD.valueOf(b.y);
  24337. const cx = DD.valueOf(c.x);
  24338. const cy = DD.valueOf(c.y);
  24339. const aTerm = ax.multiply(ax).add(ay.multiply(ay)).multiply(TrianglePredicate.triAreaDDSlow(bx, by, cx, cy, px, py));
  24340. const bTerm = bx.multiply(bx).add(by.multiply(by)).multiply(TrianglePredicate.triAreaDDSlow(ax, ay, cx, cy, px, py));
  24341. const cTerm = cx.multiply(cx).add(cy.multiply(cy)).multiply(TrianglePredicate.triAreaDDSlow(ax, ay, bx, by, px, py));
  24342. const pTerm = px.multiply(px).add(py.multiply(py)).multiply(TrianglePredicate.triAreaDDSlow(ax, ay, bx, by, cx, cy));
  24343. const sum = aTerm.subtract(bTerm).add(cTerm).subtract(pTerm);
  24344. const isInCircle = sum.doubleValue() > 0;
  24345. return isInCircle;
  24346. }
  24347. static isInCircleNonRobust(a, b, c, p) {
  24348. const isInCircle = (a.x * a.x + a.y * a.y) * TrianglePredicate.triArea(b, c, p) - (b.x * b.x + b.y * b.y) * TrianglePredicate.triArea(a, c, p) + (c.x * c.x + c.y * c.y) * TrianglePredicate.triArea(a, b, p) - (p.x * p.x + p.y * p.y) * TrianglePredicate.triArea(a, b, c) > 0;
  24349. return isInCircle;
  24350. }
  24351. static isInCircleRobust(a, b, c, p) {
  24352. return TrianglePredicate.isInCircleNormalized(a, b, c, p);
  24353. }
  24354. static triAreaDDSlow(ax, ay, bx, by, cx, cy) {
  24355. return bx.subtract(ax).multiply(cy.subtract(ay)).subtract(by.subtract(ay).multiply(cx.subtract(ax)));
  24356. }
  24357. static triAreaDDFast(a, b, c) {
  24358. const t1 = DD.valueOf(b.x).selfSubtract(a.x).selfMultiply(DD.valueOf(c.y).selfSubtract(a.y));
  24359. const t2 = DD.valueOf(b.y).selfSubtract(a.y).selfMultiply(DD.valueOf(c.x).selfSubtract(a.x));
  24360. return t1.selfSubtract(t2);
  24361. }
  24362. }
  24363. class Vertex {
  24364. constructor() {
  24365. Vertex.constructor_.apply(this, arguments);
  24366. }
  24367. static constructor_() {
  24368. this._p = null;
  24369. if (arguments.length === 1) {
  24370. const _p = arguments[0];
  24371. this._p = new Coordinate(_p);
  24372. } else if (arguments.length === 2) {
  24373. const _x = arguments[0],
  24374. _y = arguments[1];
  24375. this._p = new Coordinate(_x, _y);
  24376. } else if (arguments.length === 3) {
  24377. const _x = arguments[0],
  24378. _y = arguments[1],
  24379. _z = arguments[2];
  24380. this._p = new Coordinate(_x, _y, _z);
  24381. }
  24382. }
  24383. static interpolateZ() {
  24384. if (arguments.length === 3) {
  24385. const p = arguments[0],
  24386. p0 = arguments[1],
  24387. p1 = arguments[2];
  24388. const segLen = p0.distance(p1);
  24389. const ptLen = p.distance(p0);
  24390. const dz = p1.getZ() - p0.getZ();
  24391. const pz = p0.getZ() + dz * (ptLen / segLen);
  24392. return pz;
  24393. } else if (arguments.length === 4) {
  24394. const p = arguments[0],
  24395. v0 = arguments[1],
  24396. v1 = arguments[2],
  24397. v2 = arguments[3];
  24398. const x0 = v0.x;
  24399. const y0 = v0.y;
  24400. const a = v1.x - x0;
  24401. const b = v2.x - x0;
  24402. const c = v1.y - y0;
  24403. const d = v2.y - y0;
  24404. const det = a * d - b * c;
  24405. const dx = p.x - x0;
  24406. const dy = p.y - y0;
  24407. const t = (d * dx - b * dy) / det;
  24408. const u = (-c * dx + a * dy) / det;
  24409. const z = v0.getZ() + t * (v1.getZ() - v0.getZ()) + u * (v2.getZ() - v0.getZ());
  24410. return z;
  24411. }
  24412. }
  24413. circleCenter(b, c) {
  24414. const a = new Vertex(this.getX(), this.getY());
  24415. const cab = this.bisector(a, b);
  24416. const cbc = this.bisector(b, c);
  24417. const hcc = new HCoordinate(cab, cbc);
  24418. let cc = null;
  24419. try {
  24420. cc = new Vertex(hcc.getX(), hcc.getY());
  24421. } catch (nre) {
  24422. if (nre instanceof NotRepresentableException) {
  24423. System.err.println('a: ' + a + ' b: ' + b + ' c: ' + c);
  24424. System.err.println(nre);
  24425. } else {
  24426. throw nre;
  24427. }
  24428. } finally {}
  24429. return cc;
  24430. }
  24431. dot(v) {
  24432. return this._p.x * v.getX() + this._p.y * v.getY();
  24433. }
  24434. magn() {
  24435. return Math.sqrt(this._p.x * this._p.x + this._p.y * this._p.y);
  24436. }
  24437. getZ() {
  24438. return this._p.getZ();
  24439. }
  24440. bisector(a, b) {
  24441. const dx = b.getX() - a.getX();
  24442. const dy = b.getY() - a.getY();
  24443. const l1 = new HCoordinate(a.getX() + dx / 2.0, a.getY() + dy / 2.0, 1.0);
  24444. const l2 = new HCoordinate(a.getX() - dy + dx / 2.0, a.getY() + dx + dy / 2.0, 1.0);
  24445. return new HCoordinate(l1, l2);
  24446. }
  24447. equals() {
  24448. if (arguments.length === 1) {
  24449. const _x = arguments[0];
  24450. if (this._p.x === _x.getX() && this._p.y === _x.getY()) return true;else return false;
  24451. } else if (arguments.length === 2) {
  24452. const _x = arguments[0],
  24453. tolerance = arguments[1];
  24454. if (this._p.distance(_x.getCoordinate()) < tolerance) return true;else return false;
  24455. }
  24456. }
  24457. getCoordinate() {
  24458. return this._p;
  24459. }
  24460. isInCircle(a, b, c) {
  24461. return TrianglePredicate.isInCircleRobust(a._p, b._p, c._p, this._p);
  24462. }
  24463. interpolateZValue(v0, v1, v2) {
  24464. const x0 = v0.getX();
  24465. const y0 = v0.getY();
  24466. const a = v1.getX() - x0;
  24467. const b = v2.getX() - x0;
  24468. const c = v1.getY() - y0;
  24469. const d = v2.getY() - y0;
  24470. const det = a * d - b * c;
  24471. const dx = this.getX() - x0;
  24472. const dy = this.getY() - y0;
  24473. const t = (d * dx - b * dy) / det;
  24474. const u = (-c * dx + a * dy) / det;
  24475. const z = v0.getZ() + t * (v1.getZ() - v0.getZ()) + u * (v2.getZ() - v0.getZ());
  24476. return z;
  24477. }
  24478. midPoint(a) {
  24479. const xm = (this._p.x + a.getX()) / 2.0;
  24480. const ym = (this._p.y + a.getY()) / 2.0;
  24481. const zm = (this._p.getZ() + a.getZ()) / 2.0;
  24482. return new Vertex(xm, ym, zm);
  24483. }
  24484. rightOf(e) {
  24485. return this.isCCW(e.dest(), e.orig());
  24486. }
  24487. isCCW(b, c) {
  24488. return (b._p.x - this._p.x) * (c._p.y - this._p.y) - (b._p.y - this._p.y) * (c._p.x - this._p.x) > 0;
  24489. }
  24490. getX() {
  24491. return this._p.x;
  24492. }
  24493. crossProduct(v) {
  24494. return this._p.x * v.getY() - this._p.y * v.getX();
  24495. }
  24496. setZ(_z) {
  24497. this._p.setZ(_z);
  24498. }
  24499. times(c) {
  24500. return new Vertex(c * this._p.x, c * this._p.y);
  24501. }
  24502. cross() {
  24503. return new Vertex(this._p.y, -this._p.x);
  24504. }
  24505. leftOf(e) {
  24506. return this.isCCW(e.orig(), e.dest());
  24507. }
  24508. toString() {
  24509. return 'POINT (' + this._p.x + ' ' + this._p.y + ')';
  24510. }
  24511. sub(v) {
  24512. return new Vertex(this._p.x - v.getX(), this._p.y - v.getY());
  24513. }
  24514. getY() {
  24515. return this._p.y;
  24516. }
  24517. classify(p0, p1) {
  24518. const p2 = this;
  24519. const a = p1.sub(p0);
  24520. const b = p2.sub(p0);
  24521. const sa = a.crossProduct(b);
  24522. if (sa > 0.0) return Vertex.LEFT;
  24523. if (sa < 0.0) return Vertex.RIGHT;
  24524. if (a.getX() * b.getX() < 0.0 || a.getY() * b.getY() < 0.0) return Vertex.BEHIND;
  24525. if (a.magn() < b.magn()) return Vertex.BEYOND;
  24526. if (p0.equals(p2)) return Vertex.ORIGIN;
  24527. if (p1.equals(p2)) return Vertex.DESTINATION;
  24528. return Vertex.BETWEEN;
  24529. }
  24530. sum(v) {
  24531. return new Vertex(this._p.x + v.getX(), this._p.y + v.getY());
  24532. }
  24533. distance(v1, v2) {
  24534. return Math.sqrt(Math.pow(v2.getX() - v1.getX(), 2.0) + Math.pow(v2.getY() - v1.getY(), 2.0));
  24535. }
  24536. circumRadiusRatio(b, c) {
  24537. const x = this.circleCenter(b, c);
  24538. const radius = this.distance(x, b);
  24539. let edgeLength = this.distance(this, b);
  24540. let el = this.distance(b, c);
  24541. if (el < edgeLength) edgeLength = el;
  24542. el = this.distance(c, this);
  24543. if (el < edgeLength) edgeLength = el;
  24544. return radius / edgeLength;
  24545. }
  24546. }
  24547. Vertex.LEFT = 0;
  24548. Vertex.RIGHT = 1;
  24549. Vertex.BEYOND = 2;
  24550. Vertex.BEHIND = 3;
  24551. Vertex.BETWEEN = 4;
  24552. Vertex.ORIGIN = 5;
  24553. Vertex.DESTINATION = 6;
  24554. class ConstraintVertex extends Vertex {
  24555. constructor() {
  24556. super();
  24557. ConstraintVertex.constructor_.apply(this, arguments);
  24558. }
  24559. static constructor_() {
  24560. this._isOnConstraint = null;
  24561. this._constraint = null;
  24562. const p = arguments[0];
  24563. Vertex.constructor_.call(this, p);
  24564. }
  24565. getConstraint() {
  24566. return this._constraint;
  24567. }
  24568. setOnConstraint(isOnConstraint) {
  24569. this._isOnConstraint = isOnConstraint;
  24570. }
  24571. merge(other) {
  24572. if (other._isOnConstraint) {
  24573. this._isOnConstraint = true;
  24574. this._constraint = other._constraint;
  24575. }
  24576. }
  24577. isOnConstraint() {
  24578. return this._isOnConstraint;
  24579. }
  24580. setConstraint(constraint) {
  24581. this._isOnConstraint = true;
  24582. this._constraint = constraint;
  24583. }
  24584. }
  24585. class QuadEdge {
  24586. constructor() {
  24587. QuadEdge.constructor_.apply(this, arguments);
  24588. }
  24589. static constructor_() {
  24590. this._rot = null;
  24591. this._vertex = null;
  24592. this._next = null;
  24593. this._data = null;
  24594. }
  24595. static makeEdge(o, d) {
  24596. const q0 = new QuadEdge();
  24597. const q1 = new QuadEdge();
  24598. const q2 = new QuadEdge();
  24599. const q3 = new QuadEdge();
  24600. q0._rot = q1;
  24601. q1._rot = q2;
  24602. q2._rot = q3;
  24603. q3._rot = q0;
  24604. q0.setNext(q0);
  24605. q1.setNext(q3);
  24606. q2.setNext(q2);
  24607. q3.setNext(q1);
  24608. const base = q0;
  24609. base.setOrig(o);
  24610. base.setDest(d);
  24611. return base;
  24612. }
  24613. static swap(e) {
  24614. const a = e.oPrev();
  24615. const b = e.sym().oPrev();
  24616. QuadEdge.splice(e, a);
  24617. QuadEdge.splice(e.sym(), b);
  24618. QuadEdge.splice(e, a.lNext());
  24619. QuadEdge.splice(e.sym(), b.lNext());
  24620. e.setOrig(a.dest());
  24621. e.setDest(b.dest());
  24622. }
  24623. static splice(a, b) {
  24624. const alpha = a.oNext().rot();
  24625. const beta = b.oNext().rot();
  24626. const t1 = b.oNext();
  24627. const t2 = a.oNext();
  24628. const t3 = beta.oNext();
  24629. const t4 = alpha.oNext();
  24630. a.setNext(t1);
  24631. b.setNext(t2);
  24632. alpha.setNext(t3);
  24633. beta.setNext(t4);
  24634. }
  24635. static connect(a, b) {
  24636. const e = QuadEdge.makeEdge(a.dest(), b.orig());
  24637. QuadEdge.splice(e, a.lNext());
  24638. QuadEdge.splice(e.sym(), b);
  24639. return e;
  24640. }
  24641. equalsNonOriented(qe) {
  24642. if (this.equalsOriented(qe)) return true;
  24643. if (this.equalsOriented(qe.sym())) return true;
  24644. return false;
  24645. }
  24646. toLineSegment() {
  24647. return new LineSegment(this._vertex.getCoordinate(), this.dest().getCoordinate());
  24648. }
  24649. dest() {
  24650. return this.sym().orig();
  24651. }
  24652. oNext() {
  24653. return this._next;
  24654. }
  24655. equalsOriented(qe) {
  24656. if (this.orig().getCoordinate().equals2D(qe.orig().getCoordinate()) && this.dest().getCoordinate().equals2D(qe.dest().getCoordinate())) return true;
  24657. return false;
  24658. }
  24659. dNext() {
  24660. return this.sym().oNext().sym();
  24661. }
  24662. lPrev() {
  24663. return this._next.sym();
  24664. }
  24665. rPrev() {
  24666. return this.sym().oNext();
  24667. }
  24668. rot() {
  24669. return this._rot;
  24670. }
  24671. oPrev() {
  24672. return this._rot._next._rot;
  24673. }
  24674. sym() {
  24675. return this._rot._rot;
  24676. }
  24677. setOrig(o) {
  24678. this._vertex = o;
  24679. }
  24680. lNext() {
  24681. return this.invRot().oNext().rot();
  24682. }
  24683. getLength() {
  24684. return this.orig().getCoordinate().distance(this.dest().getCoordinate());
  24685. }
  24686. invRot() {
  24687. return this._rot.sym();
  24688. }
  24689. setDest(d) {
  24690. this.sym().setOrig(d);
  24691. }
  24692. setData(data) {
  24693. this._data = data;
  24694. }
  24695. getData() {
  24696. return this._data;
  24697. }
  24698. delete() {
  24699. this._rot = null;
  24700. }
  24701. orig() {
  24702. return this._vertex;
  24703. }
  24704. rNext() {
  24705. return this._rot._next.invRot();
  24706. }
  24707. toString() {
  24708. const p0 = this._vertex.getCoordinate();
  24709. const p1 = this.dest().getCoordinate();
  24710. return WKTWriter.toLineString(p0, p1);
  24711. }
  24712. isLive() {
  24713. return this._rot !== null;
  24714. }
  24715. getPrimary() {
  24716. if (this.orig().getCoordinate().compareTo(this.dest().getCoordinate()) <= 0) return this;else return this.sym();
  24717. }
  24718. dPrev() {
  24719. return this.invRot().oNext().invRot();
  24720. }
  24721. setNext(next) {
  24722. this._next = next;
  24723. }
  24724. }
  24725. class IncrementalDelaunayTriangulator {
  24726. constructor() {
  24727. IncrementalDelaunayTriangulator.constructor_.apply(this, arguments);
  24728. }
  24729. static constructor_() {
  24730. this._subdiv = null;
  24731. this._isUsingTolerance = false;
  24732. const subdiv = arguments[0];
  24733. this._subdiv = subdiv;
  24734. this._isUsingTolerance = subdiv.getTolerance() > 0.0;
  24735. }
  24736. insertSite(v) {
  24737. let e = this._subdiv.locate(v);
  24738. if (this._subdiv.isVertexOfEdge(e, v)) {
  24739. return e;
  24740. } else if (this._subdiv.isOnEdge(e, v.getCoordinate())) {
  24741. e = e.oPrev();
  24742. this._subdiv.delete(e.oNext());
  24743. }
  24744. let base = this._subdiv.makeEdge(e.orig(), v);
  24745. QuadEdge.splice(base, e);
  24746. const startEdge = base;
  24747. do {
  24748. base = this._subdiv.connect(e, base.sym());
  24749. e = base.oPrev();
  24750. } while (e.lNext() !== startEdge);
  24751. do {
  24752. const t = e.oPrev();
  24753. if (t.dest().rightOf(e) && v.isInCircle(e.orig(), t.dest(), e.dest())) {
  24754. QuadEdge.swap(e);
  24755. e = e.oPrev();
  24756. } else if (e.oNext() === startEdge) {
  24757. return base;
  24758. } else {
  24759. e = e.oNext().lPrev();
  24760. }
  24761. } while (true);
  24762. }
  24763. insertSites(vertices) {
  24764. for (let i = vertices.iterator(); i.hasNext();) {
  24765. const v = i.next();
  24766. this.insertSite(v);
  24767. }
  24768. }
  24769. }
  24770. class QuadEdgeLocator {
  24771. locate(v) {}
  24772. }
  24773. class LastFoundQuadEdgeLocator {
  24774. constructor() {
  24775. LastFoundQuadEdgeLocator.constructor_.apply(this, arguments);
  24776. }
  24777. static constructor_() {
  24778. this._subdiv = null;
  24779. this._lastEdge = null;
  24780. const subdiv = arguments[0];
  24781. this._subdiv = subdiv;
  24782. this.init();
  24783. }
  24784. init() {
  24785. this._lastEdge = this.findEdge();
  24786. }
  24787. locate(v) {
  24788. if (!this._lastEdge.isLive()) this.init();
  24789. const e = this._subdiv.locateFromEdge(v, this._lastEdge);
  24790. this._lastEdge = e;
  24791. return e;
  24792. }
  24793. findEdge() {
  24794. const edges = this._subdiv.getEdges();
  24795. return edges.iterator().next();
  24796. }
  24797. get interfaces_() {
  24798. return [QuadEdgeLocator];
  24799. }
  24800. }
  24801. class LocateFailureException extends RuntimeException {
  24802. constructor() {
  24803. super();
  24804. LocateFailureException.constructor_.apply(this, arguments);
  24805. }
  24806. static constructor_() {
  24807. this._seg = null;
  24808. if (arguments.length === 1) {
  24809. if (typeof arguments[0] === 'string') {
  24810. const msg = arguments[0];
  24811. RuntimeException.constructor_.call(this, msg);
  24812. } else if (arguments[0] instanceof LineSegment) {
  24813. const seg = arguments[0];
  24814. RuntimeException.constructor_.call(this, 'Locate failed to converge (at edge: ' + seg + '). Possible causes include invalid Subdivision topology or very close sites');
  24815. this._seg = new LineSegment(seg);
  24816. }
  24817. } else if (arguments.length === 2) {
  24818. const msg = arguments[0],
  24819. seg = arguments[1];
  24820. RuntimeException.constructor_.call(this, LocateFailureException.msgWithSpatial(msg, seg));
  24821. this._seg = new LineSegment(seg);
  24822. }
  24823. }
  24824. static msgWithSpatial(msg, seg) {
  24825. if (seg !== null) return msg + ' [ ' + seg + ' ]';
  24826. return msg;
  24827. }
  24828. getSegment() {
  24829. return this._seg;
  24830. }
  24831. }
  24832. class TriangleVisitor {
  24833. visit(triEdges) {}
  24834. }
  24835. class QuadEdgeSubdivision {
  24836. constructor() {
  24837. QuadEdgeSubdivision.constructor_.apply(this, arguments);
  24838. }
  24839. static constructor_() {
  24840. this._visitedKey = 0;
  24841. this._quadEdges = new ArrayList();
  24842. this._startingEdge = null;
  24843. this._tolerance = null;
  24844. this._edgeCoincidenceTolerance = null;
  24845. this._frameVertex = new Array(3).fill(null);
  24846. this._frameEnv = null;
  24847. this._locator = null;
  24848. this._seg = new LineSegment();
  24849. this._triEdges = new Array(3).fill(null);
  24850. const env = arguments[0],
  24851. tolerance = arguments[1];
  24852. this._tolerance = tolerance;
  24853. this._edgeCoincidenceTolerance = tolerance / QuadEdgeSubdivision.EDGE_COINCIDENCE_TOL_FACTOR;
  24854. this.createFrame(env);
  24855. this._startingEdge = this.initSubdiv();
  24856. this._locator = new LastFoundQuadEdgeLocator(this);
  24857. }
  24858. static getTriangleEdges(startQE, triEdge) {
  24859. triEdge[0] = startQE;
  24860. triEdge[1] = triEdge[0].lNext();
  24861. triEdge[2] = triEdge[1].lNext();
  24862. if (triEdge[2].lNext() !== triEdge[0]) throw new IllegalArgumentException('Edges do not form a triangle');
  24863. }
  24864. getTriangleVertices(includeFrame) {
  24865. const visitor = new TriangleVertexListVisitor();
  24866. this.visitTriangles(visitor, includeFrame);
  24867. return visitor.getTriangleVertices();
  24868. }
  24869. isFrameVertex(v) {
  24870. if (v.equals(this._frameVertex[0])) return true;
  24871. if (v.equals(this._frameVertex[1])) return true;
  24872. if (v.equals(this._frameVertex[2])) return true;
  24873. return false;
  24874. }
  24875. isVertexOfEdge(e, v) {
  24876. if (v.equals(e.orig(), this._tolerance) || v.equals(e.dest(), this._tolerance)) return true;
  24877. return false;
  24878. }
  24879. connect(a, b) {
  24880. const q = QuadEdge.connect(a, b);
  24881. this._quadEdges.add(q);
  24882. return q;
  24883. }
  24884. getVoronoiCellPolygon(qe, geomFact) {
  24885. const cellPts = new ArrayList();
  24886. const startQE = qe;
  24887. do {
  24888. const cc = qe.rot().orig().getCoordinate();
  24889. cellPts.add(cc);
  24890. qe = qe.oPrev();
  24891. } while (qe !== startQE);
  24892. const coordList = new CoordinateList();
  24893. coordList.addAll(cellPts, false);
  24894. coordList.closeRing();
  24895. if (coordList.size() < 4) {
  24896. System.out.println(coordList);
  24897. coordList.add(coordList.get(coordList.size() - 1), true);
  24898. }
  24899. const pts = coordList.toCoordinateArray();
  24900. const cellPoly = geomFact.createPolygon(geomFact.createLinearRing(pts));
  24901. const v = startQE.orig();
  24902. cellPoly.setUserData(v.getCoordinate());
  24903. return cellPoly;
  24904. }
  24905. setLocator(locator) {
  24906. this._locator = locator;
  24907. }
  24908. initSubdiv() {
  24909. const ea = this.makeEdge(this._frameVertex[0], this._frameVertex[1]);
  24910. const eb = this.makeEdge(this._frameVertex[1], this._frameVertex[2]);
  24911. QuadEdge.splice(ea.sym(), eb);
  24912. const ec = this.makeEdge(this._frameVertex[2], this._frameVertex[0]);
  24913. QuadEdge.splice(eb.sym(), ec);
  24914. QuadEdge.splice(ec.sym(), ea);
  24915. return ea;
  24916. }
  24917. isFrameBorderEdge(e) {
  24918. const leftTri = new Array(3).fill(null);
  24919. QuadEdgeSubdivision.getTriangleEdges(e, leftTri);
  24920. const rightTri = new Array(3).fill(null);
  24921. QuadEdgeSubdivision.getTriangleEdges(e.sym(), rightTri);
  24922. const vLeftTriOther = e.lNext().dest();
  24923. if (this.isFrameVertex(vLeftTriOther)) return true;
  24924. const vRightTriOther = e.sym().lNext().dest();
  24925. if (this.isFrameVertex(vRightTriOther)) return true;
  24926. return false;
  24927. }
  24928. makeEdge(o, d) {
  24929. const q = QuadEdge.makeEdge(o, d);
  24930. this._quadEdges.add(q);
  24931. return q;
  24932. }
  24933. visitTriangles(triVisitor, includeFrame) {
  24934. this._visitedKey++;
  24935. const edgeStack = new Stack();
  24936. edgeStack.push(this._startingEdge);
  24937. const visitedEdges = new HashSet();
  24938. while (!edgeStack.empty()) {
  24939. const edge = edgeStack.pop();
  24940. if (!visitedEdges.contains(edge)) {
  24941. const triEdges = this.fetchTriangleToVisit(edge, edgeStack, includeFrame, visitedEdges);
  24942. if (triEdges !== null) triVisitor.visit(triEdges);
  24943. }
  24944. }
  24945. }
  24946. isFrameEdge(e) {
  24947. if (this.isFrameVertex(e.orig()) || this.isFrameVertex(e.dest())) return true;
  24948. return false;
  24949. }
  24950. isOnEdge(e, p) {
  24951. this._seg.setCoordinates(e.orig().getCoordinate(), e.dest().getCoordinate());
  24952. const dist = this._seg.distance(p);
  24953. return dist < this._edgeCoincidenceTolerance;
  24954. }
  24955. getEnvelope() {
  24956. return new Envelope(this._frameEnv);
  24957. }
  24958. createFrame(env) {
  24959. const deltaX = env.getWidth();
  24960. const deltaY = env.getHeight();
  24961. let offset = 0.0;
  24962. if (deltaX > deltaY) offset = deltaX * 10.0;else offset = deltaY * 10.0;
  24963. this._frameVertex[0] = new Vertex((env.getMaxX() + env.getMinX()) / 2.0, env.getMaxY() + offset);
  24964. this._frameVertex[1] = new Vertex(env.getMinX() - offset, env.getMinY() - offset);
  24965. this._frameVertex[2] = new Vertex(env.getMaxX() + offset, env.getMinY() - offset);
  24966. this._frameEnv = new Envelope(this._frameVertex[0].getCoordinate(), this._frameVertex[1].getCoordinate());
  24967. this._frameEnv.expandToInclude(this._frameVertex[2].getCoordinate());
  24968. }
  24969. getTriangleCoordinates(includeFrame) {
  24970. const visitor = new TriangleCoordinatesVisitor();
  24971. this.visitTriangles(visitor, includeFrame);
  24972. return visitor.getTriangles();
  24973. }
  24974. getVertices(includeFrame) {
  24975. const vertices = new HashSet();
  24976. for (let i = this._quadEdges.iterator(); i.hasNext();) {
  24977. const qe = i.next();
  24978. const v = qe.orig();
  24979. if (includeFrame || !this.isFrameVertex(v)) vertices.add(v);
  24980. const vd = qe.dest();
  24981. if (includeFrame || !this.isFrameVertex(vd)) vertices.add(vd);
  24982. }
  24983. return vertices;
  24984. }
  24985. fetchTriangleToVisit(edge, edgeStack, includeFrame, visitedEdges) {
  24986. let curr = edge;
  24987. let edgeCount = 0;
  24988. let isFrame = false;
  24989. do {
  24990. this._triEdges[edgeCount] = curr;
  24991. if (this.isFrameEdge(curr)) isFrame = true;
  24992. const sym = curr.sym();
  24993. if (!visitedEdges.contains(sym)) edgeStack.push(sym);
  24994. visitedEdges.add(curr);
  24995. edgeCount++;
  24996. curr = curr.lNext();
  24997. } while (curr !== edge);
  24998. if (isFrame && !includeFrame) return null;
  24999. return this._triEdges;
  25000. }
  25001. getEdges() {
  25002. if (arguments.length === 0) {
  25003. return this._quadEdges;
  25004. } else if (arguments.length === 1) {
  25005. const geomFact = arguments[0];
  25006. const quadEdges = this.getPrimaryEdges(false);
  25007. const edges = new Array(quadEdges.size()).fill(null);
  25008. let i = 0;
  25009. for (let it = quadEdges.iterator(); it.hasNext();) {
  25010. const qe = it.next();
  25011. edges[i++] = geomFact.createLineString([qe.orig().getCoordinate(), qe.dest().getCoordinate()]);
  25012. }
  25013. return geomFact.createMultiLineString(edges);
  25014. }
  25015. }
  25016. getVertexUniqueEdges(includeFrame) {
  25017. const edges = new ArrayList();
  25018. const visitedVertices = new HashSet();
  25019. for (let i = this._quadEdges.iterator(); i.hasNext();) {
  25020. const qe = i.next();
  25021. const v = qe.orig();
  25022. if (!visitedVertices.contains(v)) {
  25023. visitedVertices.add(v);
  25024. if (includeFrame || !this.isFrameVertex(v)) edges.add(qe);
  25025. }
  25026. const qd = qe.sym();
  25027. const vd = qd.orig();
  25028. if (!visitedVertices.contains(vd)) {
  25029. visitedVertices.add(vd);
  25030. if (includeFrame || !this.isFrameVertex(vd)) edges.add(qd);
  25031. }
  25032. }
  25033. return edges;
  25034. }
  25035. getTriangleEdges(includeFrame) {
  25036. const visitor = new TriangleEdgesListVisitor();
  25037. this.visitTriangles(visitor, includeFrame);
  25038. return visitor.getTriangleEdges();
  25039. }
  25040. getPrimaryEdges(includeFrame) {
  25041. this._visitedKey++;
  25042. const edges = new ArrayList();
  25043. const edgeStack = new Stack();
  25044. edgeStack.push(this._startingEdge);
  25045. const visitedEdges = new HashSet();
  25046. while (!edgeStack.empty()) {
  25047. const edge = edgeStack.pop();
  25048. if (!visitedEdges.contains(edge)) {
  25049. const priQE = edge.getPrimary();
  25050. if (includeFrame || !this.isFrameEdge(priQE)) edges.add(priQE);
  25051. edgeStack.push(edge.oNext());
  25052. edgeStack.push(edge.sym().oNext());
  25053. visitedEdges.add(edge);
  25054. visitedEdges.add(edge.sym());
  25055. }
  25056. }
  25057. return edges;
  25058. }
  25059. delete(e) {
  25060. QuadEdge.splice(e, e.oPrev());
  25061. QuadEdge.splice(e.sym(), e.sym().oPrev());
  25062. const eSym = e.sym();
  25063. const eRot = e.rot();
  25064. const eRotSym = e.rot().sym();
  25065. this._quadEdges.remove(e);
  25066. this._quadEdges.remove(eSym);
  25067. this._quadEdges.remove(eRot);
  25068. this._quadEdges.remove(eRotSym);
  25069. e.delete();
  25070. eSym.delete();
  25071. eRot.delete();
  25072. eRotSym.delete();
  25073. }
  25074. locateFromEdge(v, startEdge) {
  25075. let iter = 0;
  25076. const maxIter = this._quadEdges.size();
  25077. let e = startEdge;
  25078. while (true) {
  25079. iter++;
  25080. if (iter > maxIter) throw new LocateFailureException(e.toLineSegment());
  25081. if (v.equals(e.orig()) || v.equals(e.dest())) break;else if (v.rightOf(e)) e = e.sym();else if (!v.rightOf(e.oNext())) e = e.oNext();else if (!v.rightOf(e.dPrev())) e = e.dPrev();else break;
  25082. }
  25083. return e;
  25084. }
  25085. getTolerance() {
  25086. return this._tolerance;
  25087. }
  25088. getVoronoiCellPolygons(geomFact) {
  25089. this.visitTriangles(new TriangleCircumcentreVisitor(), true);
  25090. const cells = new ArrayList();
  25091. const edges = this.getVertexUniqueEdges(false);
  25092. for (let i = edges.iterator(); i.hasNext();) {
  25093. const qe = i.next();
  25094. cells.add(this.getVoronoiCellPolygon(qe, geomFact));
  25095. }
  25096. return cells;
  25097. }
  25098. getVoronoiDiagram(geomFact) {
  25099. const vorCells = this.getVoronoiCellPolygons(geomFact);
  25100. return geomFact.createGeometryCollection(GeometryFactory.toGeometryArray(vorCells));
  25101. }
  25102. getTriangles(geomFact) {
  25103. const triPtsList = this.getTriangleCoordinates(false);
  25104. const tris = new Array(triPtsList.size()).fill(null);
  25105. let i = 0;
  25106. for (let it = triPtsList.iterator(); it.hasNext();) {
  25107. const triPt = it.next();
  25108. tris[i++] = geomFact.createPolygon(geomFact.createLinearRing(triPt));
  25109. }
  25110. return geomFact.createGeometryCollection(tris);
  25111. }
  25112. insertSite(v) {
  25113. let e = this.locate(v);
  25114. if (v.equals(e.orig(), this._tolerance) || v.equals(e.dest(), this._tolerance)) return e;
  25115. let base = this.makeEdge(e.orig(), v);
  25116. QuadEdge.splice(base, e);
  25117. const startEdge = base;
  25118. do {
  25119. base = this.connect(e, base.sym());
  25120. e = base.oPrev();
  25121. } while (e.lNext() !== startEdge);
  25122. return startEdge;
  25123. }
  25124. locate() {
  25125. if (arguments.length === 1) {
  25126. if (arguments[0] instanceof Vertex) {
  25127. const v = arguments[0];
  25128. return this._locator.locate(v);
  25129. } else if (arguments[0] instanceof Coordinate) {
  25130. const p = arguments[0];
  25131. return this._locator.locate(new Vertex(p));
  25132. }
  25133. } else if (arguments.length === 2) {
  25134. const p0 = arguments[0],
  25135. p1 = arguments[1];
  25136. const e = this._locator.locate(new Vertex(p0));
  25137. if (e === null) return null;
  25138. let base = e;
  25139. if (e.dest().getCoordinate().equals2D(p0)) base = e.sym();
  25140. let locEdge = base;
  25141. do {
  25142. if (locEdge.dest().getCoordinate().equals2D(p1)) return locEdge;
  25143. locEdge = locEdge.oNext();
  25144. } while (locEdge !== base);
  25145. return null;
  25146. }
  25147. }
  25148. }
  25149. class TriangleCircumcentreVisitor {
  25150. visit(triEdges) {
  25151. const a = triEdges[0].orig().getCoordinate();
  25152. const b = triEdges[1].orig().getCoordinate();
  25153. const c = triEdges[2].orig().getCoordinate();
  25154. const cc = Triangle.circumcentreDD(a, b, c);
  25155. const ccVertex = new Vertex(cc);
  25156. for (let i = 0; i < 3; i++) triEdges[i].rot().setOrig(ccVertex);
  25157. }
  25158. get interfaces_() {
  25159. return [TriangleVisitor];
  25160. }
  25161. }
  25162. class TriangleEdgesListVisitor {
  25163. constructor() {
  25164. TriangleEdgesListVisitor.constructor_.apply(this, arguments);
  25165. }
  25166. static constructor_() {
  25167. this._triList = new ArrayList();
  25168. }
  25169. getTriangleEdges() {
  25170. return this._triList;
  25171. }
  25172. visit(triEdges) {
  25173. this._triList.add(triEdges);
  25174. }
  25175. get interfaces_() {
  25176. return [TriangleVisitor];
  25177. }
  25178. }
  25179. class TriangleVertexListVisitor {
  25180. constructor() {
  25181. TriangleVertexListVisitor.constructor_.apply(this, arguments);
  25182. }
  25183. static constructor_() {
  25184. this._triList = new ArrayList();
  25185. }
  25186. visit(triEdges) {
  25187. this._triList.add([triEdges[0].orig(), triEdges[1].orig(), triEdges[2].orig()]);
  25188. }
  25189. getTriangleVertices() {
  25190. return this._triList;
  25191. }
  25192. get interfaces_() {
  25193. return [TriangleVisitor];
  25194. }
  25195. }
  25196. class TriangleCoordinatesVisitor {
  25197. constructor() {
  25198. TriangleCoordinatesVisitor.constructor_.apply(this, arguments);
  25199. }
  25200. static constructor_() {
  25201. this._coordList = new CoordinateList();
  25202. this._triCoords = new ArrayList();
  25203. }
  25204. checkTriangleSize(pts) {
  25205. if (pts.length >= 2) WKTWriter.toLineString(pts[0], pts[1]);else if (pts.length >= 1) WKTWriter.toPoint(pts[0]);
  25206. }
  25207. visit(triEdges) {
  25208. this._coordList.clear();
  25209. for (let i = 0; i < 3; i++) {
  25210. const v = triEdges[i].orig();
  25211. this._coordList.add(v.getCoordinate());
  25212. }
  25213. if (this._coordList.size() > 0) {
  25214. this._coordList.closeRing();
  25215. const pts = this._coordList.toCoordinateArray();
  25216. if (pts.length !== 4) return null;
  25217. this._triCoords.add(pts);
  25218. }
  25219. }
  25220. getTriangles() {
  25221. return this._triCoords;
  25222. }
  25223. get interfaces_() {
  25224. return [TriangleVisitor];
  25225. }
  25226. }
  25227. QuadEdgeSubdivision.TriangleCircumcentreVisitor = TriangleCircumcentreVisitor;
  25228. QuadEdgeSubdivision.TriangleEdgesListVisitor = TriangleEdgesListVisitor;
  25229. QuadEdgeSubdivision.TriangleVertexListVisitor = TriangleVertexListVisitor;
  25230. QuadEdgeSubdivision.TriangleCoordinatesVisitor = TriangleCoordinatesVisitor;
  25231. QuadEdgeSubdivision.EDGE_COINCIDENCE_TOL_FACTOR = 1000;
  25232. class Segment {
  25233. constructor() {
  25234. Segment.constructor_.apply(this, arguments);
  25235. }
  25236. static constructor_() {
  25237. this._ls = null;
  25238. this._data = null;
  25239. if (arguments.length === 2) {
  25240. const p0 = arguments[0],
  25241. p1 = arguments[1];
  25242. this._ls = new LineSegment(p0, p1);
  25243. } else if (arguments.length === 3) {
  25244. const p0 = arguments[0],
  25245. p1 = arguments[1],
  25246. data = arguments[2];
  25247. this._ls = new LineSegment(p0, p1);
  25248. this._data = data;
  25249. } else if (arguments.length === 6) {
  25250. const x1 = arguments[0],
  25251. y1 = arguments[1],
  25252. z1 = arguments[2],
  25253. x2 = arguments[3],
  25254. y2 = arguments[4],
  25255. z2 = arguments[5];
  25256. Segment.constructor_.call(this, new Coordinate(x1, y1, z1), new Coordinate(x2, y2, z2));
  25257. } else if (arguments.length === 7) {
  25258. const x1 = arguments[0],
  25259. y1 = arguments[1],
  25260. z1 = arguments[2],
  25261. x2 = arguments[3],
  25262. y2 = arguments[4],
  25263. z2 = arguments[5],
  25264. data = arguments[6];
  25265. Segment.constructor_.call(this, new Coordinate(x1, y1, z1), new Coordinate(x2, y2, z2), data);
  25266. }
  25267. }
  25268. getLineSegment() {
  25269. return this._ls;
  25270. }
  25271. getEndZ() {
  25272. const p = this._ls.getCoordinate(1);
  25273. return p.getZ();
  25274. }
  25275. getStartZ() {
  25276. const p = this._ls.getCoordinate(0);
  25277. return p.getZ();
  25278. }
  25279. intersection(s) {
  25280. return this._ls.intersection(s.getLineSegment());
  25281. }
  25282. getStart() {
  25283. return this._ls.getCoordinate(0);
  25284. }
  25285. getEnd() {
  25286. return this._ls.getCoordinate(1);
  25287. }
  25288. getEndY() {
  25289. const p = this._ls.getCoordinate(1);
  25290. return p.y;
  25291. }
  25292. getStartX() {
  25293. const p = this._ls.getCoordinate(0);
  25294. return p.x;
  25295. }
  25296. equalsTopo(s) {
  25297. return this._ls.equalsTopo(s.getLineSegment());
  25298. }
  25299. getStartY() {
  25300. const p = this._ls.getCoordinate(0);
  25301. return p.y;
  25302. }
  25303. setData(data) {
  25304. this._data = data;
  25305. }
  25306. getData() {
  25307. return this._data;
  25308. }
  25309. getEndX() {
  25310. const p = this._ls.getCoordinate(1);
  25311. return p.x;
  25312. }
  25313. toString() {
  25314. return this._ls.toString();
  25315. }
  25316. }
  25317. class ConstraintEnforcementException extends RuntimeException {
  25318. constructor() {
  25319. super();
  25320. ConstraintEnforcementException.constructor_.apply(this, arguments);
  25321. }
  25322. static constructor_() {
  25323. this._pt = null;
  25324. if (arguments.length === 1) {
  25325. const msg = arguments[0];
  25326. RuntimeException.constructor_.call(this, msg);
  25327. } else if (arguments.length === 2) {
  25328. const msg = arguments[0],
  25329. pt = arguments[1];
  25330. RuntimeException.constructor_.call(this, ConstraintEnforcementException.msgWithCoord(msg, pt));
  25331. this._pt = new Coordinate(pt);
  25332. }
  25333. }
  25334. static msgWithCoord(msg, pt) {
  25335. if (pt !== null) return msg + ' [ ' + WKTWriter.toPoint(pt) + ' ]';
  25336. return msg;
  25337. }
  25338. getCoordinate() {
  25339. return this._pt;
  25340. }
  25341. }
  25342. class ConformingDelaunayTriangulator {
  25343. constructor() {
  25344. ConformingDelaunayTriangulator.constructor_.apply(this, arguments);
  25345. }
  25346. static constructor_() {
  25347. this._initialVertices = null;
  25348. this._segVertices = null;
  25349. this._segments = new ArrayList();
  25350. this._subdiv = null;
  25351. this._incDel = null;
  25352. this._convexHull = null;
  25353. this._splitFinder = new NonEncroachingSplitPointFinder();
  25354. this._kdt = null;
  25355. this._vertexFactory = null;
  25356. this._computeAreaEnv = null;
  25357. this._splitPt = null;
  25358. this._tolerance = null;
  25359. const initialVertices = arguments[0],
  25360. tolerance = arguments[1];
  25361. this._initialVertices = new ArrayList(initialVertices);
  25362. this._tolerance = tolerance;
  25363. this._kdt = new KdTree(tolerance);
  25364. }
  25365. static computeVertexEnvelope(vertices) {
  25366. const env = new Envelope();
  25367. for (let i = vertices.iterator(); i.hasNext();) {
  25368. const v = i.next();
  25369. env.expandToInclude(v.getCoordinate());
  25370. }
  25371. return env;
  25372. }
  25373. getInitialVertices() {
  25374. return this._initialVertices;
  25375. }
  25376. getKDT() {
  25377. return this._kdt;
  25378. }
  25379. enforceConstraints() {
  25380. this.addConstraintVertices();
  25381. let count = 0;
  25382. let splits = 0;
  25383. do {
  25384. splits = this.enforceGabriel(this._segments);
  25385. count++;
  25386. } while (splits > 0 && count < ConformingDelaunayTriangulator.MAX_SPLIT_ITER);
  25387. if (count === ConformingDelaunayTriangulator.MAX_SPLIT_ITER) throw new ConstraintEnforcementException('Too many splitting iterations while enforcing constraints. Last split point was at: ', this._splitPt);
  25388. }
  25389. insertSites(vertices) {
  25390. for (let i = vertices.iterator(); i.hasNext();) {
  25391. const v = i.next();
  25392. this.insertSite(v);
  25393. }
  25394. }
  25395. getVertexFactory() {
  25396. return this._vertexFactory;
  25397. }
  25398. getPointArray() {
  25399. const pts = new Array(this._initialVertices.size() + this._segVertices.size()).fill(null);
  25400. let index = 0;
  25401. for (let i = this._initialVertices.iterator(); i.hasNext();) {
  25402. const v = i.next();
  25403. pts[index++] = v.getCoordinate();
  25404. }
  25405. for (let i2 = this._segVertices.iterator(); i2.hasNext();) {
  25406. const v = i2.next();
  25407. pts[index++] = v.getCoordinate();
  25408. }
  25409. return pts;
  25410. }
  25411. setConstraints(segments, segVertices) {
  25412. this._segments = segments;
  25413. this._segVertices = segVertices;
  25414. }
  25415. computeConvexHull() {
  25416. const fact = new GeometryFactory();
  25417. const coords = this.getPointArray();
  25418. const hull = new ConvexHull(coords, fact);
  25419. this._convexHull = hull.getConvexHull();
  25420. }
  25421. addConstraintVertices() {
  25422. this.computeConvexHull();
  25423. this.insertSites(this._segVertices);
  25424. }
  25425. findNonGabrielPoint(seg) {
  25426. const p = seg.getStart();
  25427. const q = seg.getEnd();
  25428. const midPt = new Coordinate((p.x + q.x) / 2.0, (p.y + q.y) / 2.0);
  25429. const segRadius = p.distance(midPt);
  25430. const env = new Envelope(midPt);
  25431. env.expandBy(segRadius);
  25432. const result = this._kdt.query(env);
  25433. let closestNonGabriel = null;
  25434. let minDist = Double.MAX_VALUE;
  25435. for (let i = result.iterator(); i.hasNext();) {
  25436. const nextNode = i.next();
  25437. const testPt = nextNode.getCoordinate();
  25438. if (testPt.equals2D(p) || testPt.equals2D(q)) continue;
  25439. const testRadius = midPt.distance(testPt);
  25440. if (testRadius < segRadius) {
  25441. const testDist = testRadius;
  25442. if (closestNonGabriel === null || testDist < minDist) {
  25443. closestNonGabriel = testPt;
  25444. minDist = testDist;
  25445. }
  25446. }
  25447. }
  25448. return closestNonGabriel;
  25449. }
  25450. getConstraintSegments() {
  25451. return this._segments;
  25452. }
  25453. setSplitPointFinder(splitFinder) {
  25454. this._splitFinder = splitFinder;
  25455. }
  25456. getConvexHull() {
  25457. return this._convexHull;
  25458. }
  25459. getTolerance() {
  25460. return this._tolerance;
  25461. }
  25462. enforceGabriel(segsToInsert) {
  25463. const newSegments = new ArrayList();
  25464. let splits = 0;
  25465. const segsToRemove = new ArrayList();
  25466. for (let i = segsToInsert.iterator(); i.hasNext();) {
  25467. const seg = i.next();
  25468. const encroachPt = this.findNonGabrielPoint(seg);
  25469. if (encroachPt === null) continue;
  25470. this._splitPt = this._splitFinder.findSplitPoint(seg, encroachPt);
  25471. const splitVertex = this.createVertex(this._splitPt, seg);
  25472. const insertedVertex = this.insertSite(splitVertex);
  25473. if (!insertedVertex.getCoordinate().equals2D(this._splitPt)) ;
  25474. const s1 = new Segment(seg.getStartX(), seg.getStartY(), seg.getStartZ(), splitVertex.getX(), splitVertex.getY(), splitVertex.getZ(), seg.getData());
  25475. const s2 = new Segment(splitVertex.getX(), splitVertex.getY(), splitVertex.getZ(), seg.getEndX(), seg.getEndY(), seg.getEndZ(), seg.getData());
  25476. newSegments.add(s1);
  25477. newSegments.add(s2);
  25478. segsToRemove.add(seg);
  25479. splits = splits + 1;
  25480. }
  25481. segsToInsert.removeAll(segsToRemove);
  25482. segsToInsert.addAll(newSegments);
  25483. return splits;
  25484. }
  25485. createVertex() {
  25486. if (arguments.length === 1) {
  25487. const p = arguments[0];
  25488. let v = null;
  25489. if (this._vertexFactory !== null) v = this._vertexFactory.createVertex(p, null);else v = new ConstraintVertex(p);
  25490. return v;
  25491. } else if (arguments.length === 2) {
  25492. const p = arguments[0],
  25493. seg = arguments[1];
  25494. let v = null;
  25495. if (this._vertexFactory !== null) v = this._vertexFactory.createVertex(p, seg);else v = new ConstraintVertex(p);
  25496. v.setOnConstraint(true);
  25497. return v;
  25498. }
  25499. }
  25500. getSubdivision() {
  25501. return this._subdiv;
  25502. }
  25503. computeBoundingBox() {
  25504. const vertexEnv = ConformingDelaunayTriangulator.computeVertexEnvelope(this._initialVertices);
  25505. const segEnv = ConformingDelaunayTriangulator.computeVertexEnvelope(this._segVertices);
  25506. const allPointsEnv = new Envelope(vertexEnv);
  25507. allPointsEnv.expandToInclude(segEnv);
  25508. const deltaX = allPointsEnv.getWidth() * 0.2;
  25509. const deltaY = allPointsEnv.getHeight() * 0.2;
  25510. const delta = Math.max(deltaX, deltaY);
  25511. this._computeAreaEnv = new Envelope(allPointsEnv);
  25512. this._computeAreaEnv.expandBy(delta);
  25513. }
  25514. setVertexFactory(vertexFactory) {
  25515. this._vertexFactory = vertexFactory;
  25516. }
  25517. formInitialDelaunay() {
  25518. this.computeBoundingBox();
  25519. this._subdiv = new QuadEdgeSubdivision(this._computeAreaEnv, this._tolerance);
  25520. this._subdiv.setLocator(new LastFoundQuadEdgeLocator(this._subdiv));
  25521. this._incDel = new IncrementalDelaunayTriangulator(this._subdiv);
  25522. this.insertSites(this._initialVertices);
  25523. }
  25524. insertSite() {
  25525. if (arguments[0] instanceof ConstraintVertex) {
  25526. const v = arguments[0];
  25527. const kdnode = this._kdt.insert(v.getCoordinate(), v);
  25528. if (!kdnode.isRepeated()) {
  25529. this._incDel.insertSite(v);
  25530. } else {
  25531. const snappedV = kdnode.getData();
  25532. snappedV.merge(v);
  25533. return snappedV;
  25534. }
  25535. return v;
  25536. } else if (arguments[0] instanceof Coordinate) {
  25537. const p = arguments[0];
  25538. this.insertSite(this.createVertex(p));
  25539. }
  25540. }
  25541. }
  25542. ConformingDelaunayTriangulator.MAX_SPLIT_ITER = 99;
  25543. class DelaunayTriangulationBuilder {
  25544. constructor() {
  25545. DelaunayTriangulationBuilder.constructor_.apply(this, arguments);
  25546. }
  25547. static constructor_() {
  25548. this._siteCoords = null;
  25549. this._tolerance = 0.0;
  25550. this._subdiv = null;
  25551. }
  25552. static extractUniqueCoordinates(geom) {
  25553. if (geom === null) return new CoordinateList();
  25554. const coords = geom.getCoordinates();
  25555. return DelaunayTriangulationBuilder.unique(coords);
  25556. }
  25557. static envelope(coords) {
  25558. const env = new Envelope();
  25559. for (let i = coords.iterator(); i.hasNext();) {
  25560. const coord = i.next();
  25561. env.expandToInclude(coord);
  25562. }
  25563. return env;
  25564. }
  25565. static unique(coords) {
  25566. const coordsCopy = CoordinateArrays.copyDeep(coords);
  25567. Arrays.sort(coordsCopy);
  25568. const coordList = new CoordinateList(coordsCopy, false);
  25569. return coordList;
  25570. }
  25571. static toVertices(coords) {
  25572. const verts = new ArrayList();
  25573. for (let i = coords.iterator(); i.hasNext();) {
  25574. const coord = i.next();
  25575. verts.add(new Vertex(coord));
  25576. }
  25577. return verts;
  25578. }
  25579. create() {
  25580. if (this._subdiv !== null) return null;
  25581. const siteEnv = DelaunayTriangulationBuilder.envelope(this._siteCoords);
  25582. const vertices = DelaunayTriangulationBuilder.toVertices(this._siteCoords);
  25583. this._subdiv = new QuadEdgeSubdivision(siteEnv, this._tolerance);
  25584. const triangulator = new IncrementalDelaunayTriangulator(this._subdiv);
  25585. triangulator.insertSites(vertices);
  25586. }
  25587. setTolerance(tolerance) {
  25588. this._tolerance = tolerance;
  25589. }
  25590. setSites() {
  25591. if (arguments[0] instanceof Geometry) {
  25592. const geom = arguments[0];
  25593. this._siteCoords = DelaunayTriangulationBuilder.extractUniqueCoordinates(geom);
  25594. } else if (hasInterface(arguments[0], Collection)) {
  25595. const coords = arguments[0];
  25596. this._siteCoords = DelaunayTriangulationBuilder.unique(CoordinateArrays.toCoordinateArray(coords));
  25597. }
  25598. }
  25599. getEdges(geomFact) {
  25600. this.create();
  25601. return this._subdiv.getEdges(geomFact);
  25602. }
  25603. getSubdivision() {
  25604. this.create();
  25605. return this._subdiv;
  25606. }
  25607. getTriangles(geomFact) {
  25608. this.create();
  25609. return this._subdiv.getTriangles(geomFact);
  25610. }
  25611. }
  25612. class ConformingDelaunayTriangulationBuilder {
  25613. constructor() {
  25614. ConformingDelaunayTriangulationBuilder.constructor_.apply(this, arguments);
  25615. }
  25616. static constructor_() {
  25617. this._siteCoords = null;
  25618. this._constraintLines = null;
  25619. this._tolerance = 0.0;
  25620. this._subdiv = null;
  25621. this._constraintVertexMap = new TreeMap();
  25622. }
  25623. static createConstraintSegments() {
  25624. if (arguments.length === 1) {
  25625. const geom = arguments[0];
  25626. const lines = LinearComponentExtracter.getLines(geom);
  25627. const constraintSegs = new ArrayList();
  25628. for (let i = lines.iterator(); i.hasNext();) {
  25629. const line = i.next();
  25630. ConformingDelaunayTriangulationBuilder.createConstraintSegments(line, constraintSegs);
  25631. }
  25632. return constraintSegs;
  25633. } else if (arguments.length === 2) {
  25634. const line = arguments[0],
  25635. constraintSegs = arguments[1];
  25636. const coords = line.getCoordinates();
  25637. for (let i = 1; i < coords.length; i++) constraintSegs.add(new Segment(coords[i - 1], coords[i]));
  25638. }
  25639. }
  25640. createSiteVertices(coords) {
  25641. const verts = new ArrayList();
  25642. for (let i = coords.iterator(); i.hasNext();) {
  25643. const coord = i.next();
  25644. if (this._constraintVertexMap.containsKey(coord)) continue;
  25645. verts.add(new ConstraintVertex(coord));
  25646. }
  25647. return verts;
  25648. }
  25649. create() {
  25650. if (this._subdiv !== null) return null;
  25651. const siteEnv = DelaunayTriangulationBuilder.envelope(this._siteCoords);
  25652. let segments = new ArrayList();
  25653. if (this._constraintLines !== null) {
  25654. siteEnv.expandToInclude(this._constraintLines.getEnvelopeInternal());
  25655. this.createVertices(this._constraintLines);
  25656. segments = ConformingDelaunayTriangulationBuilder.createConstraintSegments(this._constraintLines);
  25657. }
  25658. const sites = this.createSiteVertices(this._siteCoords);
  25659. const cdt = new ConformingDelaunayTriangulator(sites, this._tolerance);
  25660. cdt.setConstraints(segments, new ArrayList(this._constraintVertexMap.values()));
  25661. cdt.formInitialDelaunay();
  25662. cdt.enforceConstraints();
  25663. this._subdiv = cdt.getSubdivision();
  25664. }
  25665. setTolerance(tolerance) {
  25666. this._tolerance = tolerance;
  25667. }
  25668. setConstraints(constraintLines) {
  25669. this._constraintLines = constraintLines;
  25670. }
  25671. setSites(geom) {
  25672. this._siteCoords = DelaunayTriangulationBuilder.extractUniqueCoordinates(geom);
  25673. }
  25674. getEdges(geomFact) {
  25675. this.create();
  25676. return this._subdiv.getEdges(geomFact);
  25677. }
  25678. getSubdivision() {
  25679. this.create();
  25680. return this._subdiv;
  25681. }
  25682. getTriangles(geomFact) {
  25683. this.create();
  25684. return this._subdiv.getTriangles(geomFact);
  25685. }
  25686. createVertices(geom) {
  25687. const coords = geom.getCoordinates();
  25688. for (let i = 0; i < coords.length; i++) {
  25689. const v = new ConstraintVertex(coords[i]);
  25690. this._constraintVertexMap.put(coords[i], v);
  25691. }
  25692. }
  25693. }
  25694. class VoronoiDiagramBuilder {
  25695. constructor() {
  25696. VoronoiDiagramBuilder.constructor_.apply(this, arguments);
  25697. }
  25698. static constructor_() {
  25699. this._siteCoords = null;
  25700. this._tolerance = 0.0;
  25701. this._subdiv = null;
  25702. this._clipEnv = null;
  25703. this._diagramEnv = null;
  25704. }
  25705. static clipGeometryCollection(geom, clipEnv) {
  25706. const clipPoly = geom.getFactory().toGeometry(clipEnv);
  25707. const clipped = new ArrayList();
  25708. for (let i = 0; i < geom.getNumGeometries(); i++) {
  25709. const g = geom.getGeometryN(i);
  25710. let result = null;
  25711. if (clipEnv.contains(g.getEnvelopeInternal())) {
  25712. result = g;
  25713. } else if (clipEnv.intersects(g.getEnvelopeInternal())) {
  25714. result = OverlayOp.intersection(clipPoly, g);
  25715. result.setUserData(g.getUserData());
  25716. }
  25717. if (result !== null && !result.isEmpty()) clipped.add(result);
  25718. }
  25719. return geom.getFactory().createGeometryCollection(GeometryFactory.toGeometryArray(clipped));
  25720. }
  25721. create() {
  25722. if (this._subdiv !== null) return null;
  25723. const siteEnv = DelaunayTriangulationBuilder.envelope(this._siteCoords);
  25724. this._diagramEnv = this._clipEnv;
  25725. if (this._diagramEnv === null) {
  25726. this._diagramEnv = siteEnv;
  25727. const expandBy = this._diagramEnv.getDiameter();
  25728. this._diagramEnv.expandBy(expandBy);
  25729. }
  25730. const vertices = DelaunayTriangulationBuilder.toVertices(this._siteCoords);
  25731. this._subdiv = new QuadEdgeSubdivision(siteEnv, this._tolerance);
  25732. const triangulator = new IncrementalDelaunayTriangulator(this._subdiv);
  25733. triangulator.insertSites(vertices);
  25734. }
  25735. getDiagram(geomFact) {
  25736. this.create();
  25737. const polys = this._subdiv.getVoronoiDiagram(geomFact);
  25738. return VoronoiDiagramBuilder.clipGeometryCollection(polys, this._diagramEnv);
  25739. }
  25740. setTolerance(tolerance) {
  25741. this._tolerance = tolerance;
  25742. }
  25743. setSites() {
  25744. if (arguments[0] instanceof Geometry) {
  25745. const geom = arguments[0];
  25746. this._siteCoords = DelaunayTriangulationBuilder.extractUniqueCoordinates(geom);
  25747. } else if (hasInterface(arguments[0], Collection)) {
  25748. const coords = arguments[0];
  25749. this._siteCoords = DelaunayTriangulationBuilder.unique(CoordinateArrays.toCoordinateArray(coords));
  25750. }
  25751. }
  25752. setClipEnvelope(clipEnv) {
  25753. this._clipEnv = clipEnv;
  25754. }
  25755. getSubdivision() {
  25756. this.create();
  25757. return this._subdiv;
  25758. }
  25759. }
  25760. var quadedge = /*#__PURE__*/Object.freeze({
  25761. __proto__: null,
  25762. Vertex: Vertex
  25763. });
  25764. var triangulate = /*#__PURE__*/Object.freeze({
  25765. __proto__: null,
  25766. ConformingDelaunayTriangulationBuilder: ConformingDelaunayTriangulationBuilder,
  25767. DelaunayTriangulationBuilder: DelaunayTriangulationBuilder,
  25768. VoronoiDiagramBuilder: VoronoiDiagramBuilder,
  25769. quadedge: quadedge
  25770. });
  25771. class LinearIterator {
  25772. constructor() {
  25773. LinearIterator.constructor_.apply(this, arguments);
  25774. }
  25775. static constructor_() {
  25776. this._linearGeom = null;
  25777. this._numLines = null;
  25778. this._currentLine = null;
  25779. this._componentIndex = 0;
  25780. this._vertexIndex = 0;
  25781. if (arguments.length === 1) {
  25782. const linear = arguments[0];
  25783. LinearIterator.constructor_.call(this, linear, 0, 0);
  25784. } else if (arguments.length === 2) {
  25785. const linear = arguments[0],
  25786. start = arguments[1];
  25787. LinearIterator.constructor_.call(this, linear, start.getComponentIndex(), LinearIterator.segmentEndVertexIndex(start));
  25788. } else if (arguments.length === 3) {
  25789. const linearGeom = arguments[0],
  25790. componentIndex = arguments[1],
  25791. vertexIndex = arguments[2];
  25792. if (!hasInterface(linearGeom, Lineal)) throw new IllegalArgumentException('Lineal geometry is required');
  25793. this._linearGeom = linearGeom;
  25794. this._numLines = linearGeom.getNumGeometries();
  25795. this._componentIndex = componentIndex;
  25796. this._vertexIndex = vertexIndex;
  25797. this.loadCurrentLine();
  25798. }
  25799. }
  25800. static segmentEndVertexIndex(loc) {
  25801. if (loc.getSegmentFraction() > 0.0) return loc.getSegmentIndex() + 1;
  25802. return loc.getSegmentIndex();
  25803. }
  25804. getComponentIndex() {
  25805. return this._componentIndex;
  25806. }
  25807. getLine() {
  25808. return this._currentLine;
  25809. }
  25810. getVertexIndex() {
  25811. return this._vertexIndex;
  25812. }
  25813. getSegmentEnd() {
  25814. if (this._vertexIndex < this.getLine().getNumPoints() - 1) return this._currentLine.getCoordinateN(this._vertexIndex + 1);
  25815. return null;
  25816. }
  25817. next() {
  25818. if (!this.hasNext()) return null;
  25819. this._vertexIndex++;
  25820. if (this._vertexIndex >= this._currentLine.getNumPoints()) {
  25821. this._componentIndex++;
  25822. this.loadCurrentLine();
  25823. this._vertexIndex = 0;
  25824. }
  25825. }
  25826. loadCurrentLine() {
  25827. if (this._componentIndex >= this._numLines) {
  25828. this._currentLine = null;
  25829. return null;
  25830. }
  25831. this._currentLine = this._linearGeom.getGeometryN(this._componentIndex);
  25832. }
  25833. getSegmentStart() {
  25834. return this._currentLine.getCoordinateN(this._vertexIndex);
  25835. }
  25836. isEndOfLine() {
  25837. if (this._componentIndex >= this._numLines) return false;
  25838. if (this._vertexIndex < this._currentLine.getNumPoints() - 1) return false;
  25839. return true;
  25840. }
  25841. hasNext() {
  25842. if (this._componentIndex >= this._numLines) return false;
  25843. if (this._componentIndex === this._numLines - 1 && this._vertexIndex >= this._currentLine.getNumPoints()) return false;
  25844. return true;
  25845. }
  25846. }
  25847. class LengthIndexOfPoint {
  25848. constructor() {
  25849. LengthIndexOfPoint.constructor_.apply(this, arguments);
  25850. }
  25851. static constructor_() {
  25852. this._linearGeom = null;
  25853. const linearGeom = arguments[0];
  25854. this._linearGeom = linearGeom;
  25855. }
  25856. static indexOf(linearGeom, inputPt) {
  25857. const locater = new LengthIndexOfPoint(linearGeom);
  25858. return locater.indexOf(inputPt);
  25859. }
  25860. static indexOfAfter(linearGeom, inputPt, minIndex) {
  25861. const locater = new LengthIndexOfPoint(linearGeom);
  25862. return locater.indexOfAfter(inputPt, minIndex);
  25863. }
  25864. indexOf(inputPt) {
  25865. return this.indexOfFromStart(inputPt, -1.0);
  25866. }
  25867. indexOfFromStart(inputPt, minIndex) {
  25868. let minDistance = Double.MAX_VALUE;
  25869. let ptMeasure = minIndex;
  25870. let segmentStartMeasure = 0.0;
  25871. const seg = new LineSegment();
  25872. const it = new LinearIterator(this._linearGeom);
  25873. while (it.hasNext()) {
  25874. if (!it.isEndOfLine()) {
  25875. seg.p0 = it.getSegmentStart();
  25876. seg.p1 = it.getSegmentEnd();
  25877. const segDistance = seg.distance(inputPt);
  25878. const segMeasureToPt = this.segmentNearestMeasure(seg, inputPt, segmentStartMeasure);
  25879. if (segDistance < minDistance && segMeasureToPt > minIndex) {
  25880. ptMeasure = segMeasureToPt;
  25881. minDistance = segDistance;
  25882. }
  25883. segmentStartMeasure += seg.getLength();
  25884. }
  25885. it.next();
  25886. }
  25887. return ptMeasure;
  25888. }
  25889. indexOfAfter(inputPt, minIndex) {
  25890. if (minIndex < 0.0) return this.indexOf(inputPt);
  25891. const endIndex = this._linearGeom.getLength();
  25892. if (endIndex < minIndex) return endIndex;
  25893. const closestAfter = this.indexOfFromStart(inputPt, minIndex);
  25894. Assert.isTrue(closestAfter >= minIndex, 'computed index is before specified minimum index');
  25895. return closestAfter;
  25896. }
  25897. segmentNearestMeasure(seg, inputPt, segmentStartMeasure) {
  25898. const projFactor = seg.projectionFactor(inputPt);
  25899. if (projFactor <= 0.0) return segmentStartMeasure;
  25900. if (projFactor <= 1.0) return segmentStartMeasure + projFactor * seg.getLength();
  25901. return segmentStartMeasure + seg.getLength();
  25902. }
  25903. }
  25904. class LinearLocation {
  25905. constructor() {
  25906. LinearLocation.constructor_.apply(this, arguments);
  25907. }
  25908. static constructor_() {
  25909. this._componentIndex = 0;
  25910. this._segmentIndex = 0;
  25911. this._segmentFraction = 0.0;
  25912. if (arguments.length === 0) ; else if (arguments.length === 1) {
  25913. const loc = arguments[0];
  25914. this._componentIndex = loc._componentIndex;
  25915. this._segmentIndex = loc._segmentIndex;
  25916. this._segmentFraction = loc._segmentFraction;
  25917. } else if (arguments.length === 2) {
  25918. const segmentIndex = arguments[0],
  25919. segmentFraction = arguments[1];
  25920. LinearLocation.constructor_.call(this, 0, segmentIndex, segmentFraction);
  25921. } else if (arguments.length === 3) {
  25922. const componentIndex = arguments[0],
  25923. segmentIndex = arguments[1],
  25924. segmentFraction = arguments[2];
  25925. this._componentIndex = componentIndex;
  25926. this._segmentIndex = segmentIndex;
  25927. this._segmentFraction = segmentFraction;
  25928. this.normalize();
  25929. } else if (arguments.length === 4) {
  25930. const componentIndex = arguments[0],
  25931. segmentIndex = arguments[1],
  25932. segmentFraction = arguments[2],
  25933. doNormalize = arguments[3];
  25934. this._componentIndex = componentIndex;
  25935. this._segmentIndex = segmentIndex;
  25936. this._segmentFraction = segmentFraction;
  25937. if (doNormalize) this.normalize();
  25938. }
  25939. }
  25940. static getEndLocation(linear) {
  25941. const loc = new LinearLocation();
  25942. loc.setToEnd(linear);
  25943. return loc;
  25944. }
  25945. static pointAlongSegmentByFraction(p0, p1, frac) {
  25946. if (frac <= 0.0) return p0;
  25947. if (frac >= 1.0) return p1;
  25948. const x = (p1.x - p0.x) * frac + p0.x;
  25949. const y = (p1.y - p0.y) * frac + p0.y;
  25950. const z = (p1.getZ() - p0.getZ()) * frac + p0.getZ();
  25951. return new Coordinate(x, y, z);
  25952. }
  25953. static compareLocationValues(componentIndex0, segmentIndex0, segmentFraction0, componentIndex1, segmentIndex1, segmentFraction1) {
  25954. if (componentIndex0 < componentIndex1) return -1;
  25955. if (componentIndex0 > componentIndex1) return 1;
  25956. if (segmentIndex0 < segmentIndex1) return -1;
  25957. if (segmentIndex0 > segmentIndex1) return 1;
  25958. if (segmentFraction0 < segmentFraction1) return -1;
  25959. if (segmentFraction0 > segmentFraction1) return 1;
  25960. return 0;
  25961. }
  25962. static numSegments(line) {
  25963. const npts = line.getNumPoints();
  25964. if (npts <= 1) return 0;
  25965. return npts - 1;
  25966. }
  25967. getSegmentIndex() {
  25968. return this._segmentIndex;
  25969. }
  25970. getComponentIndex() {
  25971. return this._componentIndex;
  25972. }
  25973. isEndpoint(linearGeom) {
  25974. const lineComp = linearGeom.getGeometryN(this._componentIndex);
  25975. const nseg = LinearLocation.numSegments(lineComp);
  25976. return this._segmentIndex >= nseg || this._segmentIndex === nseg - 1 && this._segmentFraction >= 1.0;
  25977. }
  25978. isValid(linearGeom) {
  25979. if (this._componentIndex < 0 || this._componentIndex >= linearGeom.getNumGeometries()) return false;
  25980. const lineComp = linearGeom.getGeometryN(this._componentIndex);
  25981. if (this._segmentIndex < 0 || this._segmentIndex > lineComp.getNumPoints()) return false;
  25982. if (this._segmentIndex === lineComp.getNumPoints() && this._segmentFraction !== 0.0) return false;
  25983. if (this._segmentFraction < 0.0 || this._segmentFraction > 1.0) return false;
  25984. return true;
  25985. }
  25986. normalize() {
  25987. if (this._segmentFraction < 0.0) this._segmentFraction = 0.0;
  25988. if (this._segmentFraction > 1.0) this._segmentFraction = 1.0;
  25989. if (this._componentIndex < 0) {
  25990. this._componentIndex = 0;
  25991. this._segmentIndex = 0;
  25992. this._segmentFraction = 0.0;
  25993. }
  25994. if (this._segmentIndex < 0) {
  25995. this._segmentIndex = 0;
  25996. this._segmentFraction = 0.0;
  25997. }
  25998. if (this._segmentFraction === 1.0) {
  25999. this._segmentFraction = 0.0;
  26000. this._segmentIndex += 1;
  26001. }
  26002. }
  26003. toLowest(linearGeom) {
  26004. const lineComp = linearGeom.getGeometryN(this._componentIndex);
  26005. const nseg = LinearLocation.numSegments(lineComp);
  26006. if (this._segmentIndex < nseg) return this;
  26007. return new LinearLocation(this._componentIndex, nseg - 1, 1.0, false);
  26008. }
  26009. getCoordinate(linearGeom) {
  26010. const lineComp = linearGeom.getGeometryN(this._componentIndex);
  26011. const p0 = lineComp.getCoordinateN(this._segmentIndex);
  26012. if (this._segmentIndex >= LinearLocation.numSegments(lineComp)) return p0;
  26013. const p1 = lineComp.getCoordinateN(this._segmentIndex + 1);
  26014. return LinearLocation.pointAlongSegmentByFraction(p0, p1, this._segmentFraction);
  26015. }
  26016. getSegmentFraction() {
  26017. return this._segmentFraction;
  26018. }
  26019. getSegment(linearGeom) {
  26020. const lineComp = linearGeom.getGeometryN(this._componentIndex);
  26021. const p0 = lineComp.getCoordinateN(this._segmentIndex);
  26022. if (this._segmentIndex >= LinearLocation.numSegments(lineComp)) {
  26023. const prev = lineComp.getCoordinateN(lineComp.getNumPoints() - 2);
  26024. return new LineSegment(prev, p0);
  26025. }
  26026. const p1 = lineComp.getCoordinateN(this._segmentIndex + 1);
  26027. return new LineSegment(p0, p1);
  26028. }
  26029. clamp(linear) {
  26030. if (this._componentIndex >= linear.getNumGeometries()) {
  26031. this.setToEnd(linear);
  26032. return null;
  26033. }
  26034. if (this._segmentIndex >= linear.getNumPoints()) {
  26035. const line = linear.getGeometryN(this._componentIndex);
  26036. this._segmentIndex = LinearLocation.numSegments(line);
  26037. this._segmentFraction = 1.0;
  26038. }
  26039. }
  26040. setToEnd(linear) {
  26041. this._componentIndex = linear.getNumGeometries() - 1;
  26042. const lastLine = linear.getGeometryN(this._componentIndex);
  26043. this._segmentIndex = LinearLocation.numSegments(lastLine);
  26044. this._segmentFraction = 0.0;
  26045. }
  26046. compareTo(o) {
  26047. const other = o;
  26048. if (this._componentIndex < other._componentIndex) return -1;
  26049. if (this._componentIndex > other._componentIndex) return 1;
  26050. if (this._segmentIndex < other._segmentIndex) return -1;
  26051. if (this._segmentIndex > other._segmentIndex) return 1;
  26052. if (this._segmentFraction < other._segmentFraction) return -1;
  26053. if (this._segmentFraction > other._segmentFraction) return 1;
  26054. return 0;
  26055. }
  26056. copy() {
  26057. return new LinearLocation(this._componentIndex, this._segmentIndex, this._segmentFraction);
  26058. }
  26059. toString() {
  26060. return 'LinearLoc[' + this._componentIndex + ', ' + this._segmentIndex + ', ' + this._segmentFraction + ']';
  26061. }
  26062. isOnSameSegment(loc) {
  26063. if (this._componentIndex !== loc._componentIndex) return false;
  26064. if (this._segmentIndex === loc._segmentIndex) return true;
  26065. if (loc._segmentIndex - this._segmentIndex === 1 && loc._segmentFraction === 0.0) return true;
  26066. if (this._segmentIndex - loc._segmentIndex === 1 && this._segmentFraction === 0.0) return true;
  26067. return false;
  26068. }
  26069. snapToVertex(linearGeom, minDistance) {
  26070. if (this._segmentFraction <= 0.0 || this._segmentFraction >= 1.0) return null;
  26071. const segLen = this.getSegmentLength(linearGeom);
  26072. const lenToStart = this._segmentFraction * segLen;
  26073. const lenToEnd = segLen - lenToStart;
  26074. if (lenToStart <= lenToEnd && lenToStart < minDistance) this._segmentFraction = 0.0;else if (lenToEnd <= lenToStart && lenToEnd < minDistance) this._segmentFraction = 1.0;
  26075. }
  26076. compareLocationValues(componentIndex1, segmentIndex1, segmentFraction1) {
  26077. if (this._componentIndex < componentIndex1) return -1;
  26078. if (this._componentIndex > componentIndex1) return 1;
  26079. if (this._segmentIndex < segmentIndex1) return -1;
  26080. if (this._segmentIndex > segmentIndex1) return 1;
  26081. if (this._segmentFraction < segmentFraction1) return -1;
  26082. if (this._segmentFraction > segmentFraction1) return 1;
  26083. return 0;
  26084. }
  26085. getSegmentLength(linearGeom) {
  26086. const lineComp = linearGeom.getGeometryN(this._componentIndex);
  26087. let segIndex = this._segmentIndex;
  26088. if (this._segmentIndex >= LinearLocation.numSegments(lineComp)) segIndex = lineComp.getNumPoints() - 2;
  26089. const p0 = lineComp.getCoordinateN(segIndex);
  26090. const p1 = lineComp.getCoordinateN(segIndex + 1);
  26091. return p0.distance(p1);
  26092. }
  26093. isVertex() {
  26094. return this._segmentFraction <= 0.0 || this._segmentFraction >= 1.0;
  26095. }
  26096. get interfaces_() {
  26097. return [Comparable];
  26098. }
  26099. }
  26100. class LocationIndexOfPoint {
  26101. constructor() {
  26102. LocationIndexOfPoint.constructor_.apply(this, arguments);
  26103. }
  26104. static constructor_() {
  26105. this._linearGeom = null;
  26106. const linearGeom = arguments[0];
  26107. this._linearGeom = linearGeom;
  26108. }
  26109. static indexOf(linearGeom, inputPt) {
  26110. const locater = new LocationIndexOfPoint(linearGeom);
  26111. return locater.indexOf(inputPt);
  26112. }
  26113. static indexOfAfter(linearGeom, inputPt, minIndex) {
  26114. const locater = new LocationIndexOfPoint(linearGeom);
  26115. return locater.indexOfAfter(inputPt, minIndex);
  26116. }
  26117. indexOf(inputPt) {
  26118. return this.indexOfFromStart(inputPt, null);
  26119. }
  26120. indexOfFromStart(inputPt, minIndex) {
  26121. let minDistance = Double.MAX_VALUE;
  26122. let minComponentIndex = 0;
  26123. let minSegmentIndex = 0;
  26124. let minFrac = -1.0;
  26125. const seg = new LineSegment();
  26126. for (let it = new LinearIterator(this._linearGeom); it.hasNext(); it.next()) if (!it.isEndOfLine()) {
  26127. seg.p0 = it.getSegmentStart();
  26128. seg.p1 = it.getSegmentEnd();
  26129. const segDistance = seg.distance(inputPt);
  26130. const segFrac = seg.segmentFraction(inputPt);
  26131. const candidateComponentIndex = it.getComponentIndex();
  26132. const candidateSegmentIndex = it.getVertexIndex();
  26133. if (segDistance < minDistance) if (minIndex === null || minIndex.compareLocationValues(candidateComponentIndex, candidateSegmentIndex, segFrac) < 0) {
  26134. minComponentIndex = candidateComponentIndex;
  26135. minSegmentIndex = candidateSegmentIndex;
  26136. minFrac = segFrac;
  26137. minDistance = segDistance;
  26138. }
  26139. }
  26140. if (minDistance === Double.MAX_VALUE) return new LinearLocation(minIndex);
  26141. const loc = new LinearLocation(minComponentIndex, minSegmentIndex, minFrac);
  26142. return loc;
  26143. }
  26144. indexOfAfter(inputPt, minIndex) {
  26145. if (minIndex === null) return this.indexOf(inputPt);
  26146. const endLoc = LinearLocation.getEndLocation(this._linearGeom);
  26147. if (endLoc.compareTo(minIndex) <= 0) return endLoc;
  26148. const closestAfter = this.indexOfFromStart(inputPt, minIndex);
  26149. Assert.isTrue(closestAfter.compareTo(minIndex) >= 0, 'computed location is before specified minimum location');
  26150. return closestAfter;
  26151. }
  26152. }
  26153. class LocationIndexOfLine {
  26154. constructor() {
  26155. LocationIndexOfLine.constructor_.apply(this, arguments);
  26156. }
  26157. static constructor_() {
  26158. this._linearGeom = null;
  26159. const linearGeom = arguments[0];
  26160. this._linearGeom = linearGeom;
  26161. }
  26162. static indicesOf(linearGeom, subLine) {
  26163. const locater = new LocationIndexOfLine(linearGeom);
  26164. return locater.indicesOf(subLine);
  26165. }
  26166. indicesOf(subLine) {
  26167. const startPt = subLine.getGeometryN(0).getCoordinateN(0);
  26168. const lastLine = subLine.getGeometryN(subLine.getNumGeometries() - 1);
  26169. const endPt = lastLine.getCoordinateN(lastLine.getNumPoints() - 1);
  26170. const locPt = new LocationIndexOfPoint(this._linearGeom);
  26171. const subLineLoc = new Array(2).fill(null);
  26172. subLineLoc[0] = locPt.indexOf(startPt);
  26173. if (subLine.getLength() === 0.0) subLineLoc[1] = subLineLoc[0].copy();else subLineLoc[1] = locPt.indexOfAfter(endPt, subLineLoc[0]);
  26174. return subLineLoc;
  26175. }
  26176. }
  26177. class LengthLocationMap {
  26178. constructor() {
  26179. LengthLocationMap.constructor_.apply(this, arguments);
  26180. }
  26181. static constructor_() {
  26182. this._linearGeom = null;
  26183. const linearGeom = arguments[0];
  26184. this._linearGeom = linearGeom;
  26185. }
  26186. static getLength(linearGeom, loc) {
  26187. const locater = new LengthLocationMap(linearGeom);
  26188. return locater.getLength(loc);
  26189. }
  26190. static getLocation() {
  26191. if (arguments.length === 2) {
  26192. const linearGeom = arguments[0],
  26193. length = arguments[1];
  26194. const locater = new LengthLocationMap(linearGeom);
  26195. return locater.getLocation(length);
  26196. } else if (arguments.length === 3) {
  26197. const linearGeom = arguments[0],
  26198. length = arguments[1],
  26199. resolveLower = arguments[2];
  26200. const locater = new LengthLocationMap(linearGeom);
  26201. return locater.getLocation(length, resolveLower);
  26202. }
  26203. }
  26204. getLength(loc) {
  26205. let totalLength = 0.0;
  26206. const it = new LinearIterator(this._linearGeom);
  26207. while (it.hasNext()) {
  26208. if (!it.isEndOfLine()) {
  26209. const p0 = it.getSegmentStart();
  26210. const p1 = it.getSegmentEnd();
  26211. const segLen = p1.distance(p0);
  26212. if (loc.getComponentIndex() === it.getComponentIndex() && loc.getSegmentIndex() === it.getVertexIndex()) return totalLength + segLen * loc.getSegmentFraction();
  26213. totalLength += segLen;
  26214. }
  26215. it.next();
  26216. }
  26217. return totalLength;
  26218. }
  26219. resolveHigher(loc) {
  26220. if (!loc.isEndpoint(this._linearGeom)) return loc;
  26221. let compIndex = loc.getComponentIndex();
  26222. if (compIndex >= this._linearGeom.getNumGeometries() - 1) return loc;
  26223. do compIndex++; while (compIndex < this._linearGeom.getNumGeometries() - 1 && this._linearGeom.getGeometryN(compIndex).getLength() === 0);
  26224. return new LinearLocation(compIndex, 0, 0.0);
  26225. }
  26226. getLocation() {
  26227. if (arguments.length === 1) {
  26228. const length = arguments[0];
  26229. return this.getLocation(length, true);
  26230. } else if (arguments.length === 2) {
  26231. const length = arguments[0],
  26232. resolveLower = arguments[1];
  26233. let forwardLength = length;
  26234. if (length < 0.0) {
  26235. const lineLen = this._linearGeom.getLength();
  26236. forwardLength = lineLen + length;
  26237. }
  26238. const loc = this.getLocationForward(forwardLength);
  26239. if (resolveLower) return loc;
  26240. return this.resolveHigher(loc);
  26241. }
  26242. }
  26243. getLocationForward(length) {
  26244. if (length <= 0.0) return new LinearLocation();
  26245. let totalLength = 0.0;
  26246. const it = new LinearIterator(this._linearGeom);
  26247. while (it.hasNext()) {
  26248. if (it.isEndOfLine()) {
  26249. if (totalLength === length) {
  26250. const compIndex = it.getComponentIndex();
  26251. const segIndex = it.getVertexIndex();
  26252. return new LinearLocation(compIndex, segIndex, 0.0);
  26253. }
  26254. } else {
  26255. const p0 = it.getSegmentStart();
  26256. const p1 = it.getSegmentEnd();
  26257. const segLen = p1.distance(p0);
  26258. if (totalLength + segLen > length) {
  26259. const frac = (length - totalLength) / segLen;
  26260. const compIndex = it.getComponentIndex();
  26261. const segIndex = it.getVertexIndex();
  26262. return new LinearLocation(compIndex, segIndex, frac);
  26263. }
  26264. totalLength += segLen;
  26265. }
  26266. it.next();
  26267. }
  26268. return LinearLocation.getEndLocation(this._linearGeom);
  26269. }
  26270. }
  26271. class LinearGeometryBuilder {
  26272. constructor() {
  26273. LinearGeometryBuilder.constructor_.apply(this, arguments);
  26274. }
  26275. static constructor_() {
  26276. this._geomFact = null;
  26277. this._lines = new ArrayList();
  26278. this._coordList = null;
  26279. this._ignoreInvalidLines = false;
  26280. this._fixInvalidLines = false;
  26281. this._lastPt = null;
  26282. const geomFact = arguments[0];
  26283. this._geomFact = geomFact;
  26284. }
  26285. getGeometry() {
  26286. this.endLine();
  26287. return this._geomFact.buildGeometry(this._lines);
  26288. }
  26289. getLastCoordinate() {
  26290. return this._lastPt;
  26291. }
  26292. endLine() {
  26293. if (this._coordList === null) return null;
  26294. if (this._ignoreInvalidLines && this._coordList.size() < 2) {
  26295. this._coordList = null;
  26296. return null;
  26297. }
  26298. const rawPts = this._coordList.toCoordinateArray();
  26299. let pts = rawPts;
  26300. if (this._fixInvalidLines) pts = this.validCoordinateSequence(rawPts);
  26301. this._coordList = null;
  26302. let line = null;
  26303. try {
  26304. line = this._geomFact.createLineString(pts);
  26305. } catch (ex) {
  26306. if (ex instanceof IllegalArgumentException) {
  26307. if (!this._ignoreInvalidLines) throw ex;
  26308. } else {
  26309. throw ex;
  26310. }
  26311. } finally {}
  26312. if (line !== null) this._lines.add(line);
  26313. }
  26314. setFixInvalidLines(fixInvalidLines) {
  26315. this._fixInvalidLines = fixInvalidLines;
  26316. }
  26317. add() {
  26318. if (arguments.length === 1) {
  26319. const pt = arguments[0];
  26320. this.add(pt, true);
  26321. } else if (arguments.length === 2) {
  26322. const pt = arguments[0],
  26323. allowRepeatedPoints = arguments[1];
  26324. if (this._coordList === null) this._coordList = new CoordinateList();
  26325. this._coordList.add(pt, allowRepeatedPoints);
  26326. this._lastPt = pt;
  26327. }
  26328. }
  26329. setIgnoreInvalidLines(ignoreInvalidLines) {
  26330. this._ignoreInvalidLines = ignoreInvalidLines;
  26331. }
  26332. validCoordinateSequence(pts) {
  26333. if (pts.length >= 2) return pts;
  26334. const validPts = [pts[0], pts[0]];
  26335. return validPts;
  26336. }
  26337. }
  26338. class ExtractLineByLocation {
  26339. constructor() {
  26340. ExtractLineByLocation.constructor_.apply(this, arguments);
  26341. }
  26342. static constructor_() {
  26343. this._line = null;
  26344. const line = arguments[0];
  26345. this._line = line;
  26346. }
  26347. static extract(line, start, end) {
  26348. const ls = new ExtractLineByLocation(line);
  26349. return ls.extract(start, end);
  26350. }
  26351. computeLinear(start, end) {
  26352. const builder = new LinearGeometryBuilder(this._line.getFactory());
  26353. builder.setFixInvalidLines(true);
  26354. if (!start.isVertex()) builder.add(start.getCoordinate(this._line));
  26355. for (let it = new LinearIterator(this._line, start); it.hasNext(); it.next()) {
  26356. if (end.compareLocationValues(it.getComponentIndex(), it.getVertexIndex(), 0.0) < 0) break;
  26357. const pt = it.getSegmentStart();
  26358. builder.add(pt);
  26359. if (it.isEndOfLine()) builder.endLine();
  26360. }
  26361. if (!end.isVertex()) builder.add(end.getCoordinate(this._line));
  26362. return builder.getGeometry();
  26363. }
  26364. computeLine(start, end) {
  26365. const coordinates = this._line.getCoordinates();
  26366. const newCoordinates = new CoordinateList();
  26367. let startSegmentIndex = start.getSegmentIndex();
  26368. if (start.getSegmentFraction() > 0.0) startSegmentIndex += 1;
  26369. let lastSegmentIndex = end.getSegmentIndex();
  26370. if (end.getSegmentFraction() === 1.0) lastSegmentIndex += 1;
  26371. if (lastSegmentIndex >= coordinates.length) lastSegmentIndex = coordinates.length - 1;
  26372. if (!start.isVertex()) newCoordinates.add(start.getCoordinate(this._line));
  26373. for (let i = startSegmentIndex; i <= lastSegmentIndex; i++) newCoordinates.add(coordinates[i]);
  26374. if (!end.isVertex()) newCoordinates.add(end.getCoordinate(this._line));
  26375. if (newCoordinates.size() <= 0) newCoordinates.add(start.getCoordinate(this._line));
  26376. let newCoordinateArray = newCoordinates.toCoordinateArray();
  26377. if (newCoordinateArray.length <= 1) newCoordinateArray = [newCoordinateArray[0], newCoordinateArray[0]];
  26378. return this._line.getFactory().createLineString(newCoordinateArray);
  26379. }
  26380. extract(start, end) {
  26381. if (end.compareTo(start) < 0) return this.reverse(this.computeLinear(end, start));
  26382. return this.computeLinear(start, end);
  26383. }
  26384. reverse(linear) {
  26385. if (hasInterface(linear, Lineal)) return linear.reverse();
  26386. Assert.shouldNeverReachHere('non-linear geometry encountered');
  26387. return null;
  26388. }
  26389. }
  26390. class LengthIndexedLine {
  26391. constructor() {
  26392. LengthIndexedLine.constructor_.apply(this, arguments);
  26393. }
  26394. static constructor_() {
  26395. this._linearGeom = null;
  26396. const linearGeom = arguments[0];
  26397. this._linearGeom = linearGeom;
  26398. }
  26399. clampIndex(index) {
  26400. const posIndex = this.positiveIndex(index);
  26401. const startIndex = this.getStartIndex();
  26402. if (posIndex < startIndex) return startIndex;
  26403. const endIndex = this.getEndIndex();
  26404. if (posIndex > endIndex) return endIndex;
  26405. return posIndex;
  26406. }
  26407. locationOf() {
  26408. if (arguments.length === 1) {
  26409. const index = arguments[0];
  26410. return LengthLocationMap.getLocation(this._linearGeom, index);
  26411. } else if (arguments.length === 2) {
  26412. const index = arguments[0],
  26413. resolveLower = arguments[1];
  26414. return LengthLocationMap.getLocation(this._linearGeom, index, resolveLower);
  26415. }
  26416. }
  26417. project(pt) {
  26418. return LengthIndexOfPoint.indexOf(this._linearGeom, pt);
  26419. }
  26420. positiveIndex(index) {
  26421. if (index >= 0.0) return index;
  26422. return this._linearGeom.getLength() + index;
  26423. }
  26424. extractPoint() {
  26425. if (arguments.length === 1) {
  26426. const index = arguments[0];
  26427. const loc = LengthLocationMap.getLocation(this._linearGeom, index);
  26428. return loc.getCoordinate(this._linearGeom);
  26429. } else if (arguments.length === 2) {
  26430. const index = arguments[0],
  26431. offsetDistance = arguments[1];
  26432. const loc = LengthLocationMap.getLocation(this._linearGeom, index);
  26433. const locLow = loc.toLowest(this._linearGeom);
  26434. return locLow.getSegment(this._linearGeom).pointAlongOffset(locLow.getSegmentFraction(), offsetDistance);
  26435. }
  26436. }
  26437. isValidIndex(index) {
  26438. return index >= this.getStartIndex() && index <= this.getEndIndex();
  26439. }
  26440. getEndIndex() {
  26441. return this._linearGeom.getLength();
  26442. }
  26443. getStartIndex() {
  26444. return 0.0;
  26445. }
  26446. indexOfAfter(pt, minIndex) {
  26447. return LengthIndexOfPoint.indexOfAfter(this._linearGeom, pt, minIndex);
  26448. }
  26449. extractLine(startIndex, endIndex) {
  26450. const startIndex2 = this.clampIndex(startIndex);
  26451. const endIndex2 = this.clampIndex(endIndex);
  26452. const resolveStartLower = startIndex2 === endIndex2;
  26453. const startLoc = this.locationOf(startIndex2, resolveStartLower);
  26454. const endLoc = this.locationOf(endIndex2);
  26455. return ExtractLineByLocation.extract(this._linearGeom, startLoc, endLoc);
  26456. }
  26457. indexOf(pt) {
  26458. return LengthIndexOfPoint.indexOf(this._linearGeom, pt);
  26459. }
  26460. indicesOf(subLine) {
  26461. const locIndex = LocationIndexOfLine.indicesOf(this._linearGeom, subLine);
  26462. const index = [LengthLocationMap.getLength(this._linearGeom, locIndex[0]), LengthLocationMap.getLength(this._linearGeom, locIndex[1])];
  26463. return index;
  26464. }
  26465. }
  26466. class LocationIndexedLine {
  26467. constructor() {
  26468. LocationIndexedLine.constructor_.apply(this, arguments);
  26469. }
  26470. static constructor_() {
  26471. this._linearGeom = null;
  26472. const linearGeom = arguments[0];
  26473. this._linearGeom = linearGeom;
  26474. this.checkGeometryType();
  26475. }
  26476. clampIndex(index) {
  26477. const loc = index.copy();
  26478. loc.clamp(this._linearGeom);
  26479. return loc;
  26480. }
  26481. project(pt) {
  26482. return LocationIndexOfPoint.indexOf(this._linearGeom, pt);
  26483. }
  26484. checkGeometryType() {
  26485. if (!(this._linearGeom instanceof LineString || this._linearGeom instanceof MultiLineString)) throw new IllegalArgumentException('Input geometry must be linear');
  26486. }
  26487. extractPoint() {
  26488. if (arguments.length === 1) {
  26489. const index = arguments[0];
  26490. return index.getCoordinate(this._linearGeom);
  26491. } else if (arguments.length === 2) {
  26492. const index = arguments[0],
  26493. offsetDistance = arguments[1];
  26494. const indexLow = index.toLowest(this._linearGeom);
  26495. return indexLow.getSegment(this._linearGeom).pointAlongOffset(indexLow.getSegmentFraction(), offsetDistance);
  26496. }
  26497. }
  26498. isValidIndex(index) {
  26499. return index.isValid(this._linearGeom);
  26500. }
  26501. getEndIndex() {
  26502. return LinearLocation.getEndLocation(this._linearGeom);
  26503. }
  26504. getStartIndex() {
  26505. return new LinearLocation();
  26506. }
  26507. indexOfAfter(pt, minIndex) {
  26508. return LocationIndexOfPoint.indexOfAfter(this._linearGeom, pt, minIndex);
  26509. }
  26510. extractLine(startIndex, endIndex) {
  26511. return ExtractLineByLocation.extract(this._linearGeom, startIndex, endIndex);
  26512. }
  26513. indexOf(pt) {
  26514. return LocationIndexOfPoint.indexOf(this._linearGeom, pt);
  26515. }
  26516. indicesOf(subLine) {
  26517. return LocationIndexOfLine.indicesOf(this._linearGeom, subLine);
  26518. }
  26519. }
  26520. var linearref = /*#__PURE__*/Object.freeze({
  26521. __proto__: null,
  26522. LengthIndexedLine: LengthIndexedLine,
  26523. LengthLocationMap: LengthLocationMap,
  26524. LinearGeometryBuilder: LinearGeometryBuilder,
  26525. LinearIterator: LinearIterator,
  26526. LinearLocation: LinearLocation,
  26527. LocationIndexedLine: LocationIndexedLine
  26528. });
  26529. class CollectionUtil {
  26530. static transform(coll, func) {
  26531. const result = new ArrayList();
  26532. for (let i = coll.iterator(); i.hasNext();) result.add(func.execute(i.next()));
  26533. return result;
  26534. }
  26535. static select(collection, func) {
  26536. const result = new ArrayList();
  26537. for (let i = collection.iterator(); i.hasNext();) {
  26538. const item = i.next();
  26539. if (Boolean.TRUE.equals(func.execute(item))) result.add(item);
  26540. }
  26541. return result;
  26542. }
  26543. static apply(coll, func) {
  26544. for (let i = coll.iterator(); i.hasNext();) func.execute(i.next());
  26545. }
  26546. }
  26547. function Function() {}
  26548. CollectionUtil.Function = Function;
  26549. class CoordinateArrayFilter {
  26550. constructor() {
  26551. CoordinateArrayFilter.constructor_.apply(this, arguments);
  26552. }
  26553. static constructor_() {
  26554. this.pts = null;
  26555. this.n = 0;
  26556. const size = arguments[0];
  26557. this.pts = new Array(size).fill(null);
  26558. }
  26559. filter(coord) {
  26560. this.pts[this.n++] = coord;
  26561. }
  26562. getCoordinates() {
  26563. return this.pts;
  26564. }
  26565. get interfaces_() {
  26566. return [CoordinateFilter];
  26567. }
  26568. }
  26569. class CoordinateCountFilter {
  26570. constructor() {
  26571. CoordinateCountFilter.constructor_.apply(this, arguments);
  26572. }
  26573. static constructor_() {
  26574. this._n = 0;
  26575. }
  26576. filter(coord) {
  26577. this._n++;
  26578. }
  26579. getCount() {
  26580. return this._n;
  26581. }
  26582. get interfaces_() {
  26583. return [CoordinateFilter];
  26584. }
  26585. }
  26586. class ObjectCounter {
  26587. constructor() {
  26588. ObjectCounter.constructor_.apply(this, arguments);
  26589. }
  26590. static constructor_() {
  26591. this._counts = new HashMap();
  26592. }
  26593. count(o) {
  26594. const counter = this._counts.get(o);
  26595. if (counter === null) return 0;else return counter.count();
  26596. }
  26597. add(o) {
  26598. const counter = this._counts.get(o);
  26599. if (counter === null) this._counts.put(o, new Counter(1));else counter.increment();
  26600. }
  26601. }
  26602. class Counter {
  26603. constructor() {
  26604. Counter.constructor_.apply(this, arguments);
  26605. }
  26606. static constructor_() {
  26607. this.count = 0;
  26608. if (arguments.length === 0) ; else if (arguments.length === 1) {
  26609. const count = arguments[0];
  26610. this.count = count;
  26611. }
  26612. }
  26613. count() {
  26614. return this.count;
  26615. }
  26616. increment() {
  26617. this.count++;
  26618. }
  26619. }
  26620. ObjectCounter.Counter = Counter;
  26621. function PrintStream() {}
  26622. function StringReader() {}
  26623. function ByteArrayOutputStream() {}
  26624. class IOException extends Exception {}
  26625. function LineNumberReader() {}
  26626. class StringUtil {
  26627. static chars(c, n) {
  26628. const ch = new Array(n).fill(null);
  26629. for (let i = 0; i < n; i++) ch[i] = c;
  26630. return new String(ch);
  26631. }
  26632. static getStackTrace() {
  26633. if (arguments.length === 1) {
  26634. const t = arguments[0];
  26635. const os = new ByteArrayOutputStream();
  26636. const ps = new PrintStream(os);
  26637. t.printStackTrace(ps);
  26638. return os.toString();
  26639. } else if (arguments.length === 2) {
  26640. const t = arguments[0],
  26641. depth = arguments[1];
  26642. let stackTrace = '';
  26643. const stringReader = new StringReader(StringUtil.getStackTrace(t));
  26644. const lineNumberReader = new LineNumberReader(stringReader);
  26645. for (let i = 0; i < depth; i++) try {
  26646. stackTrace += lineNumberReader.readLine() + StringUtil.NEWLINE;
  26647. } catch (e) {
  26648. if (e instanceof IOException) Assert.shouldNeverReachHere();else throw e;
  26649. } finally {}
  26650. return stackTrace;
  26651. }
  26652. }
  26653. static spaces(n) {
  26654. return StringUtil.chars(' ', n);
  26655. }
  26656. static split(s, separator) {
  26657. const separatorlen = separator.length;
  26658. const tokenList = new ArrayList();
  26659. let tmpString = '' + s;
  26660. let pos = tmpString.indexOf(separator);
  26661. while (pos >= 0) {
  26662. const token = tmpString.substring(0, pos);
  26663. tokenList.add(token);
  26664. tmpString = tmpString.substring(pos + separatorlen);
  26665. pos = tmpString.indexOf(separator);
  26666. }
  26667. if (tmpString.length > 0) tokenList.add(tmpString);
  26668. const res = new Array(tokenList.size()).fill(null);
  26669. for (let i = 0; i < res.length; i++) res[i] = tokenList.get(i);
  26670. return res;
  26671. }
  26672. }
  26673. StringUtil.NEWLINE = System.getProperty('line.separator');
  26674. var util = /*#__PURE__*/Object.freeze({
  26675. __proto__: null,
  26676. CollectionUtil: CollectionUtil,
  26677. CoordinateArrayFilter: CoordinateArrayFilter,
  26678. CoordinateCountFilter: CoordinateCountFilter,
  26679. GeometricShapeFactory: GeometricShapeFactory,
  26680. NumberUtil: NumberUtil,
  26681. ObjectCounter: ObjectCounter,
  26682. PriorityQueue: PriorityQueue,
  26683. StringUtil: StringUtil,
  26684. UniqueCoordinateArrayFilter: UniqueCoordinateArrayFilter
  26685. });
  26686. const version = '2.7.1 (16652a2)';
  26687. export { algorithm, densify, dissolve, geom, geomgraph, index, io, linearref, noding, operation, precision, simplify, triangulate, util, version };
  26688. //# sourceMappingURL=jsts.es6.js.map